Spring MVC中的常用注解

@RequestMapping - 请求映射
作用:最基础的请求映射注解,可以用在类或方法上,用来匹配 URL、请求方法 (GET/POST 等)、请求头、参数等。

核心属性:

  • value/path:指定匹配的 URL 路径(最常用)
  • method:指定匹配的 HTTP 方法(如 RequestMethod.GET/POST)
  • params:指定必须包含的请求参数

举例:

1
2
3
4
5
6
7
8
9
10
// 类级别:所有方法的URL都以/user开头
@RequestMapping("/user")
@Controller
public class UserController {
// 方法级别:匹配 GET /user/info 请求
@RequestMapping(value = "/info", method = RequestMethod.GET)
public String getUserInfo() {
return "userInfo";
}
}

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
作用:是@RequestMapping的简化版,专门匹配特定 HTTP 方法,无需手动指定method属性,更符合 RESTful 风格。

对应关系:

  • @GetMapping = @RequestMapping(method = RequestMethod.GET)
  • @PostMapping = @RequestMapping(method = RequestMethod.POST)
  • @PutMapping/@DeleteMapping/@PatchMapping同理(分别对应 PUT/DELETE/PATCH 方法)

注意: 形象对比:PUT vs PATCH

  • PUT (替换模式): 你把整辆车拖到修理厂,说:“给我换一辆一模一样的新车,但发动机要好的。”
    • 结果:修理厂直接报废旧车,给你一台全新的。如果你忘了说要有天窗,那新车可能就没有天窗。
  • PATCH (修补模式): 你把车开过去,指着发动机说:“就把这个零件换了。”
    • 结果:车还是原来的车,只有发动机变了,轮胎、音响、天窗都原封不动。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("/user")
public class UserController {
// 替代 @RequestMapping(value = "/{id}", method = RequestMethod.GET)
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}

// 替代 @RequestMapping(value = "", method = RequestMethod.POST)
@PostMapping
public void addUser(@RequestBody User user) {
userService.add(user);
}
}

@RequestParam - 获取请求参数
作用:专门用于提取URL 中?后面的键值对参数(Query String),比如 /user?name=张三&age=20 中的 name 和 age,并绑定到方法参数上。

完整用法与参数

参数名 作用 默认值
value/name 指定要绑定的请求参数名(如果参数名和变量名一致,可省略)
required 是否为必传参数,true表示必须传,否则抛MissingServletRequestParameterException true
defaultValue 参数非必传时的默认值(设置后required会自动变为false)

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:参数名与变量名一致,简化写法
@GetMapping("/search")
public String searchUser(@RequestParam String name) {
return "查询用户:" + name; // 访问 /user/search?name=张三 → 返回 "查询用户:张三"
}

// 场景2:参数名与变量名不一致(如前端传username,后端用name接收)
@GetMapping("/search2")
public String searchUser2(@RequestParam("username") String name) {
return "查询用户:" + name; // 访问 /user/search2?username=李四 → 返回 "查询用户:李四"
}

// 场景3:非必传参数 + 默认值
@GetMapping("/search3")
public String searchUser3(
@RequestParam(required = false, defaultValue = "未知") String name,
@RequestParam(defaultValue = "18") Integer age) { // 设置defaultValue后,required自动为false
return "用户:" + name + ",年龄:" + age;
// 访问 /user/search3 → 返回 "用户:未知,年龄:18"
// 访问 /user/search3?name=王五 → 返回 "用户:王五,年龄:18"
}
}

@PathVariable - 获取路径变量
作用:提取URL 路径中的动态变量(RESTful 风格常用),比如 /user/123 中的 123、/order/2024/01 中的 2024 和 01,需要在 URL 中用{变量名}声明。

完整用法与参数

参数名 作用 默认值
value/name 指定 URL 中声明的变量名(如果变量名和参数名一致,可省略)
required 是否为必传变量(路径中声明了就必须传,否则 404) true

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:单个路径变量
@GetMapping("/{id}")
public String getUserById(@PathVariable Long id) {
return "获取用户ID:" + id; // 访问 /user/100 → 返回 "获取用户ID:100"
}

// 场景2:多个路径变量 + 变量名不一致
@GetMapping("/{userId}/order/{orderId}")
public String getUserOrder(
@PathVariable("userId") Long uid,
@PathVariable("orderId") Long oid) {
return "用户ID:" + uid + ",订单ID:" + oid;
// 访问 /user/100/order/200 → 返回 "用户ID:100,订单ID:200"
}

