0%

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 路径匹配规则

@RequestMappingpath 属性支持 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;

// 类级别 @RequestMapping:基础路径为 /user
@Controller
@RequestMapping("/user")
public class UserController {

// 1. 方法级别路径:完整路径为 /user/list(仅允许 GET 请求)
@RequestMapping(path = "/list", method = RequestMethod.GET)
@ResponseBody
public String getUserList() {
return "用户列表";
}

// 2. 支持 Ant 表达式:匹配 /user/1、/user/2 等
@RequestMapping("/{id}")
@ResponseBody
public String getUserById() {
return "查询单个用户";
}

// 3. 限制请求参数:必须包含 name 参数,且 age 不能为 0
@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
// 等效于 @RequestMapping(path = "/list", method = RequestMethod.GET)
@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 {

// 1. 单个路径参数:/rest/user/1 → id=1
@GetMapping("/{id}")
public String getUser(@PathVariable("id") Integer userId) {
return "查询用户 ID:" + userId;
}

// 2. 多个路径参数:/rest/user/1/detail/info → id=1, type=info
@GetMapping("/{id}/detail/{type}")
public String getUserDetail(
@PathVariable Integer id, // 变量名与 {id} 一致,可省略 value
@PathVariable("type") String detailType) {
return "用户 ID:" + id + ",详情类型:" + detailType;
}

// 3. 可选参数(required = false):/rest/user/optional 或 /rest/user/optional/123
@GetMapping("/optional/{name:.+}") // .+ 匹配含小数点的字符串(如文件名)
public String getOptionalParam(
@PathVariable(required = false) String name) {
return "可选参数:" + (name == null ? "未提供" : name);
}
}

注意

  • 若路径参数包含特殊字符(如 ./),需通过正则表达式显式匹配(如 {name:.+} 匹配含 . 的字符串);
  • 参数名与路径变量名一致时,可省略 @PathVariablevalue 属性。

@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 {

// 1. 基础用法:获取 ?id=1&name=张三
@GetMapping("/user")
public String getUser(
@RequestParam("id") Integer userId,
@RequestParam String name) { // 参数名与请求参数一致,可省略 value
return "ID:" + userId + ",姓名:" + name;
}

// 2. 可选参数与默认值:?page=2 或 无page参数(默认1)
@GetMapping("/list")
public String getList(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return "第 " + page + " 页,每页 " + size + " 条";
}

// 3. 非必填参数:?keyword=java 或 无keyword参数(值为null)
@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:获取请求头信息

@RequestHeader 用于获取 HTTP 请求头中的信息(如 User-AgentContent-TypeCookie 等)。

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 值(如 JSESSIONID、自定义 Cookie)。

1. 核心作用

直接绑定 Cookie 的值到方法参数,无需手动通过 HttpServletRequest 获取。

2. 核心属性

@RequestParam 一致:value(Cookie 名)、requireddefaultValue

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;

// 类级别:将模型中 "userName" 和 "role" 属性存入 Session
@Controller
@RequestMapping("/session")
@SessionAttributes(value = {"userName", "role"})
public class SessionController {

// 1. 向模型添加数据(会被 @SessionAttributes 同步到 Session)
@GetMapping("/login")
public String login(Model model) {
model.addAttribute("userName", "张三"); // 存入 Model + Session
model.addAttribute("role", "admin"); // 存入 Model + Session
return "loginSuccess";
}

// 2. 从 Session 中获取数据(三种方式)
@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")); // admin
System.out.println("@SessionAttribute 获取的 userName:" + userName); // 张三

return "sessionInfo";
}

// 3. 清除 @SessionAttributes 管理的 Session 数据
@GetMapping("/logout")
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. 实战示例:日期格式化

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 {

// 1. 注册日期格式化器:将 "yyyy-MM-dd" 字符串转为 Date 对象
@InitBinder
public void initBinder(WebDataBinder binder) {
// 自定义日期格式
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}

// 2. 接收 Date 参数(自动通过上面的格式化器转换)
@GetMapping("/date")
public String getDate(Date birthday) { // 请求参数:?birthday=2000-01-01
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;

// 自定义转换器:String → GenderEnum(枚举)
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) { // 请求参数:?gender=男 → 转换为 MALE
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 {

// 1. 无返回值:手动添加数据到 Model
@ModelAttribute
public void preHandle(@RequestParam(required = false) String version, Model model) {
model.addAttribute("systemVersion", version == null ? "1.0.0" : version);
}

// 2. 有返回值:自动将返回值添加到 Model(键名为返回值类型名首字母小写,如 User → "user")
@ModelAttribute
public User preUser() {
return new User("默认用户", 20); // 自动存入 Model:key = "user"
}

// 3. 有返回值+指定键名:通过 @ModelAttribute("key") 指定模型键名
@ModelAttribute("globalTime")
public Long preTime() {
return System.currentTimeMillis(); // 存入 Model:key = "globalTime"
}

// 4. 使用预置的模型数据
@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;
// 构造器、getter/setter
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 {

// 接收表单参数:?name=张三&age=25 → 自动绑定到 User 对象
@PostMapping("/save")
public String saveUser(@ModelAttribute("user") 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 类级别,作用于所有方法

最佳实践

  1. 路径映射:优先使用 @GetMapping@PostMapping 等派生注解,简化代码;
  2. 参数获取:REST 风格用 @PathVariable,查询 / 表单参数用 @RequestParam
  3. 数据共享:跨请求数据用 @SessionAttributes + @SessionAttribute,单次请求用 Model;
  4. 数据绑定:复杂类型转换用 @InitBinder 注册转换器,表单对象用 @ModelAttribute 绑定;
  5. 全局处理:全局数据预置用 @ControllerAdvice + @ModelAttribute,全局异常用 @ControllerAdvice + @ExceptionHandler

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10