Spring MVC 核心注解全解析:从基础到实战
Spring MVC 提供了丰富的注解体系,简化了请求映射、参数绑定、数据共享等核心功能的开发。从 “注解作用→核心属性→实战示例→注意事项” 四个维度,详细解析 @RequestMapping、@PathVariable、@RequestParam 等常用注解的使用方法与设计思想。
@RequestMapping:请求路径映射的核心注解
@RequestMapping 是 Spring MVC 中最基础的注解,用于将 HTTP 请求映射到 Controller 方法,可标注在类或方法上,实现细粒度的路径控制。
1. 核心作用
- 类级别:定义当前 Controller 的基础路径(所有方法路径的前缀);
- 方法级别:定义具体方法的映射路径(与类级别路径组合为完整路径)。
2. 核心属性
| 属性名 |
类型 |
作用描述 |
示例 |
value/path |
String[] |
映射的 URL 路径(支持 Ant 表达式) |
@RequestMapping(path = "/user/list") |
method |
RequestMethod[] |
指定允许的 HTTP 请求方法(如 GET、POST) |
method = {RequestMethod.GET, RequestMethod.POST} |
params |
String[] |
限制请求必须包含指定参数(支持表达式) |
params = {"id", "name!=admin"}(必须有 id 参数,name 不能为 admin) |
headers |
String[] |
限制请求必须包含指定请求头 |
headers = "Content-Type=application/json" |
consumes |
String[] |
限制请求的 Content-Type 类型 |
consumes = "application/json" |
produces |
String[] |
限制响应的 Content-Type 类型 |
produces = "application/json;charset=UTF-8" |
3. Ant 路径匹配规则
@RequestMapping 的 path 属性支持 Ant 风格的路径表达式,灵活匹配 URL:
| 通配符 |
含义 |
示例 |
匹配 URL 示例 |
* |
匹配任意单个字符 |
/user/* |
/user/1、/user/a(不匹配/user/1/2) |
** |
匹配任意路径(含子路径) |
/user/** |
/user/1、/user/1/2、/user/a/b |
? |
匹配单个字符 |
/user/? |
/user/1、/user/a(不匹配/user/12) |
4. 实战示例
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
| import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @RequestMapping("/user") public class UserController {
@RequestMapping(path = "/list", method = RequestMethod.GET) @ResponseBody public String getUserList() { return "用户列表"; }
@RequestMapping("/{id}") @ResponseBody public String getUserById() { return "查询单个用户"; }
@RequestMapping(path = "/save", params = {"name", "age!=0"}) @ResponseBody public String saveUser() { return "保存用户"; } }
|
5. 派生注解(推荐使用)
Spring 4.3+ 提供了 @RequestMapping 的派生注解,简化常用请求方法的配置:
| 派生注解 |
对应 HTTP 方法 |
等效于 |
@GetMapping |
GET |
@RequestMapping(method = RequestMethod.GET) |
@PostMapping |
POST |
@RequestMapping(method = RequestMethod.POST) |
@PutMapping |
PUT |
@RequestMapping(method = RequestMethod.PUT) |
@DeleteMapping |
DELETE |
@RequestMapping(method = RequestMethod.DELETE) |
示例:
1 2 3 4 5 6
| @GetMapping("/list") @ResponseBody public String getUserList() { return "用户列表"; }
|
@PathVariable:REST 风格的 URL 参数绑定
@PathVariable 用于从 URL 路径中提取参数,适用于 RESTful 风格的 API 设计(如 /user/1 中的 1 表示用户 ID)。
1. 核心作用
将 URL 中的模板变量(如 {id})绑定到方法参数,实现路径参数的获取。
2. 核心属性
| 属性名 |
类型 |
作用描述 |
value |
String |
模板变量名(与 URL 中的 {name} 对应) |
required |
boolean |
是否必填(默认 true,缺失会抛异常) |
3. 实战示例
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
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/rest/user") public class RestUserController {
@GetMapping("/{id}") public String getUser(@PathVariable("id") Integer userId) { return "查询用户 ID:" + userId; }
@GetMapping("/{id}/detail/{type}") public String getUserDetail( @PathVariable Integer id, // 变量名与 {id} 一致,可省略 value @PathVariable("type") String detailType) { return "用户 ID:" + id + ",详情类型:" + detailType; }
@GetMapping("/optional/{name:.+}") public String getOptionalParam( @PathVariable(required = false) String name) { return "可选参数:" + (name == null ? "未提供" : name); } }
|
注意:
- 若路径参数包含特殊字符(如
.、/),需通过正则表达式显式匹配(如 {name:.+} 匹配含 . 的字符串);
- 参数名与路径变量名一致时,可省略
@PathVariable 的 value 属性。
@RequestParam:请求参数绑定(查询字符串 / 表单)
@RequestParam 用于获取 HTTP 请求中的参数(包括 URL 查询字符串和表单提交的参数),适用于 ?id=1&name=张三 形式的参数。
1. 核心作用
将请求参数(键值对)绑定到方法参数,支持设置默认值、是否必填等。
2. 核心属性
| 属性名 |
类型 |
作用描述 |
value/name |
String |
请求参数名(与前端传递的参数键对应) |
required |
boolean |
是否必填(默认 true,缺失会抛 MissingServletRequestParameterException) |
defaultValue |
String |
默认值(若参数缺失则使用该值,required 自动变为 false) |
3. 实战示例
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
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/param") public class ParamController {
@GetMapping("/user") public String getUser( @RequestParam("id") Integer userId, @RequestParam String name) { return "ID:" + userId + ",姓名:" + name; }
@GetMapping("/list") public String getList( @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) { return "第 " + page + " 页,每页 " + size + " 条"; }
@GetMapping("/search") public String search( @RequestParam(required = false) String keyword) { return "搜索关键词:" + (keyword == null ? "无" : keyword); } }
|
4. 与 @PathVariable 的区别
| 维度 |
@PathVariable |
@RequestParam |
| 参数位置 |
URL 路径中(如 /user/{id}) |
URL 查询字符串或表单(如 ?id=1) |
| 适用场景 |
RESTful API 路径参数 |
传统表单提交、查询参数 |
| 示例 |
/user/1 → 获取 id=1 |
/user?id=1 → 获取 id=1 |
@RequestHeader 用于获取 HTTP 请求头中的信息(如 User-Agent、Content-Type、Cookie 等)。
1. 核心作用
绑定请求头中的键值对到方法参数,常用于获取客户端信息、认证令牌等。
2. 核心属性
与 @RequestParam 一致:value(请求头名)、required(是否必填)、defaultValue(默认值)。
3. 实战示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/header") public class HeaderController {
@GetMapping("/info") public String getHeaderInfo( // 获取 User-Agent(客户端浏览器/设备信息) @RequestHeader("User-Agent") String userAgent, // 获取 Content-Type(请求体类型) @RequestHeader("Content-Type") String contentType, // 获取自定义请求头(如前端传递的 Token) @RequestHeader(value = "X-Token", required = false) String token) { return "User-Agent:" + userAgent + "\n" + "Content-Type:" + contentType + "\n" + "X-Token:" + (token == null ? "未传递" : token); } }
|
@CookieValue:获取 Cookie 值
@CookieValue 用于获取请求中携带的 Cookie 值(如 JSESSIONID、自定义 Cookie)。
1. 核心作用
直接绑定 Cookie 的值到方法参数,无需手动通过 HttpServletRequest 获取。
2. 核心属性
与 @RequestParam 一致:value(Cookie 名)、required、defaultValue。
3. 实战示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/cookie") public class CookieController {
@GetMapping("/info") public String getCookieInfo( // 获取 JSESSIONID(Tomcat 自动生成的会话 ID) @CookieValue("JSESSIONID") String sessionId, // 获取自定义 Cookie(如前端设置的 theme=dark) @CookieValue(value = "theme", defaultValue = "light") String theme) { return "JSESSIONID:" + sessionId + "\n" + "主题:" + theme; } }
|
@SessionAttributes 与 @SessionAttribute:会话域数据操作
这两个注解用于处理会话域(HttpSession)中的数据,实现跨请求的数据共享(如用户登录信息)。
1. @SessionAttributes:类级别,将模型数据存入 Session
- 作用:标注在 Controller 类上,指定模型(Model)中的哪些属性需要同步到 HttpSession 中;
- 核心属性:
value(属性名数组)、types(属性类型数组)。
2. @SessionAttribute:参数级别,从 Session 中获取数据
- 作用:标注在方法参数上,从 HttpSession 中获取指定属性的值;
- 核心属性:
value(Session 属性名)、required(是否必填)。
3. 实战示例
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 36 37 38 39 40 41 42 43
| import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.SessionAttribute; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.support.SessionStatus;
@Controller @RequestMapping("/session") @SessionAttributes(value = {"userName", "role"}) public class SessionController {
@GetMapping("/login") public String login(Model model) { model.addAttribute("userName", "张三"); model.addAttribute("role", "admin"); return "loginSuccess"; }
@GetMapping("/info") public String getSessionInfo( Model model, // 方式1:从 Model 中获取(已同步 Session 数据) HttpSession session, // 方式2:通过 HttpSession 获取 @SessionAttribute("userName") String userName, // 方式3:通过 @SessionAttribute 获取 @SessionAttribute(value = "role", required = false) String role) { System.out.println("Model 中的 userName:" + model.getAttribute("userName")); System.out.println("HttpSession 中的 role:" + session.getAttribute("role")); System.out.println("@SessionAttribute 获取的 userName:" + userName); return "sessionInfo"; }
@GetMapping("/logout") public String logout(SessionStatus status) { status.setComplete(); return "logoutSuccess"; } }
|
注意:
@SessionAttributes 仅作用于当前 Controller 及其子类;
- 清除 Session 数据需通过
SessionStatus.setComplete(),而非 session.invalidate()(后者会销毁整个会话)。
@InitBinder:自定义数据绑定器
@InitBinder 用于注册自定义数据转换器或格式化器,解决 HTTP 请求参数到 Java 对象的类型转换问题(如字符串转日期、自定义枚举转换)。
1. 核心作用
在 @RequestMapping 方法执行前,初始化 WebDataBinder,注册转换器,实现参数的个性化转换。
2. 实战示例:日期格式化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import org.springframework.format.datetime.DateFormatter; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RestController; import java.util.Date;
@RestController @RequestMapping("/binder") public class BinderController {
@InitBinder public void initBinder(WebDataBinder binder) { binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); }
@GetMapping("/date") public String getDate(Date birthday) { return "生日:" + birthday.toLocaleString(); } }
|
扩展:自定义类型转换器(如字符串转枚举)
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
| import org.springframework.core.convert.converter.Converter; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder;
enum GenderEnum { MALE, FEMALE; }
class StringToGenderConverter implements Converter<String, GenderEnum> { @Override public GenderEnum convert(String source) { return "男".equals(source) ? GenderEnum.MALE : GenderEnum.FEMALE; } }
@RestController public class ConverterController { @InitBinder public void initBinder(WebDataBinder binder) { binder.addConverter(new StringToGenderConverter()); }
@GetMapping("/gender") public String getGender(GenderEnum gender) { return "性别枚举:" + gender; } }
|
@ModelAttribute:模型数据预置与参数绑定
@ModelAttribute 是多功能注解,可标注在方法或参数上,分别用于 “预置模型数据” 和 “绑定请求参数到对象”。
1. 标注在方法上:预置模型数据
- 作用:在当前 Controller 的所有
@RequestMapping 方法执行前执行,用于预置模型数据(如全局查询条件、用户信息);
- 执行时机:优先于同 Controller 中的
@RequestMapping 方法。
示例:预置全局数据
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 36 37 38 39 40 41 42 43 44 45
| import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/model") public class ModelAttributeController {
@ModelAttribute public void preHandle(@RequestParam(required = false) String version, Model model) { model.addAttribute("systemVersion", version == null ? "1.0.0" : version); }
@ModelAttribute public User preUser() { return new User("默认用户", 20); }
@ModelAttribute("globalTime") public Long preTime() { return System.currentTimeMillis(); }
@GetMapping("/info") public String getInfo(Model model) { return "系统版本:" + model.getAttribute("systemVersion") + "\n" + "默认用户:" + ((User) model.getAttribute("user")).getName() + "\n" + "时间戳:" + model.getAttribute("globalTime"); }
static class User { private String name; private Integer age; public User(String name, Integer age) { this.name = name; this.age = age; } } }
|
2. 标注在参数上:绑定请求参数到对象
- 作用:将请求参数自动绑定到 Java 对象(如表单提交的用户信息),并将该对象存入模型;
- 核心属性:
value(模型中的键名,默认是对象类型名首字母小写)。
示例:表单参数绑定到对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController;
@RestController @RequestMapping("/user") public class UserFormController {
@PostMapping("/save") public String saveUser(@ModelAttribute("user") User user) { return "保存用户:" + user.getName() + ",年龄:" + user.getAge(); }
static class User { private String name; private Integer age; } }
|
注意:
- 被
@ModelAttribute 标注的参数对象,会自动存入模型,视图可直接访问;
- 若参数对象已通过 “方法级
@ModelAttribute” 预置,则直接复用该对象,而非新建。
注解优先级与使用场景总结
| 注解 |
核心场景 |
优先级 / 执行顺序 |
@RequestMapping |
请求路径映射 |
类级别 → 方法级别 |
@PathVariable |
RESTful 路径参数 |
无(按参数顺序绑定) |
@RequestParam |
查询字符串 / 表单参数 |
无(按参数顺序绑定) |
@InitBinder |
数据绑定器初始化 |
先于 @RequestMapping 方法执行 |
@ModelAttribute |
方法级:预置模型数据;参数级:绑定对象 |
方法级 @ModelAttribute → @InitBinder → @RequestMapping 方法 → 参数级 @ModelAttribute |
@SessionAttributes |
模型数据同步到 Session |
类级别,作用于所有方法 |
最佳实践
- 路径映射:优先使用
@GetMapping、@PostMapping 等派生注解,简化代码;
- 参数获取:REST 风格用
@PathVariable,查询 / 表单参数用 @RequestParam;
- 数据共享:跨请求数据用
@SessionAttributes + @SessionAttribute,单次请求用 Model;
- 数据绑定:复杂类型转换用
@InitBinder 注册转换器,表单对象用 @ModelAttribute 绑定;
- 全局处理:全局数据预置用
@ControllerAdvice + @ModelAttribute,全局异常用 @ControllerAdvice + @ExceptionHandler
v1.3.10