// 场景3:非必传路径变量(Spring 5.3+支持,需配合ant风格路径)
@GetMapping("/{id}/info?") // ?表示该段路径可选
public String getUserInfo(@PathVariable(required = false) Long id) {
return id == null ? "获取所有用户信息" : "获取用户" + id + "的信息";
// 访问 /user/info → 返回 "获取所有用户信息"
// 访问 /user/100/info → 返回 "获取用户100的信息"
}
}

@RequestBody - 获取请求体
作用:读取HTTP 请求体中的数据(通常是 JSON/XML 格式),并自动转换为 Java 对象(依赖 Jackson 等 JSON 解析库),是 POST/PUT/PATCH 请求传递复杂数据的核心注解。

关键特性

  • 只能用在有请求体的 HTTP 方法(POST/PUT/PATCH),GET 请求无请求体,使用会抛HttpMessageNotReadableException。
  • 一个方法只能有一个@RequestBody参数(请求体只有一个)。
  • 前端需设置请求头Content-Type: application/json(JSON 格式),否则解析失败。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 先定义User实体类
public class User {
private Long id;
private String name;
private Integer age;
// 必须有无参构造器(Spring反射创建对象用)
// getter/setter/toString 省略
}

@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:接收JSON请求体,转换为User对象
@PostMapping("/add")
public String addUser(@RequestBody User user) {
return "新增用户:" + user.toString();
// 前端POST请求体(JSON):{"id":1,"name":"张三","age":20}
// 后端返回:"新增用户:User{id=1, name='张三', age=20}"
}

// 场景2:接收简单JSON(如字符串、数字)
@PutMapping("/{id}/name")
public String updateUserName(
@PathVariable Long id,
@RequestBody String newName) {
return "用户" + id + "的新名称:" + newName;
// 前端PUT请求体:"李四"
// 访问 /user/1/name → 返回 "用户1的新名称:李四"
}
}

@ResponseBody - 响应体
作用:单独用在方法上,将方法返回值转为 JSON/XML 作为响应体(如果类用了@RestController,则无需加)。

@RequestHeader - 获取请求头
作用:提取HTTP 请求头中的指定字段值,比如 Token(Authorization)、Content-Type、User-Agent 等。

完整用法与参数

参数名 作用 默认值
value/name 指定请求头字段名
required 是否必传 true
defaultValue 默认值(设置后required自动为 false)

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:获取Token(Authorization请求头)
@GetMapping("/info")
public String getUserInfoByToken(
@RequestHeader("Authorization") String token) {
return "验证Token:" + token;
// 前端请求头:Authorization: Bearer 123456
// 后端返回:"验证Token:Bearer 123456"
}

// 场景2:获取Content-Type + 非必传请求头
@PostMapping("/test")
public String testHeader(
@RequestHeader("Content-Type") String contentType,
@RequestHeader(required = false, defaultValue = "unknown") String User_Agent) {
return "Content-Type:" + contentType + ",User-Agent:" + User_Agent;
// 前端请求头含Content-Type: application/json,无User-Agent
// 后端返回:"Content-Type:application/json,User-Agent:unknown"
}
}

@CookieValue - 获取 Cookie
作用:提取请求中携带的 Cookie指定键的值,比如 JSESSIONID(会话 ID)、用户登录态 Cookie 等。

完整用法与参数

参数名 作用 默认值
value/name 指定Cookie键名
required 是否必传 true
defaultValue 默认值(设置后required自动为 false)

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:获取JSESSIONID Cookie
@GetMapping("/session")
public String getSessionId(
@CookieValue("JSESSIONID") String sessionId) {
return "会话ID:" + sessionId;
// 前端请求携带Cookie:JSESSIONID=ABC123456
// 后端返回:"会话ID:ABC123456"
}

// 场景2:非必传Cookie + 默认值
@GetMapping("/login")
public String checkLogin(
@CookieValue(required = false, defaultValue = "未登录") String loginToken) {
return "登录状态:" + loginToken;
// 前端无loginToken Cookie → 返回 "登录状态:未登录"
// 前端有loginToken=xyz → 返回 "登录状态:xyz"
}
}

@ModelAttribute- 模型属性
作用:将多个请求参数(Query String 或表单参数)自动绑定到 JavaBean 对象中,替代多个@RequestParam的繁琐写法,适合参数较多的场景。

关键特性

  • 支持 GET 请求的 Query String、POST 请求的表单参数(Content-Type: application/x-www-form-urlencoded)。
  • 自动完成类型转换(如前端传age=20,后端实体类Integer age会自动转换)。
  • 可省略注解(Spring 会自动将符合条件的参数绑定到 JavaBean),但显式加@ModelAttribute更清晰。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 复用之前的User实体类(id/name/age)
