springmvc注解的使用
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. 实战示例
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;
// 类级别 @RequestMapping:基础路径为 /user
public class UserController {
// 1. 方法级别路径:完整路径为 /user/list(仅允许 GET 请求)
public String getUserList() {
return "用户列表";
}
// 2. 支持 Ant 表达式:匹配 /user/1、/user/2 等
public String getUserById() {
return "查询单个用户";
}
// 3. 限制请求参数:必须包含 name 参数,且 age 不能为 0
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) |
示例:
// 等效于 @RequestMapping(path = "/list", method = RequestMethod.GET)
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. 实战示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
public class RestUserController {
// 1. 单个路径参数:/rest/user/1 → id=1
public String getUser( Integer userId) {
return "查询用户 ID:" + userId;
}
// 2. 多个路径参数:/rest/user/1/detail/info → id=1, type=info
public String getUserDetail(
Integer id, // 变量名与 {id} 一致,可省略 value
String detailType) {
return "用户 ID:" + id + ",详情类型:" + detailType;
}
// 3. 可选参数(required = false):/rest/user/optional 或 /rest/user/optional/123
// .+ 匹配含小数点的字符串(如文件名)
public String getOptionalParam(
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. 实战示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
public class ParamController {
// 1. 基础用法:获取 ?id=1&name=张三
public String getUser(
Integer userId,
String name) { // 参数名与请求参数一致,可省略 value
return "ID:" + userId + ",姓名:" + name;
}
// 2. 可选参数与默认值:?page=2 或 无page参数(默认1)
public String getList(
Integer page,
Integer size) {
return "第 " + page + " 页,每页 " + size + " 条";
}
// 3. 非必填参数:?keyword=java 或 无keyword参数(值为null)
public String search(
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:获取请求头信息
@RequestHeader 用于获取 HTTP 请求头中的信息(如 User-Agent、Content-Type、Cookie 等)。
1. 核心作用
绑定请求头中的键值对到方法参数,常用于获取客户端信息、认证令牌等。
2. 核心属性
与 @RequestParam 一致:value(请求头名)、required(是否必填)、defaultValue(默认值)。
3. 实战示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
public class HeaderController {
public String getHeaderInfo(
// 获取 User-Agent(客户端浏览器/设备信息)
String userAgent,
// 获取 Content-Type(请求体类型)
String contentType,
// 获取自定义请求头(如前端传递的 Token)
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. 实战示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RestController;
public class CookieController {
public String getCookieInfo(
// 获取 JSESSIONID(Tomcat 自动生成的会话 ID)
String sessionId,
// 获取自定义 Cookie(如前端设置的 theme=dark)
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. 实战示例
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;
// 类级别:将模型中 "userName" 和 "role" 属性存入 Session
public class SessionController {
// 1. 向模型添加数据(会被 @SessionAttributes 同步到 Session)
public String login(Model model) {
model.addAttribute("userName", "张三"); // 存入 Model + Session
model.addAttribute("role", "admin"); // 存入 Model + Session
return "loginSuccess";
}
// 2. 从 Session 中获取数据(三种方式)
public String getSessionInfo(
Model model, // 方式1:从 Model 中获取(已同步 Session 数据)
HttpSession session, // 方式2:通过 HttpSession 获取
String userName, // 方式3:通过 获取
String role) {
System.out.println("Model 中的 userName:" + model.getAttribute("userName")); // 张三
System.out.println("HttpSession 中的 role:" + session.getAttribute("role")); // admin
System.out.println("@SessionAttribute 获取的 userName:" + userName); // 张三
return "sessionInfo";
}
// 3. 清除 @SessionAttributes 管理的 Session 数据
public String logout(SessionStatus status) {
status.setComplete(); // 标记会话完成,清除 Session 中的属性
return "logoutSuccess";
}
}
注意:
@SessionAttributes仅作用于当前 Controller 及其子类;- 清除 Session 数据需通过
SessionStatus.setComplete(),而非session.invalidate()(后者会销毁整个会话)。
@InitBinder:自定义数据绑定器
@InitBinder 用于注册自定义数据转换器或格式化器,解决 HTTP 请求参数到 Java 对象的类型转换问题(如字符串转日期、自定义枚举转换)。
1. 核心作用
在 @RequestMapping 方法执行前,初始化 WebDataBinder,注册转换器,实现参数的个性化转换。
2. 实战示例:日期格式化
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;
public class BinderController {
// 1. 注册日期格式化器:将 "yyyy-MM-dd" 字符串转为 Date 对象
public void initBinder(WebDataBinder binder) {
// 自定义日期格式
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
// 2. 接收 Date 参数(自动通过上面的格式化器转换)
public String getDate(Date birthday) { // 请求参数:?birthday=2000-01-01
return "生日:" + birthday.toLocaleString(); // 输出格式化后的日期
}
}
扩展:自定义类型转换器(如字符串转枚举)
import org.springframework.core.convert.converter.Converter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
// 自定义转换器:String → GenderEnum(枚举)
enum GenderEnum {
MALE, FEMALE;
}
class StringToGenderConverter implements Converter<String, GenderEnum> {
public GenderEnum convert(String source) {
return "男".equals(source) ? GenderEnum.MALE : GenderEnum.FEMALE;
}
}
public class ConverterController {
public void initBinder(WebDataBinder binder) {
// 注册自定义转换器
binder.addConverter(new StringToGenderConverter());
}
public String getGender(GenderEnum gender) { // 请求参数:?gender=男 → 转换为 MALE
return "性别枚举:" + gender;
}
}
@ModelAttribute:模型数据预置与参数绑定
@ModelAttribute 是多功能注解,可标注在方法或参数上,分别用于 “预置模型数据” 和 “绑定请求参数到对象”。
1. 标注在方法上:预置模型数据
- 作用:在当前 Controller 的所有
@RequestMapping方法执行前执行,用于预置模型数据(如全局查询条件、用户信息); - 执行时机:优先于同 Controller 中的
@RequestMapping方法。
示例:预置全局数据
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;
public class ModelAttributeController {
// 1. 无返回值:手动添加数据到 Model
public void preHandle( String version, Model model) {
model.addAttribute("systemVersion", version == null ? "1.0.0" : version);
}
// 2. 有返回值:自动将返回值添加到 Model(键名为返回值类型名首字母小写,如 User → "user")
public User preUser() {
return new User("默认用户", 20); // 自动存入 Model:key = "user"
}
// 3. 有返回值+指定键名:通过 @ModelAttribute("key") 指定模型键名
public Long preTime() {
return System.currentTimeMillis(); // 存入 Model:key = "globalTime"
}
// 4. 使用预置的模型数据
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;
// 构造器、getter/setter
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
}
}
2. 标注在参数上:绑定请求参数到对象
- 作用:将请求参数自动绑定到 Java 对象(如表单提交的用户信息),并将该对象存入模型;
- 核心属性:
value(模型中的键名,默认是对象类型名首字母小写)。
示例:表单参数绑定到对象
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
public class UserFormController {
// 接收表单参数:?name=张三&age=25 → 自动绑定到 User 对象
public String saveUser( User user) {
// @ModelAttribute("user"):将 user 对象存入 Model,键名为 "user"
return "保存用户:" + user.getName() + ",年龄:" + user.getAge();
}
static class User {
private String name;
private Integer age;
// 无参构造器(必须,Spring 反射创建对象)、getter/setter
}
}
注意:
- 被
@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