SpringMVC 控制器与请求映射注解高级用法:一场优雅的HTTP请求交响乐
各位看官,今天咱们不聊风花雪月,聊聊SpringMVC中的“灵魂人物”——控制器(@Controller
)以及它的“御用指挥家”——请求映射(@RequestMapping
注解)。 这俩玩意儿,初看简单,实则蕴藏着无穷的能量。掌握了它们,你就能像一位经验老道的乐队指挥,让各种HTTP请求在你精心设计的代码中翩翩起舞,奏响一曲优雅的交响乐。
废话不多说,咱们直接进入正题,深入剖析 @Controller
和 @RequestMapping
的高级用法,让你彻底搞懂它们,在实际开发中如鱼得水。
1. @Controller
:控制器的灵魂
首先,咱们来认识一下 @Controller
。 简单来说,它就像一个交通枢纽,负责接收用户的请求,处理业务逻辑,然后将结果返回给用户。 它的作用就是告诉Spring: “嘿,哥们儿,这个类是控制器,专门负责处理HTTP请求的!”
简单示例:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "Hello, SpringMVC!";
}
}
在这个例子中,HelloController
类被 @Controller
注解标记, Spring 就会自动识别它,并将其注册为一个Bean。 @RequestMapping("/hello")
注解则表示,当用户访问 /hello
路径时,就会执行 hello()
方法。 @ResponseBody
注解则表示,hello()
方法的返回值将直接作为HTTP响应的内容返回给客户端。
@Controller
的作用:
- 标识作用: 告诉Spring这是一个控制器,需要进行管理。
- Bean注册: 自动将该类注册为Spring的Bean,方便进行依赖注入和其他操作。
- 请求处理: 配合
@RequestMapping
注解,负责处理特定的HTTP请求。
2. @RequestMapping
:请求映射的艺术
@RequestMapping
注解才是真正的“指挥家”,它负责将HTTP请求映射到特定的处理方法上。 就像乐队指挥根据乐谱指挥不同的乐器演奏一样,@RequestMapping
根据不同的请求信息,将请求分发到不同的方法进行处理。
@RequestMapping
的基本属性:
属性 | 说明 | 示例 |
---|---|---|
value/path | 指定请求的URL路径。 | @RequestMapping("/users") |
method | 指定请求的HTTP方法(GET, POST, PUT, DELETE等)。 | @RequestMapping(value = "/users", method = RequestMethod.POST) |
params | 指定请求中必须包含的参数及其值。 | @RequestMapping(value = "/users", params = "id=123") |
headers | 指定请求中必须包含的请求头及其值。 | @RequestMapping(value = "/users", headers = "Content-Type=application/json") |
consumes | 指定处理请求的Content-Type类型。 | @RequestMapping(value = "/users", consumes = "application/json") |
produces | 指定返回的Content-Type类型。 | @RequestMapping(value = "/users", produces = "application/json") |
name | 给RequestMapping命名,方便引用 | @RequestMapping(name = "getUser", value = "/user/{id}") |
接下来,我们逐一深入探讨这些属性的高级用法。
2.1 value/path
:路径的灵活匹配
value
和 path
属性的作用是相同的,都是用来指定请求的URL路径。 它们可以接受单个字符串,也可以接受字符串数组,表示可以匹配多个路径。
示例:
@Controller
@RequestMapping("/users") // 类级别的RequestMapping,所有方法都会继承这个路径
public class UserController {
@RequestMapping("/list") // 完整路径:/users/list
@ResponseBody
public String listUsers() {
return "List of users";
}
@RequestMapping(value = {"/add", "/create"}) // 匹配 /users/add 和 /users/create
@ResponseBody
public String createUser() {
return "Create a user";
}
}
路径变量:
@RequestMapping
还支持使用路径变量,通过 {}
占位符来表示。 路径变量的值可以通过 @PathVariable
注解注入到方法参数中。
示例:
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping("/view/{id}") // 匹配 /users/view/123, /users/view/456 等
@ResponseBody
public String viewUser(@PathVariable("id") Long userId) {
return "User ID: " + userId;
}
@RequestMapping("/update/{id}/{name}")
@ResponseBody
public String updateUser(@PathVariable Long id, @PathVariable String name) { // 参数名与变量名相同,可以省略 @PathVariable("id")
return "Update User ID: " + id + ", Name: " + name;
}
}
正则表达式:
从Spring 5.0开始,@RequestMapping
支持在路径变量中使用正则表达式,可以进行更复杂的路径匹配。
示例:
@Controller
@RequestMapping("/products")
public class ProductController {
@RequestMapping("/view/{productId:[a-zA-Z0-9-]+}") // 匹配 /products/view/product-123, /products/view/abc-456 等
@ResponseBody
public String viewProduct(@PathVariable("productId") String productId) {
return "Product ID: " + productId;
}
}
2.2 method
:HTTP方法的精准控制
method
属性用于指定请求的HTTP方法,常用的有GET、POST、PUT、DELETE等。 通过 method
属性,可以确保只有特定类型的请求才能被处理。
示例:
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "/list", method = RequestMethod.GET) // 只处理GET请求
@ResponseBody
public String listUsers() {
return "List of users";
}
@RequestMapping(value = "/add", method = RequestMethod.POST) // 只处理POST请求
@ResponseBody
public String createUser() {
return "Create a user";
}
@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT) // 只处理PUT请求
@ResponseBody
public String updateUser(@PathVariable Long id) {
return "Update user with ID: " + id;
}
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE) // 只处理DELETE请求
@ResponseBody
public String deleteUser(@PathVariable Long id) {
return "Delete user with ID: " + id;
}
}
快捷注解:
为了简化开发,Spring MVC 提供了针对常用HTTP方法的快捷注解:
@GetMapping
:等价于@RequestMapping(method = RequestMethod.GET)
@PostMapping
:等价于@RequestMapping(method = RequestMethod.POST)
@PutMapping
:等价于@RequestMapping(method = RequestMethod.PUT)
@DeleteMapping
:等价于@RequestMapping(method = RequestMethod.DELETE)
@PatchMapping
:等价于@RequestMapping(method = RequestMethod.PATCH)
使用快捷注解,可以使代码更加简洁易读。
示例:
@Controller
@RequestMapping("/users")
public class UserController {
@GetMapping("/list")
@ResponseBody
public String listUsers() {
return "List of users";
}
@PostMapping("/add")
@ResponseBody
public String createUser() {
return "Create a user";
}
@PutMapping("/update/{id}")
@ResponseBody
public String updateUser(@PathVariable Long id) {
return "Update user with ID: " + id;
}
@DeleteMapping("/delete/{id}")
@ResponseBody
public String deleteUser(@PathVariable Long id) {
return "Delete user with ID: " + id;
}
}
2.3 params
:参数的精细筛选
params
属性用于指定请求中必须包含的参数及其值。 它可以根据参数的存在、值以及值的模式进行匹配。
示例:
@Controller
@RequestMapping("/products")
public class ProductController {
@RequestMapping(value = "/list", params = "category=electronics") // 只处理包含 category=electronics 参数的请求
@ResponseBody
public String listElectronicsProducts() {
return "List of electronics products";
}
@RequestMapping(value = "/list", params = "!category") // 只处理不包含 category 参数的请求
@ResponseBody
public String listAllProducts() {
return "List of all products";
}
@RequestMapping(value = "/view", params = {"id", "name"}) // 只处理同时包含 id 和 name 参数的请求
@ResponseBody
public String viewProduct(String id, String name) {
return "View product with ID: " + id + ", Name: " + name;
}
@RequestMapping(value = "/search", params = "keyword!=null") // 只处理 keyword 参数不为 null 的请求
@ResponseBody
public String searchProducts(String keyword) {
return "Search products with keyword: " + keyword;
}
}
2.4 headers
:请求头的严格把控
headers
属性用于指定请求中必须包含的请求头及其值。 它可以根据请求头的存在、值以及值的模式进行匹配。
示例:
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "/list", headers = "Content-Type=application/json") // 只处理 Content-Type 为 application/json 的请求
@ResponseBody
public String listUsers() {
return "List of users";
}
@RequestMapping(value = "/add", headers = "!X-Requested-With") // 只处理不包含 X-Requested-With 请求头的请求 (非Ajax请求)
@ResponseBody
public String createUser() {
return "Create a user";
}
@RequestMapping(value = "/update/{id}", headers = {"Accept=application/xml", "Content-Type=application/json"}) // 同时满足 Accept 和 Content-Type
@ResponseBody
public String updateUser(@PathVariable Long id) {
return "Update user with ID: " + id;
}
}
2.5 consumes
:请求体的格式限定
consumes
属性用于指定处理请求的Content-Type类型,也就是请求体的内容类型。 它可以限制请求体必须是指定的格式,例如JSON、XML等。
示例:
import org.springframework.web.bind.annotation.RequestBody;
@Controller
@RequestMapping("/products")
public class ProductController {
@RequestMapping(value = "/add", consumes = "application/json") // 只处理 Content-Type 为 application/json 的请求
@ResponseBody
public String createProduct(@RequestBody Product product) {
return "Create product: " + product.getName();
}
@RequestMapping(value = "/update/{id}", consumes = {"application/json", "application/xml"}) // 同时支持 JSON 和 XML
@ResponseBody
public String updateProduct(@PathVariable Long id, @RequestBody Product product) {
return "Update product with ID: " + id + ", Name: " + product.getName();
}
}
class Product {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在这个例子中,@RequestBody
注解用于将请求体的内容绑定到 Product
对象上。 Spring MVC 会根据 consumes
属性指定的 Content-Type 类型,自动将请求体的内容转换为 Product
对象。
2.6 produces
:响应体的格式约定
produces
属性用于指定返回的Content-Type类型,也就是响应体的内容类型。 它可以告诉客户端,服务器返回的是什么格式的数据,例如JSON、XML等。
示例:
@Controller
@RequestMapping("/products")
public class ProductController {
@RequestMapping(value = "/list", produces = "application/json") // 返回 Content-Type 为 application/json 的响应
@ResponseBody
public List<Product> listProducts() {
List<Product> products = new ArrayList<>();
products.add(new Product("Product 1"));
products.add(new Product("Product 2"));
return products;
}
@RequestMapping(value = "/view/{id}", produces = {"application/json", "application/xml"}) // 同时支持 JSON 和 XML
@ResponseBody
public Product viewProduct(@PathVariable Long id) {
return new Product("Product with ID: " + id);
}
}
在这个例子中,如果客户端请求时指定 Accept
请求头为 application/json
,则服务器会返回 JSON 格式的响应;如果客户端指定 Accept
请求头为 application/xml
,则服务器会返回 XML 格式的响应。 Spring MVC 会根据 produces
属性指定的 Content-Type 类型,自动将返回值转换为相应的格式。
2.7 name
:给RequestMapping命名
name
属性用于给RequestMapping命名,方便在其他地方引用,例如在使用UrlBasedViewResolver
时,可以通过name来指定跳转的视图。
示例:
@Controller
public class MyController {
@RequestMapping(name = "showHomePage", value = "/home")
public String home() {
return "home"; // 逻辑视图名,UrlBasedViewResolver会根据name找到对应的视图
}
}
3. 组合使用:奏响完美的交响乐
@Controller
和 @RequestMapping
的强大之处在于它们可以组合使用,实现复杂的请求映射逻辑。 通过灵活地配置 value
、method
、params
、headers
、consumes
和 produces
等属性,你可以精确地控制哪些请求会被哪些方法处理。
示例:
@Controller
@RequestMapping(value = "/api/v1/users",
consumes = "application/json",
produces = "application/json",
headers = "X-API-Version=1.0")
public class UserApiController {
@GetMapping(value = "/{id}", params = "details=true")
@ResponseBody
public User getUserDetails(@PathVariable Long id) {
// ...
return new User();
}
@PostMapping
@ResponseBody
public User createUser(@RequestBody User user) {
// ...
return user;
}
}
在这个例子中,只有满足以下所有条件的请求才能被 UserApiController
处理:
- URL路径以
/api/v1/users
开头 - Content-Type 为
application/json
- Accept 为
application/json
- 请求头中包含
X-API-Version=1.0
getUserDetails
方法只处理满足以下条件的请求:
- URL路径为
/api/v1/users/{id}
- 包含
details=true
参数
createUser
方法只处理满足以下条件的请求:
- URL路径为
/api/v1/users
- HTTP方法为 POST
通过这种组合使用的方式,你可以构建出非常灵活和强大的API接口。
4. 总结
@Controller
和 @RequestMapping
是 Spring MVC 中最核心的两个注解。 掌握它们,你就能轻松地构建出各种各样的Web应用程序。 记住,理解每个属性的含义和用法,灵活地组合它们,才能真正发挥出它们的威力。
希望这篇文章能够帮助你更好地理解 @Controller
和 @RequestMapping
的高级用法。 下次再遇到复杂的请求映射问题时,不妨回过头来看看这篇文章,相信你一定能找到解决方案。
最后,祝大家编程愉快,早日成为Spring MVC大师! 愿你的代码如诗般优雅,如歌般动听!