@RestController
@RequestMapping("/user")
public class UserController {
// 场景1:绑定Query String到User对象
@GetMapping("/query")
public String queryUser(@ModelAttribute User user) {
return "查询条件:" + user.toString();
// 访问 /user/query?id=1&name=张三&age=20
// 后端返回:"查询条件:User{id=1, name='张三', age=20}"
}

// 场景2:绑定表单参数到User对象(POST表单)
@PostMapping("/addForm")
public String addUserByForm(@ModelAttribute User user) {
return "表单新增用户:" + user.toString();
// 前端POST表单(Content-Type: application/x-www-form-urlencoded):
// id=2&name=李四&age=25
// 后端返回:"表单新增用户:User{id=2, name='李四', age=25}"
}

// 场景3:省略@ModelAttribute(效果相同)
@GetMapping("/query2")
public String queryUser2(User user) {
return "查询条件2:" + user.toString();
}
}

@RestController
作用:@Controller + @ResponseBody 的组合注解。

  • 标记类为控制器,同时所有方法的返回值都会直接作为响应体(JSON/XML)返回,而非跳转页面。

举例:

1
2
3
4
5
6
7
8
9
10
// 替代 @Controller + 每个方法加@ResponseBody
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// 返回的User对象会自动转为JSON响应给前端
return new User(id, "张三", 20);
}
}

@ResponseStatus - 响应状态码
作用:指定响应的 HTTP 状态码(如 200 成功、201 创建、404 未找到、500 服务器错误)。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@ResponseStatus(HttpStatus.NOT_FOUND) // 只有抛出这个异常时,才返回 404
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}

@GetMapping("/{id}")
// 这里不需要加 @ResponseStatus,正常查询应该返回 200 OK
public User getUser(@PathVariable Long id) {
User user = userService.getById(id);
if (user == null) {
// 抛出自定义异常,此时 @ResponseStatus 在异常类上生效,返回 404
throw new UserNotFoundException("用户不存在");
}
return user;
}

@CrossOrigin - 跨域支持
作用:解决前端跨域请求问题(如前端域名http://localhost:8080访问后端http://localhost:9090)。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
// 允许所有域名跨域
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
// 也可以单独加在方法上,指定允许的域名、方法等
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getById(id);
}
}

@ExceptionHandler - 异常处理
作用:自定义异常处理,捕获控制器中的异常,返回友好的响应(而非默认的错误页面)。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
if (id <= 0) {
throw new IllegalArgumentException("用户ID不能为负数");
}
return userService.getById(id);
}

// 捕获当前控制器中的IllegalArgumentException异常
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST) // 响应400状态码
public String handleIllegalArgException(IllegalArgumentException e) {
return "参数错误:" + e.getMessage();
}
}

@RestControllerAdvice -全局异常捕获
这个注解其实是一个组合注解,它结合了:

  • @ControllerAdvice:允许你编写全局的、横切多个 Controller 的逻辑(如异常处理)。
  • @ResponseBody:确保该类中所有方法的返回值都会自动转为 JSON 格式。

它的核心功能:@RestControllerAdvice 主要用来做三件事:

  • 全局异常处理 (@ExceptionHandler):捕获所有 Controller 抛出的异常,统一返回错误格式。
  • 全局数据绑定 (@ModelAttribute):在所有 Controller 的每个请求执行前,向 Model 中添加全局属性。
  • 全局数据预处理 (@InitBinder):统一配置日期格式化、参数过滤等

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@RestControllerAdvice
public class GlobalControllerConfig {

// --- 1. 全局异常处理 (@ExceptionHandler) ---
// 无论哪个 Controller 抛出了 UserNotFoundException,都会被这个方法抓住
@ExceptionHandler(UserNotFoundException.class)
public Result<String> handleUserNotFound(UserNotFoundException e) {
// 返回统一的 JSON 格式,而不是报错页面
return Result.error(404, e.getMessage());
}


// --- 2. 全局数据绑定 (@ModelAttribute) ---
// 在所有 Controller 的方法执行前,先把一些公用数据存进去
// 比如:在每一个接口返回的 Map 或 Model 中都带上当前系统版本
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("sysVersion", "V2.0.1");
model.addAttribute("author", "Gemini Team");
}


// --- 3. 全局数据预处理 (@InitBinder) ---
// 场景:前端传来的字符串两端经常有空格,或者日期格式乱七八糟
@InitBinder
public void initBinder(WebDataBinder binder) {
// 示例:自动去掉所有输入字符串的首尾空格
StringTrimmerEditor stringTrimmer = new StringTrimmerEditor(true);
binder.registerCustomEditor(String.class, stringTrimmer);

// 示例:统一规定前端传来的日期字符串格式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
}