SpringMVC 控制器(`@Controller`)与请求映射(`@RequestMapping`)注解的高级用法

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:路径的灵活匹配

valuepath 属性的作用是相同的,都是用来指定请求的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 的强大之处在于它们可以组合使用,实现复杂的请求映射逻辑。 通过灵活地配置 valuemethodparamsheadersconsumesproduces 等属性,你可以精确地控制哪些请求会被哪些方法处理。

示例:

@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大师! 愿你的代码如诗般优雅,如歌般动听!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注