spring MVC基础注解汇总
目录
一、Spring MVC 请求处理的整体流程
从核心组件方面分析流程
从不同类型注解的使用方面分析流程
二、核心控制器注解
1. @Controller 注解
2. @RestController 注解
@Controller vs @RestController 详细对比
@Controller 和 @RestController 的组合使用
二、请求映射注解
1. @RequestMapping
2. @GetMapping
3. @PostMapping
4. @PutMapping
5. @DeleteMapping
6. @PatchMapping
7. 请求映射注解的总结
三、自动绑定参数
1. 自动绑定 URL 查询参数
2. 自动绑定表单字段
3.自动绑定对象
4. 自动绑定的限制
四、请求参数绑定相关注解
1. @PathVariable
2. @RequestParam
3. @RequestBody
4. @ModelAttribute
5. @RequestHeader
6. @CookieValue
7.@RequestPart 注解
8. 请求参数绑定注解的总结
五、响应相关注解
1. @ResponseBody
2. @ResponseStatus
3. @RestController
4. @ExceptionHandler
5. @ResponseBody 与视图解析器的区别
六、会话和请求作用域注解
1. @RequestScope
2. @SessionScope
3. 请求作用域与会话作用域的区别
七、安全和认证相关注解
1. @Secured
2. @PreAuthorize
3. @PostAuthorize
4. @RolesAllowed
5. @AuthenticationPrincipal
6.安全和认证相关注解总结
八、拦截器相关注解
1. @Component
2. @Configuration
3. @Order
九、跨域相关注解
1. @CrossOrigin
2. @Configuration 配置跨域
3. @CrossOrigin 与全局配置的区别
十、总结
一、Spring MVC 请求处理的整体流程
从核心组件方面分析流程
- 请求进入 DispatcherServlet:客户端的 HTTP 请求被
DispatcherServlet
接收,它是请求的统一入口。 - HandlerMapping 查找 Controller:
DispatcherServlet
将请求转交给HandlerMapping
,后者根据 URL 选择合适的Controller
。 - Interceptor 拦截请求:在调用控制器方法之前,
Interceptor
进行前置处理,如权限验证。 - Controller 处理请求:
Controller
执行业务逻辑,处理请求,返回ModelAndView
,其中包含模型数据和视图名称。 - ViewResolver 解析视图:
DispatcherServlet
使用ViewResolver
将逻辑视图名称转换为物理视图(如 JSP 页面)。 - 视图渲染和响应:视图将模型数据渲染为最终的页面,
DispatcherServlet
将生成的响应返回给客户端。
从不同类型注解的使用方面分析流程
1.控制器定义:当用户发出请求时,Spring 通过 @Controller
或 @RestController
识别哪个类是处理请求的控制器。这一步,Spring 知道哪个类应该接收请求并处理逻辑。
2.请求映射:Spring 查找控制器类中的方法,并根据 @RequestMapping
、@GetMapping
或 @PostMapping
等注解,将请求的 URL 和 HTTP 方法映射到具体的控制器方法上。比如,GET 请求会被映射到带有 @GetMapping
注解的方法。
3.跨域检查:如果请求是跨域的,Spring 会检查 @CrossOrigin
注解,决定是否允许跨域请求。这一步确保跨域请求可以安全地被控制器方法处理。
4.拦截器预处理:在请求进入控制器方法前,Spring 可能通过拦截器的 preHandle
方法进行预处理,比如记录日志或执行权限验证。拦截器可以在 @Configuration
配置类中注册。这一步会先检查请求是否符合预处理逻辑,比如用户是否已登录或是否有访问权限。
5.安全验证:Spring Security 会使用 @PreAuthorize
或 @Secured
注解来检查当前用户是否有权限执行该方法。如果用户没有权限,Spring 会拒绝请求。这一阶段确保用户只能访问他们有权限访问的资源或执行的操作。
6.请求参数绑定:Spring 通过 @RequestParam
、@PathVariable
、@RequestBody
、或 @ModelAttribute
等注解,将请求中的 URL 参数、表单数据或 JSON 数据绑定到控制器方法的参数中。例如,表单中的数据会被自动绑定到 Java 对象,供控制器方法使用。
7.控制器方法执行:完成参数绑定后,Spring 执行映射的控制器方法来处理业务逻辑。
8.拦截器后处理:在控制器方法执行完后,拦截器的 postHandle
方法可能会对响应数据进行修改或记录处理信息。例如,可以在这一步修改响应的模型数据。
9.响应处理:控制器方法的返回值会经过 @ResponseBody
注解处理,将 Java 对象直接转换为 JSON 或 XML 返回给客户端。如果使用了 @RestController
,Spring 会自动将方法的返回值作为 HTTP 响应体。
10.拦截器完成处理:在整个请求完成后,拦截器的 afterCompletion
方法执行,用于清理资源或记录完成状态。
11.作用域管理:如果使用了 @RequestScope
或 @SessionScope
,Spring 会在请求处理或会话期间管理这些 Bean 的生命周期。请求结束或会话失效时,Bean 实例会被销毁。
二、核心控制器注解
1. @Controller
注解
作用
@Controller
是 Spring MVC 中的核心注解之一,主要用于标识 一个类为控制器,用于处理 Web 请求。使用 @Controller
的类通常包含处理客户端请求的业务逻辑,并返回一个视图名称。
特点
@Controller
注解的类是 Spring MVC 中的 处理器类,它与前端控制器DispatcherServlet
配合使用。- 通过方法级别的
@RequestMapping
、@GetMapping
、@PostMapping
等注解,可以将请求 URL 映射到具体的控制器方法上。 @Controller
默认用于返回 视图名称,由 Spring MVC 的 视图解析器(ViewResolver
)将逻辑视图名称解析为具体的视图模板(如 JSP、Thymeleaf)。
使用场景
- 适用于传统的 MVC 模式,其中控制器方法会返回视图名称,并渲染前端页面。
- 用于需要返回网页、HTML、JSP 或其他视图模板的场景。
示例代码
@Controller
public class UserController {
// 处理 GET 请求,返回视图名称 "userDetails"
@GetMapping("/users/{id}")
public String getUserDetails(@PathVariable Long id, Model model) {
// 假设我们通过 id 获取用户对象,并添加到模型中
User user = userService.findUserById(id);
model.addAttribute("user", user);
// 返回逻辑视图名 "userDetails",Spring MVC 会根据视图解析器解析该视图
return "userDetails";
}
}
详细解释
(1)@Controller
:定义 UserController
类为控制器类。
(2)@GetMapping("/users/{id}")
:将 URL /users/{id}
映射到 getUserDetails()
方法。该方法处理用户请求,获取用户信息。
(3)Model
对象:用于将数据传递给视图层。控制器方法处理完后,将用户数据放入 Model
对象中,供视图显示。
(4)返回视图名称:return "userDetails"
返回逻辑视图名称,视图解析器会将其解析为具体的 JSP 或 Thymeleaf 模板文件(如 WEB-INF/views/userDetails.jsp
)。
2. @RestController
注解
作用
@RestController
是 Spring MVC 提供的另一个核心注解,它是 @Controller
和 @ResponseBody
的组合注解,主要用于构建 RESTful API。与 @Controller
不同,@RestController
返回的数据不会通过视图解析器解析,而是直接写入 HTTP 响应体。
特点
@RestController
注解的类被视为 RESTful 控制器,专用于返回 JSON、XML 或其他格式的数据。- 所有控制器方法返回的数据会被自动序列化为 JSON 或 XML 格式(取决于请求头
Content-Type
),无需手动使用@ResponseBody
。 - 适用于构建 RESTful API,处理客户端请求并返回结构化数据(如 JSON)。
使用场景
- 适用于构建 API,返回 JSON、XML 等数据格式,而不是视图页面。
- 用于需要开发 RESTful Web 服务 的场景,特别是客户端请求需要处理数据,而不需要返回完整的网页时。
示例代码
@RestController
@RequestMapping("/api/users")
public class UserRestController {
// 处理 GET 请求,返回用户信息(JSON)
@GetMapping("/{id}")
public User getUserDetails(@PathVariable Long id) {
// 假设通过 id 获取用户对象
return userService.findUserById(id);
}
// 处理 POST 请求,创建新用户,并返回创建的用户信息
@PostMapping
public User createUser(@RequestBody User user) {
// 创建新用户
return userService.saveUser(user);
}
}
详细解释
@RestController
:定义UserRestController
类为 RESTful 控制器。所有返回的数据会自动序列化为 JSON 或 XML 格式。@RequestMapping("/api/users")
:将控制器的所有请求路径前缀设为/api/users
。@GetMapping("/{id}")
:将 URL/api/users/{id}
映射到getUserDetails()
方法。该方法返回的是User
对象,Spring 会将其序列化为 JSON 格式,并写入响应体。@PostMapping
和@RequestBody
:createUser()
方法处理 POST 请求,@RequestBody
注解会自动将请求体中的 JSON 数据反序列化为User
对象,并返回保存后的用户信息。
返回示例
客户端发送 GET /api/users/123
请求时,服务器响应:
{
"id": 123,
"name": "John Doe",
"email": "john.doe@example.com"
}
@Controller
vs @RestController
详细对比
特性 | @Controller | @RestController |
---|---|---|
主要用途 | 返回视图页面(JSP、Thymeleaf 等) | 返回 JSON 或 XML 数据,构建 RESTful API |
返回值 | 返回逻辑视图名称 | 返回数据,通常为对象或列表,自动转换为 JSON |
视图解析 | 使用视图解析器(ViewResolver)解析视图 | 不使用视图解析器,直接返回数据 |
与 @ResponseBody 关系 | 需要与 @ResponseBody 一起使用 | 内置了 @ResponseBody ,无需单独使用 |
典型使用场景 | 传统 MVC 应用,需要渲染页面的场景 | 构建 RESTful API,返回数据而不是视图页面 |
@Controller
和 @RestController
的组合使用
在实际项目中,通常我们需要结合使用 @Controller
和 @RestController
。@Controller
用于处理需要返回视图的请求,而 @RestController
用于处理 API 请求。这种组合方式可以让一个项目同时支持前端页面渲染和 API 服务。
@Controller
:主要用于处理返回视图页面的请求,适合传统的 MVC 应用。它与视图解析器一起工作,返回 JSP、Thymeleaf 等页面。@RestController
:主要用于返回数据而不是视图页面,适合构建 RESTful API。它自动将返回值转换为 JSON 或 XML,直接输出到 HTTP 响应体中。
二、请求映射注解
1. @RequestMapping
作用
@RequestMapping
是最基本的请求映射注解,可以应用在类或者方法上,用于映射请求的 URL 和处理器方法。它不仅可以指定 URL,还可以指定 HTTP 方法、请求参数等多种匹配条件。
特点
- 灵活性:可以同时应用在控制器类级别和方法级别。
- 支持多种配置:除了映射 URL,还可以设置请求方法、请求参数、请求头等条件。
- 用法:常用于处理多个 HTTP 方法的请求,比如 GET 和 POST。
示例代码
@Controller
@RequestMapping("/users")
public class UserController {
// 处理 GET 请求,获取用户列表
@RequestMapping(method = RequestMethod.GET)
public String getUsers(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "userList";
}
}
详细解释
@RequestMapping("/users")
:将控制器的请求路径前缀设为/users
。类级别的注解意味着所有方法的 URL 都会以/users
开头。method = RequestMethod.GET
:将请求方法限定为 GET,仅处理 GET 请求。- 返回值:返回视图名称
userList
,由视图解析器处理。
2. @GetMapping
作用
@GetMapping
是 @RequestMapping
的简化版本,专门用于处理 GET 请求。GET 请求通常用于获取资源或页面。
特点
- 专注于 GET 请求:相比于
@RequestMapping
,它只处理 GET 请求,语法简洁。 - 常用场景:用于从服务器获取资源(如数据、页面)而不改变服务器状态。
示例代码
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.findUserById(id);
model.addAttribute("user", user);
return "userDetails";
}
详细解释
@GetMapping("/users/{id}")
:映射 GET 请求到 getUser() 方法,URL 中的{id}
是路径变量,绑定到方法参数id
。@PathVariable
:用于从 URL 中获取动态路径部分(例如用户 ID)。- 返回值:返回视图名称
userDetails
,视图解析器处理后展示用户详情页面。
3. @PostMapping
作用
@PostMapping
是专门用于处理 POST 请求的注解,POST 请求通常用于提交表单数据或者创建新的资源。
特点
- 专注于 POST 请求:简化了处理 POST 请求的配置。
- 常用场景:用于服务器端资源的创建或数据提交操作。
示例代码
@PostMapping("/users")
public String createUser(@RequestBody User user, Model model) {
userService.saveUser(user);
model.addAttribute("user", user);
return "userCreated";
}
详细解释
@PostMapping("/users")
:映射 POST 请求到 createUser() 方法,处理新用户的创建。@RequestBody
:从请求体中接收 JSON 数据,并将其转换为 User 对象。- 返回值:返回视图名称
userCreated
,视图解析器处理后展示创建成功页面。
4. @PutMapping
作用
@PutMapping
是专门用于处理 PUT 请求的注解,PUT 请求通常用于更新现有资源。
特点
- 专注于 PUT 请求:与 POST 类似,但 PUT 用于更新现有资源。
- 常用场景:当你需要更新服务器上现有的数据时,通常使用 PUT 请求。
示例代码
@PutMapping("/users/{id}")
public String updateUser(@PathVariable Long id, @RequestBody User user) {
userService.updateUser(id, user);
return "userUpdated";
}
详细解释
@PutMapping("/users/{id}")
:映射 PUT 请求到 updateUser() 方法,用于更新用户信息。@RequestBody
:从请求体中接收 JSON 数据,并将其转换为 User 对象。@PathVariable
:从 URL 中获取用户 ID,用于更新指定用户的信息。
5. @DeleteMapping
作用
@DeleteMapping
是专门用于处理 DELETE 请求的注解,DELETE 请求通常用于删除资源。
特点
- 专注于 DELETE 请求:用于删除服务器端的资源。
- 常用场景:当你需要从服务器删除某个资源时,使用 DELETE 请求。
示例代码
@DeleteMapping("/users/{id}")
public String deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return "userDeleted";
}
详细解释
@DeleteMapping("/users/{id}")
:映射 DELETE 请求到 deleteUser() 方法,用于删除指定的用户。@PathVariable
:从 URL 中获取用户 ID,指定删除哪个用户。- 返回值:返回视图名称
userDeleted
,视图解析器处理后展示删除成功页面。
6. @PatchMapping
作用
@PatchMapping
是专门用于处理 PATCH 请求的注解,PATCH 请求通常用于部分更新资源。
特点
- 专注于 PATCH 请求:与 PUT 相似,但用于部分更新,而不是全量更新。
- 常用场景:当你只需要更新资源的一部分时,可以使用 PATCH 请求。
示例代码
@PatchMapping("/users/{id}")
public String patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
userService.patchUser(id, updates);
return "userPatched";
}
详细解释
@PatchMapping("/users/{id}")
:映射 PATCH 请求到 patchUser() 方法,用于部分更新用户信息。@RequestBody
:接收部分更新数据,并以 Map 的形式传递。- 返回值:返回视图名称
userPatched
,视图解析器处理后展示更新成功页面。
7. 请求映射注解的总结
注解 | 用途 | HTTP 方法 |
---|---|---|
@RequestMapping | 映射任意请求方法(GET、POST、PUT、DELETE 等) | 任意 |
@GetMapping | 处理 GET 请求,用于获取资源 | GET |
@PostMapping | 处理 POST 请求,用于创建资源或提交数据 | POST |
@PutMapping | 处理 PUT 请求,用于更新资源 | PUT |
@DeleteMapping | 处理 DELETE 请求,用于删除资源 | DELETE |
@PatchMapping | 处理 PATCH 请求,用于部分更新资源 | PATCH |
三、自动绑定参数
在某些情况下,Spring MVC 可以通过参数名称与 URL 查询参数 或 表单字段名称 的匹配,自动绑定参数到控制器方法的参数上 而不需要显式地使用注解。这种情况下,参数名称与请求中的字段名称一致时,Spring MVC 会自动完成数据绑定。
1. 自动绑定 URL 查询参数
如果 URL 查询参数的名称与控制器方法的参数名称一致,Spring MVC 可以自动将查询参数绑定到方法的参数上,而无需使用 @RequestParam
注解。
示例
@GetMapping("/search")
public String search(String query, int page, Model model) {
// Spring MVC 会自动将 URL 中的 query 和 page 绑定到对应的参数上
model.addAttribute("query", query);
model.addAttribute("page", page);
return "searchResults";
}
示例请求
GET /search?query=springmvc&page=2
- 在这个例子中,Spring 会自动将
query
和page
的值从 URL 查询参数中提取出来,并绑定到方法的query
和page
参数上。无需显式使用@RequestParam
注解。
2. 自动绑定表单字段
在 POST 请求 中,如果表单字段的名称和控制器方法的参数名称一致,Spring 也可以自动将表单字段的数据绑定到方法参数上,而不需要显式地使用 @RequestParam
。
示例
@PostMapping("/submitForm")
public String handleForm(String name, int age, Model model) {
// 表单字段 name 和 age 会自动绑定到对应的参数上
model.addAttribute("name", name);
model.addAttribute("age", age);
return "formSuccess";
}
示例表单
<form action="/submitForm" method="post">
<input type="text" name="name" />
<input type="number" name="age" />
<button type="submit">Submit</button>
</form>
- 表单提交后,
name
和age
字段的数据将自动绑定到控制器方法的name
和age
参数上,无需显式使用@RequestParam
注解。
这种机制通常依赖于对象的字段名称与请求参数的名称匹配,并且可以通过对象的 getter 和 setter 方法来自动绑定数据。
这种方式主要使用的是 @ModelAttribute
注解或者不加注解的对象参数。
3.自动绑定对象
Spring MVC 可以自动将 表单数据 或 查询参数 映射到一个 Java 对象,前提是请求中的参数名称与对象的属性名称一致。Spring 会根据参数的名称,自动调用对象的 setter 方法进行属性赋值。
(1)自动绑定对象 (表单提交)
假设我们有一个包含多个字段的表单,Spring MVC 可以自动将表单数据绑定到一个 Java 对象的属性中。
public class User {
private String name;
private int age;
// getters and setters
}
控制器方法
@PostMapping("/register")
public String registerUser(User user, Model model) {
// Spring MVC 自动将表单字段绑定到 User 对象的属性中
model.addAttribute("user", user);
return "registrationSuccess";
}
HTML 表单
<form action="/register" method="post">
<input type="text" name="name" />
<input type="number" name="age" />
<button type="submit">Register</button>
</form>
详细解释
User
类:包含name
和age
属性,并且具有对应的 getter 和 setter 方法。- Spring MVC 绑定机制:在表单提交时,Spring 会将表单中
name
和age
字段的值绑定到User
对象的name
和age
属性上,使用 setter 方法自动进行数据赋值。
示例请求
POST /register
name=John&age=25
name
和age
会自动绑定到User
对象的name
和age
属性上。
(2)自动绑定对象 (查询参数)
类似地,Spring MVC 也支持从 URL 查询参数 直接绑定到 Java 对象的属性中。
控制器方法
@GetMapping("/userSearch")
public String searchUser(User user, Model model) {
// Spring MVC 自动将查询参数绑定到 User 对象的属性中
model.addAttribute("user", user);
return "userDetails";
}
示例 URL
GET /userSearch?name=John&age=25
- Spring 会自动将查询参数
name=John
和age=25
绑定到User
对象的name
和age
属性上。
详细解释
- URL 查询参数:URL 中的
?name=John&age=25
会被自动解析,并且绑定到User
对象的对应属性中。 - 对象绑定机制:Spring 通过反射机制和对象的 setter 方法来实现这种参数到对象属性的自动绑定。
4. 自动绑定的限制
虽然 Spring MVC 能够自动完成参数绑定,但在某些复杂场景下,仍然建议使用注解来明确指定绑定行为。以下是几种情况,你可能仍然需要使用注解:
-
自定义参数名称:如果 URL 查询参数或表单字段的名称与方法参数名称不一致,你需要使用
@RequestParam
来指定参数名称。@GetMapping("/search") public String search(@RequestParam("q") String query) { // 如果 URL 查询参数是 `q`,而方法参数是 `query`,则必须使用 @RequestParam 指定绑定 }
-
可选参数或默认值:当某些参数是可选的或者你希望提供默认值时,使用
@RequestParam
注解更灵活。@GetMapping("/search") public String search(@RequestParam(defaultValue = "spring") String query) { // 如果没有提供 query 参数,则使用默认值 "spring" }
-
非简单类型:当你需要绑定复杂的对象或列表时,通常需要使用其他注解(如
@ModelAttribute
或@RequestBody
),而不是依赖自动绑定。
- 自动绑定:Spring MVC 能够根据 参数名称和 URL 查询参数/表单字段名称 自动完成数据绑定。如果名称一致,无需显式使用注解。
- 适合场景:这种自动绑定方式适合简单的请求参数和表单字段处理,尤其是名称一致的情况下。
- 需要使用注解的情况:当需要处理可选参数、提供默认值、名称不一致或处理复杂对象时,建议使用
@RequestParam
或其他注解来明确指定绑定逻辑。
四、请求参数绑定相关注解
在 Spring MVC 中,请求参数绑定相关的注解主要用于将 HTTP 请求中的参数(如 URL 路径中的变量、查询参数、表单数据或请求体中的 JSON 数据等)绑定到控制器方法的参数上。以下是常用的请求参数绑定相关的注解及其详细解释:
1. @PathVariable
作用
@PathVariable
注解用于将 URL 路径中的模板变量绑定到控制器方法的参数上。它通常用于 RESTful 风格的 URL 中,用于获取路径中的动态部分。
特点
- 绑定路径中的变量:
@PathVariable
可以将 URL 中的某个部分直接绑定到方法参数上。 - 常用于 RESTful URL:特别适合于资源标识符(如 ID)的绑定。
示例代码
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id, Model model) {
// 通过 id 获取用户信息
User user = userService.findUserById(id);
model.addAttribute("user", user);
return "userDetails";
}
详细解释
@PathVariable("{id}")
:将 URL/users/{id}
中的{id}
动态路径变量绑定到方法参数id
上。- 示例请求:
GET /users/123
会将123
作为参数传递给id
,并用于查询用户信息。
支持多个路径变量
@GetMapping("/users/{userId}/orders/{orderId}")
public String getOrder(@PathVariable Long userId, @PathVariable Long orderId, Model model) {
// 处理业务逻辑
}
- 示例请求:
GET /users/123/orders/456
会将userId
绑定为123
,orderId
绑定为456
。
2. @RequestParam
作用
@RequestParam
注解用于将请求的查询参数或表单参数绑定到方法的参数上。它通常用于处理 GET 请求中的查询参数或 POST 请求中的表单数据。
特点
- 绑定查询参数或表单字段:用于从 URL 查询字符串或表单字段中获取参数。
- 支持默认值和是否必需:可以指定参数的默认值,也可以配置参数是否必须存在。
这里的@RequestParam注解所说的 “从 URL 查询字符串获取参数”就是指从普通的URL中获取参数(因为普通的URL中参数都是跟在路径下的问号之后),所以@RequestParam主要负责处理的是普通的URL。
还有就是“从表单字段获取参数”就是指前端创建了个HTML表单,@RequestParam将这些表单字段绑定到控制器方法的参数上。
示例代码--从 URL 查询字符串获取参数
@GetMapping("/search")
public String search(@RequestParam String query, @RequestParam(defaultValue = "1") int page, Model model) {
// 执行搜索逻辑
model.addAttribute("query", query);
model.addAttribute("page", page);
return "searchResults";
}
详细解释
@RequestParam("query")
:将请求的查询参数query
绑定到方法参数query
。@RequestParam(defaultValue = "1")
:如果未提供page
参数,则使用默认值1
。
示例代码--从表单字段获取参数
HTML表单
<form action="/submitForm" method="post">
<input type="text" name="name" />
<input type="number" name="age" />
<button type="submit">Submit</button>
</form>
@PostMapping("/submitForm")
public String handleForm(@RequestParam String name, @RequestParam int age, Model model) {
// 处理表单提交的数据
model.addAttribute("name", name);
model.addAttribute("age", age);
return "formSuccess";
}
详细解释
@RequestParam("name")
:从表单字段name
获取用户输入的值并绑定到方法参数name
上。@RequestParam("age")
:从表单字段age
获取用户输入的值并绑定到方法参数age
上。
支持多个查询参数
@GetMapping("/filter")
public String filter(@RequestParam String category, @RequestParam(required = false) String brand) {
// 处理业务逻辑
}
- 示例请求:
GET /filter?category=electronics&brand=apple
将category
绑定为electronics
,brand
绑定为apple
。
3. @RequestBody
作用
@RequestBody
注解用于将请求体中的 JSON、XML 或其他格式的数据绑定到方法参数上。它通常用于处理 POST、PUT 请求,接收客户端发送的 JSON 数据并将其反序列化为 Java 对象。
特点
- 处理请求体数据:将请求体中的数据解析并绑定到方法参数,常用于 RESTful API 中的数据传递。
- 自动反序列化 JSON:Spring MVC 自动将请求体中的 JSON 数据转换为 Java 对象。
示例代码
@GetMapping("/filter")
public String filter(@RequestParam String category, @RequestParam(required = false) String brand) {
// 处理业务逻辑
}
详细解释
@RequestBody
:用于接收请求体中的 JSON 数据并将其反序列化为User
对象。- 示例请求:
POST /users { "name": "John", "email": "john@example.com" }
- Spring MVC 会将 JSON 数据自动解析为
User
对象,并将其传递给控制器方法。
- Spring MVC 会将 JSON 数据自动解析为
处理复杂数据
@PutMapping("/users/{id}")
public String updateUser(@PathVariable Long id, @RequestBody UserUpdateRequest updateRequest) {
// 更新用户信息
}
- 示例请求:
PUT /users/123 { "email": "new-email@example.com", "name": "New Name" }
4. @ModelAttribute
作用
@ModelAttribute
注解用于将请求参数自动绑定到模型对象上,或者在方法上添加属性到模型中。它特别适合处理表单提交的数据绑定,将表单字段的数据自动绑定到 Java 对象中。
特点
- 用于表单数据绑定:将请求参数自动填充到 Java 对象中。
- 可以在方法级别使用:也可以用于向视图添加模型数据。
示例代码
@PostMapping("/register")
public String registerUser(@ModelAttribute User user, Model model) {
userService.register(user);
model.addAttribute("user", user);
return "registrationSuccess";
}
详细解释
@ModelAttribute
:自动将表单字段绑定到User
对象的属性上。- 示例表单:
<form action="/register" method="post">
<input type="text" name="name" />
<input type="email" name="email" />
<button type="submit">Register</button>
</form>
- 提交的表单数据会自动绑定到
User
对象的name
和email
属性上。
向模型添加数据
@ModelAttribute("roles")
public List<String> getRoles() {
return Arrays.asList("Admin", "User", "Guest");
}
- 解释:该方法将
roles
数据添加到模型中,供视图层使用。
5. @RequestHeader
作用
@RequestHeader
注解用于将请求头中的数据绑定到方法参数上。它可以获取请求头中的某个字段的值,并将其传递给控制器方法。
特点
- 用于绑定请求头数据:用于获取 HTTP 请求中的头信息。
- 可以设置默认值:可以在请求头不存在时使用默认值。
示例代码
@GetMapping("/greet")
public String greetUser(@RequestHeader("User-Agent") String userAgent, Model model) {
model.addAttribute("userAgent", userAgent);
return "greeting";
}
详细解释
@RequestHeader("User-Agent")
:将请求头中的User-Agent
值绑定到方法参数userAgent
。- 示例请求:
GET /greet
时,Spring MVC 会提取请求头中的User-Agent
字段的值,并传递给greetUser()
方法。
设置默认值
@GetMapping("/greet")
public String greetUser(@RequestHeader(value = "User-Agent", defaultValue = "Unknown") String userAgent) {
// 如果请求头中没有 "User-Agent",使用默认值 "Unknown"
}
6. @CookieValue
作用
@CookieValue
注解用于将 HTTP 请求中的 Cookie 值绑定到方法参数上。它可以获取指定的 Cookie 的值,并传递给控制器方法。
特点
- 用于绑定 Cookie 数据:获取客户端发送的 Cookie 中的值。
- 支持设置默认值:如果 Cookie 不存在,可以设置默认值。
示例代码
@GetMapping("/welcome")
public String welcomeUser(@CookieValue(value = "userSessionId", defaultValue = "defaultSessionId") String sessionId) {
// 使用 sessionId 处理逻辑
return "welcome";
}
详细解释
@CookieValue("userSessionId")
:将名为userSessionId
的 Cookie 值绑定到sessionId
参数。- 示例请求:客户端请求携带 Cookie
userSessionId=abc123
,该值将传递给sessionId
。
7.@RequestPart
注解
作用
@RequestPart
注解用于处理 multipart/form-data 类型的请求,这种请求格式通常用于文件上传。通过 @RequestPart
,Spring MVC 可以将文件部分绑定到 MultipartFile
对象,文件的元数据(如文件名、大小等)以及文件的实际内容都可以通过 MultipartFile
来获取。
特点
- 处理文件上传:专门用于处理文件上传请求,绑定 multipart 请求中的文件数据。
- 适合 multipart/form-data:这种类型的请求包含多个部分(如文件和其他普通字段),
@RequestPart
主要处理文件部分。 - 与
MultipartFile
配合使用:Spring 提供了MultipartFile
类型来处理上传的文件。
MultipartFile
MultipartFile
是 Spring 提供的一个接口,用来表示上传的文件。它包含文件的基本信息以及一些常用的方法,如获取文件名、文件大小、文件类型、将文件保存到服务器等。
常用方法:
getOriginalFilename()
:获取上传的文件名。getSize()
:获取文件大小。getContentType()
:获取文件类型(MIME type)。transferTo(File dest)
:将文件保存到服务器上的某个位置。
示例代码:文件上传
控制器方法
@PostMapping("/upload")
public String handleFileUpload(@RequestPart("file") MultipartFile file) {
if (!file.isEmpty()) {
try {
// 获取文件信息
String fileName = file.getOriginalFilename();
long fileSize = file.getSize();
String contentType = file.getContentType();
// 将文件保存到服务器
file.transferTo(new File("/path/to/save/" + fileName));
return "File uploaded successfully!";
} catch (IOException e) {
return "File upload failed: " + e.getMessage();
}
} else {
return "No file uploaded!";
}
}
详细解释
@RequestPart("file")
:将文件上传表单字段file
绑定到控制器方法的MultipartFile
参数file
。MultipartFile
:表示上传的文件,可以通过其方法获取文件名、大小、类型等信息。file.transferTo()
:将上传的文件保存到服务器指定的目录。
HTML 示例
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="file">Choose a file:</label>
<input type="file" id="file" name="file" />
<button type="submit">Upload</button>
</form>
<input type="file">
:这是文件输入控件,允许用户选择一个文件。enctype="multipart/form-data"
:这是一种 MIME 类型,用于表示表单包含文件上传的数据。对于文件上传的表单,必须将enctype
设置为"multipart/form-data"
,否则文件不会被正确上传。<button type="submit">Upload</button>
:这是提交按钮,点击后会将选定的文件与表单数据一起提交到服务器。
8. 请求参数绑定注解的总结
注解 | 用途 | 数据来源 |
---|---|---|
@PathVariable | 从 URL 路径中获取动态变量并绑定到方法参数 | URL 路径 |
@RequestParam | 从 URL 查询参数或表单字段中获取参数 | 查询参数、表单 |
@RequestBody | 从请求体中接收 JSON 或 XML 数据并绑定到方法参数 | 请求体 |
@ModelAttribute | 从请求参数中自动绑定到模型对象,或添加数据到模型中 | 表单数据 |
@RequestHeader | 从请求头中获取某个字段的值并绑定到方法参数 | 请求头 |
@CookieValue | 从请求的 Cookie 中获取值并绑定到方法参数 | Cookie |
@PathVariable主要用于获取RESTfu类型的URL中的参数,而@RequestParam则用于普通URL中的参数与从表单字段中获取参数,当然如果不加这两个注解,只要URL中的参数名称与控制器方法中的名称一致也是可以自动绑定参数的。
五、响应相关注解
pring MVC 提供了多个与响应相关的注解,用于控制 HTTP 响应的格式和内容。响应相关的注解主要用于将处理结果转换成客户端所期望的格式,比如 JSON、XML 或直接返回文本信息。以下是 Spring MVC 中常用的响应相关注解的详细介绍:
1. @ResponseBody
作用
@ResponseBody
是最常用的响应注解之一,它的作用是将控制器方法的返回值直接写入 HTTP 响应体(response body),而不是将其解析为视图名称。它通常用于返回 JSON、XML 或文本数据,特别适合用于构建 RESTful API。
特点
- 直接写入响应体:控制器方法的返回值不会通过视图解析器,而是直接写入 HTTP 响应体中。
- 自动序列化:如果返回值是对象或列表,Spring 会自动将其序列化为 JSON 或 XML 格式,前提是请求头中包含
Accept
字段,指定所期望的响应格式(如application/json
)。
示例代码
@RestController // 也可以用 @Controller + @ResponseBody 组合
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{id}")
@ResponseBody // 将返回的 User 对象作为 JSON 输出
public User getUserById(@PathVariable Long id) {
return userService.findUserById(id);
}
}
详细解释
@ResponseBody
:将方法的返回值User
对象转换为 JSON 格式,并直接返回给客户端,而不是返回视图名称。- 示例请求:
GET /api/users/1
- 返回的 JSON 格式:
{
"id": 1,
"name": "John",
"email": "john@example.com"
}
与 @RestController
的关系
@RestController
是@Controller
和@ResponseBody
的组合注解,它将所有控制器方法的返回值都默认转换为响应体中的数据。因此,当你使用@RestController
时,不再需要单独为每个方法添加@ResponseBody
注解。
2. @ResponseStatus
作用
@ResponseStatus
注解用于为控制器方法或异常处理器指定 HTTP 状态码。当方法执行成功时,可以通过该注解指定自定义的 HTTP 状态码返回给客户端,通常用于在 RESTful API 中设置 HTTP 响应状态。
特点
- 设置响应状态码:可以为成功或失败的操作设置特定的 HTTP 状态码,例如
201 Created
、204 No Content
、404 Not Found
等。 - 可用于异常处理器:当捕获特定异常时,可以通过
@ResponseStatus
返回自定义的错误状态码。
示例代码
@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED) // 返回 201 状态码
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
详细解释
@ResponseStatus(HttpStatus.CREATED)
:指定该方法成功执行后,返回 201 Created 状态码,表示资源已成功创建。- 示例请求:
POST /users
,成功创建用户后,返回状态码201 Created
,并附带新创建的用户信息。
结合异常处理器
@ResponseStatus(HttpStatus.NOT_FOUND) // 返回 404 状态码
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
- 解释:当抛出
UserNotFoundException
时,Spring 会自动返回 404 Not Found 状态码。
3. @RestController
作用
@RestController
是一个组合注解,等同于 @Controller
和 @ResponseBody
的组合。标注了 @RestController
的类中的每个方法都会默认返回对象或数据,并将其写入 响应体,而不需要每个方法都手动添加 @ResponseBody
。
特点
- 简化 API 开发:对于 RESTful 风格的 API 开发,
@RestController
非常适用,简化了控制器方法的开发流程。 - 自动将返回值序列化:默认情况下,返回的对象会被自动序列化为 JSON 格式(如果客户端请求了 JSON 格式的响应)。
示例代码
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public List<User> getAllUsers() {
return userService.findAllUsers();
}
}
详细解释
@RestController
:将控制器中的所有方法返回的对象直接转换为 JSON 数据,并将其写入响应体中。- 示例请求:
GET /api/users
- 返回的 JSON 格式:
[
{"id": 1, "name": "John"},
{"id": 2, "name": "Jane"}
]
4. @ExceptionHandler
作用
@ExceptionHandler
注解用于定义异常处理器,处理控制器中抛出的特定异常。它可以返回自定义的响应内容和状态码,确保程序异常时返回一致的错误格式。
特点
- 处理异常:通过
@ExceptionHandler
,可以捕获指定的异常并返回自定义的错误信息和状态码。 - 与
@ResponseStatus
结合:可以结合@ResponseStatus
一起使用,返回特定的 HTTP 状态码。
示例代码
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findUserById(id).orElseThrow(() -> new UserNotFoundException("User not found"));
}
@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, String> handleUserNotFound(UserNotFoundException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
return error;
}
}
详细解释
userService.findUserById(id)
:这里通过userService
服务层的方法根据用户 ID 查找用户,返回的是一个Optional<User>
,如果找到用户,就返回用户对象。orElseThrow()
:这是 Java 8 中Optional
类的一个方法,它的作用是在找不到用户的情况下抛出一个自定义异常。这里抛出的是UserNotFoundException
,带有一个错误消息 "User not found"。ExceptionHandler(UserNotFoundException.class)
:这个注解声明了一个异常处理方法,用于捕获控制器中抛出的UserNotFoundException
异常,并自定义异常的响应内容和格式。当UserNotFoundException
被抛出时,该方法会被调用,返回一个自定义的错误信息。@ResponseStatus(HttpStatus.NOT_FOUND)
:这行注解表示,当捕获到UserNotFoundException
时,HTTP 响应的状态码将设置为 404 Not Found。UserNotFoundException ex
:该参数表示捕获的异常对象,可以用来获取异常中的信息。ex.getMessage()
:从异常对象中获取错误消息,在UserNotFoundException
中,这个消息是"User not found"
。- 返回的错误信息:
{ "error": "User not found" }
5. @ResponseBody
与视图解析器的区别
在 Spring MVC 中,如果没有使用 @ResponseBody
,默认情况下,方法返回的字符串会被视为 视图名称,由 视图解析器(如 Thymeleaf、JSP)来渲染页面。使用了 @ResponseBody
或 @RestController
后,返回的内容将直接写入 HTTP 响应体,而不再经过视图解析器。
示例对比
- 没有
@ResponseBody
(返回视图):
@GetMapping("/hello")
public String hello() {
return "helloPage"; // 将视图名称 "helloPage" 交给视图解析器处理
}
- 有
@ResponseBody
(返回文本或 JSON):
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello, World!"; // 将 "Hello, World!" 写入 HTTP 响应体
}
@ResponseBody
:将控制器方法的返回值直接写入响应体,适用于返回 JSON、XML 或文本数据,特别适用于 RESTful API 开发。@ResponseStatus
:用于指定控制器方法的返回状态码,常用于成功创建、删除或自定义异常处理等场景。@RestController
:组合了@Controller
和@ResponseBody
,简化 RESTful 控制器的开发,自动将返回值转换为 JSON 并写入响应体。@ExceptionHandler
:用于处理控制器中的异常,并返回自定义的错误响应和状态码。
六、会话和请求作用域注解
在 Spring MVC 中,作用域(Scope)用于定义 Spring Bean 的生命周期和可见性范围。在 Spring 中,最常用的作用域有 会话作用域(Session Scope) 和 请求作用域(Request Scope)。
1. @RequestScope
作用
@RequestScope
注解用于声明一个 Bean 具有 请求作用域,即每次新的 HTTP 请求都会创建一个新的 Bean 实例。当请求结束时,Bean 实例会被销毁。
特点
- 短生命周期:每次 HTTP 请求都会生成一个新的 Bean 实例,生命周期从请求开始到请求结束。
- 适用场景:适合处理与单个 HTTP 请求相关的数据或对象。
Bean就是一个由Spring容器管理的类,Spring来负责控制这个对象的创建与销毁,就比如在下图中通过 @Component注解规定了RequestBean类是一个Bean,然后在控制器类中创建RequestBean类的对象就是Bean的实例,这个对象的生命周期就是从请求开始到请求结束,请求结束之后就销毁该对象,释放相关资源。
示例代码
@Component
@RequestScope
public class RequestBean {
private String message;
// getter and setter
}
@RestController
public class MyController {
@Autowired
private RequestBean requestBean;
@GetMapping("/request")
public String handleRequest() {
requestBean.setMessage("Request Scoped Bean Example");
return requestBean.getMessage();
}
}
详细解释
@RequestScope
:标注的RequestBean
是请求作用域的,每次发送请求/request
时,都会生成一个新的RequestBean
实例。- 生命周期:每个请求都会有一个新的实例,在请求结束后,
RequestBean
会被销毁。
2. @SessionScope
作用
@SessionScope
注解用于声明一个 Bean 具有 会话作用域,即同一用户的多个请求会共享同一个 Bean 实例,直到用户会话结束。
特点
- 长生命周期:Bean 在整个用户会话期间存在,可以跨多个 HTTP 请求共享数据。
- 适用场景:适合需要跨多个请求共享数据的情况,如用户登录信息、购物车等。
示例代码
@Component
@SessionScope
public class SessionBean {
private String username;
// getter and setter
}
@RestController
public class MyController {
@Autowired
private SessionBean sessionBean;
@GetMapping("/login")
public String login(@RequestParam String username) {
sessionBean.setUsername(username);
return "User " + sessionBean.getUsername() + " logged in.";
}
@GetMapping("/user")
public String getUser() {
return "Current user: " + sessionBean.getUsername();
}
}
详细解释
@SessionScope
:标注的SessionBean
是会话作用域的,在整个会话期间,SessionBean
实例会被多次请求共享。- 生命周期:会话开始时创建
SessionBean
,在会话结束时销毁实例。
3. 请求作用域与会话作用域的区别
特性 | 请求作用域(Request Scope) | 会话作用域(Session Scope) |
---|---|---|
生命周期 | 每次请求都会创建新的 Bean 实例,生命周期随请求结束而结束 | 在整个会话期间共享同一个 Bean 实例,直到会话过期 |
实例数量 | 每次请求都有一个新的实例 | 整个会话期间共享一个实例 |
适用场景 | 适合短暂的数据存储,处理一次请求的数据 | 适合需要在整个会话中共享的数据(如用户登录状态) |
结束时间 | 请求处理完毕后销毁 Bean 实例 | 会话结束时销毁 Bean 实例 |
@RequestScope
:Bean 在每个请求中生存,每次请求会创建一个新的实例,适用于一次请求期间的数据存储。@SessionScope
:Bean 在整个用户会话中生存,每次会话共享一个实例,适用于在整个会话中保持数据,如用户登录状态等。通过选择不同的作用域,你可以精确控制 Spring Bean 的生命周期,确保它们在合适的范围内生存,避免资源浪费和逻辑错误。
七、安全和认证相关注解
在 Spring Security 中,安全和认证 相关的注解用于处理用户权限、认证和授权等问题。这些注解可以帮助你轻松地为应用添加安全保护功能。
在 Spring Security 中,用户的权限(或角色)通常用于控制该用户能执行哪些操作或访问哪些资源。
用户角色解释
- 角色 是一种 权限标识,它定义了用户在系统中的操作权限范围。比如
ROLE_ADMIN
通常代表用户是管理员,具有较高的权限,可以执行创建、修改、删除等敏感操作。- 具备
ROLE_ADMIN
角色的用户,就是指在系统中,用户的权限信息中包含ROLE_ADMIN
这个角色。Spring Security 会根据这个角色判断用户是否有权访问某些方法或资源。用户角色的来源
- 用户角色通常是在用户 认证(登录) 时,通过数据库、内存或第三方认证服务(如 OAuth、LDAP)加载的。认证完成后,Spring Security 会将这些角色与用户绑定,用户的角色信息会存储在
SecurityContext
中。例子:用户的角色信息
假设一个用户登录后,其角色信息如下:
- 用户名:
admin
- 角色:
ROLE_ADMIN
,ROLE_USER
那么这个用户既具备 普通用户 (
ROLE_USER
) 的权限,也具备 管理员 (ROLE_ADMIN
) 的权限。用户角色的存储与分配
- 数据库:角色信息通常存储在数据库中,和用户的记录关联在一起。登录时系统会从数据库中读取用户的角色信息。
- 硬编码:有时,角色信息会直接在代码中指定,特别是在简单的应用中
1. @Secured
作用
@Secured
用于基于 用户角色 限制方法访问。只有拥有指定角色的用户才能访问该方法。
特点
- 基于 角色 限制访问。
- 简单易用,适用于只需要基于角色的权限控制场景。
示例代码
@Secured("ROLE_ADMIN")
public void adminOnlyMethod() {
// 只有拥有 ROLE_ADMIN 角色的用户才能访问
}
详细解释
@Secured("ROLE_ADMIN")
:只有具备ROLE_ADMIN
角色的用户才能访问adminOnlyMethod()
方法。用户如果没有该角色,Spring Security 会拒绝访问。
2. @PreAuthorize
作用
@PreAuthorize
用于方法执行 之前 验证权限。支持复杂的权限控制逻辑,可以通过 Spring Expression Language (SpEL) 表达式实现。
特点
- 支持 复杂权限控制,不仅可以基于角色,还可以基于方法参数和用户属性进行控制。
- 灵活,适用于需要根据多种条件进行权限验证的场景。
示例代码
@PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
public void userOrAdminAccess() {
// 用户或管理员角色的用户可以访问
}
详细解释
@PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
:允许拥有ROLE_USER
或ROLE_ADMIN
角色的用户访问该方法。@PreAuthorize
在方法执行前进行权限检查,确保用户满足至少一个角色的条件。
3. @PostAuthorize
作用
@PostAuthorize
用于在方法执行 之后 验证权限,通常用于根据方法的返回结果判断用户是否有权限访问。
特点
- 支持 返回结果 的权限验证,适合在方法执行后根据返回的对象属性进行权限检查。
- 常用于需要先执行逻辑,再验证用户是否有权限查看或处理返回数据的场景。
示例代码
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long id) {
// 只有文档的拥有者才能访问
return documentService.findById(id);
}
详细解释
@PostAuthorize("returnObject.owner == authentication.name")
:在方法执行后,检查返回的Document
对象的owner
属性是否等于当前登录用户的用户名。如果当前用户不是文档的拥有者,Spring Security 将拒绝访问返回的结果。
4. @RolesAllowed
作用
@RolesAllowed
限制方法访问,只有具有指定角色的用户才能访问该方法。它是 JSR-250 标准的一部分,功能类似于 @Secured
。
特点
- 基于 角色 的权限控制,支持多个角色。
- 多个角色之间的权限是 OR 关系,即用户只要拥有其中一个角色即可访问。
示例代码
@RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
public void userOrAdminAccess() {
// 拥有 ROLE_USER 或 ROLE_ADMIN 的用户可以访问
}
详细解释
@RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
:方法只允许拥有ROLE_USER
或ROLE_ADMIN
角色的用户访问。如果用户拥有其中任意一个角色,访问将被允许。
5. @AuthenticationPrincipal
作用
@AuthenticationPrincipal
用于获取当前登录用户的详细信息,通常用于在控制器方法中直接访问用户的认证信息。
特点
- 可以直接访问 当前登录用户 的信息,简化了从
SecurityContext
中手动获取用户信息的流程。 - 适用于需要在控制器中使用当前用户信息的场景。
示例代码
@GetMapping("/profile")
public String getUserProfile(@AuthenticationPrincipal UserDetails userDetails) {
return "User profile: " + userDetails.getUsername();
}
详细解释
@AuthenticationPrincipal UserDetails userDetails
:Spring Security 会自动将当前认证用户的详细信息注入到userDetails
参数中,开发者可以直接获取用户的用户名、权限等信息,而不需要手动从SecurityContext
获取。
6.安全和认证相关注解总结
注解 | 作用 | 适用场景 | 示例解释 |
---|---|---|---|
@Secured | 基于角色限制方法访问 | 简单的角色权限控制 | 只有指定角色的用户才能访问方法,角色必须以 ROLE_ 为前缀。 |
@PreAuthorize | 在方法执行前进行权限检查,支持复杂的 SpEL 表达式 | 灵活、复杂的权限控制 | 根据角色或方法参数灵活控制访问,适合多种条件下的权限控制。 |
@PostAuthorize | 在方法执行后进行权限检查 | 返回结果的权限控制 | 根据方法返回的对象属性进行权限判断,例如检查是否为数据的拥有者。 |
@RolesAllowed | 基于角色限制方法访问,JSR-250 标准 | 简单的角色权限控制 | 支持多个角色,多个角色是 OR 关系,用户只需拥有其中一个角色即可。 |
@AuthenticationPrincipal | 获取当前登录用户信息 | 获取当前用户信息 | 直接访问当前登录用户的详细信息,简化了获取用户信息的操作。 |
八、拦截器相关注解
在 Spring MVC 中,拦截器(Interceptor) 用于在请求到达控制器之前、执行完控制器之后、以及请求完成之后,执行一些预处理或后处理操作。拦截器通常用于实现功能,例如 权限校验、日志记录、性能监控 等。与拦截器相关的注解主要是通过 配置拦截器来控制其行为,而不是直接通过注解实现。不过,Spring 提供了一些与拦截器配置相关的注解和接口,常见的包括 HandlerInterceptor
接口以及相关的配置注解。
1. @Component
作用
@Component
注解用于将拦截器类标记为 Spring 的 Bean,使其可以被 Spring 容器管理,并通过 Java 配置或 XML 配置进行注册。
特点
- 通过
@Component
将拦截器类加入到 Spring 容器中,确保拦截器能够在应用启动时被扫描到。
示例代码
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Before handler method");
return true;
}
}
详细解释
@Component
:将MyInterceptor
类注册为 Spring 的 Bean,使它能够被 Spring 容器自动管理。- 通过实现
HandlerInterceptor
接口,MyInterceptor
类可以对 HTTP 请求进行拦截,执行预处理逻辑。
这里注解@Component的作用是将 类MyInterceptor(三个拦截器方法preHandle和postHandle和afterCompletion所在的类) 注册为 Spring 的 Bean,这样确保在对HTTP请求进行拦截的时候这个类能被扫描到执行预处理。
2. @Configuration
作用
@Configuration
注解用于定义一个配置类,Spring 会将此类作为配置类进行处理。通过该配置类,我们可以注册拦截器。
特点
- 该注解可以结合
WebMvcConfigurer
接口,用于配置拦截器、视图解析器等。
示例代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
详细解释
@Configuration
:标记WebConfig
为配置类。addInterceptors()
:通过WebMvcConfigurer
接口的方法,将自定义的拦截器注册到 Spring 的拦截器链中。addPathPatterns("/**")
:表示拦截所有路径下的请求。
3. @Order
作用
@Order
注解用于指定多个拦截器的执行顺序。顺序值越小,拦截器的优先级越高,先被执行。
特点
- 可以控制拦截器的顺序,确保某些拦截器优先执行。
示例代码
@Component
@Order(1) // 优先级高
public class FirstInterceptor implements HandlerInterceptor {
// 拦截器代码
}
@Component
@Order(2) // 优先级较低
public class SecondInterceptor implements HandlerInterceptor {
// 拦截器代码
}
详细解释
@Order(1)
:FirstInterceptor
的优先级为 1,表示它会先于其他拦截器执行。@Order(2)
:SecondInterceptor
的优先级为 2,表示它在FirstInterceptor
之后执行。
注解 | 作用 | 示例解释 |
---|---|---|
@Component | 将拦截器类注册为 Spring Bean | 将拦截器类标记为 @Component ,使其被 Spring 容器管理。 |
@Configuration | 标记配置类,通常用于注册拦截器 | 使用 @Configuration 结合 addInterceptors() 方法配置拦截器。 |
@Order | 定义多个拦截器的执行顺序 | @Order(1) 优先级高,@Order(2) 优先级低。 |
九、跨域相关注解
在 Web 开发中,跨域(CORS,Cross-Origin Resource Sharing) 是一个安全策略,限制网页从不同的域名、协议或端口加载资源。为了允许跨域请求,Spring 提供了几种注解来简化跨域资源共享的配置。
1. @CrossOrigin
作用
@CrossOrigin
注解用于允许跨域请求。它可以作用在 控制器类 或 控制器方法 上,用于定义允许来自哪些域的请求可以访问资源,并且可以设置请求的方法、头部、凭证等参数。
特点
- 可以在类或方法上标注,灵活地控制哪些资源允许被跨域访问。
- 支持详细配置,包括允许的源(域名)、HTTP 方法、请求头、凭证等。
示例代码
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://example.com", maxAge = 3600)
public class MyController {
@GetMapping("/data")
public String getData() {
return "This is some data";
}
}
详细解释
@CrossOrigin(origins = "http://example.com")
:允许来自http://example.com
这个源的跨域请求访问该控制器的方法。maxAge = 3600
:在 3600 秒(即 1 小时)内缓存跨域请求的结果,避免每次请求都进行跨域验证。@CrossOrigin
可以配置以下参数:origins
:允许哪些域可以访问资源,如http://example.com
,也可以设置为*
以允许所有域访问。methods
:允许的 HTTP 方法,如GET
、POST
等。allowedHeaders
:允许的请求头。exposedHeaders
:哪些响应头可以暴露给客户端。allowCredentials
:是否允许发送凭证(如 Cookies),默认为false
。
2. @Configuration
配置跨域
作用
在全局配置类中,通过 WebMvcConfigurer
接口配置跨域规则,可以在一个地方集中管理跨域设置,适合需要全局配置跨域请求的场景。
特点
- 适合全局配置,所有路径或某些指定的路径都可以统一设置跨域规则。
- 更灵活,适用于需要为多个控制器或整个应用启用跨域的情况。
示例代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径
.allowedOrigins("http://example.com") // 允许的域
.allowedMethods("GET", "POST") // 允许的 HTTP 方法
.allowCredentials(true) // 允许携带凭证
.maxAge(3600); // 跨域请求的缓存时间
}
}
详细解释
addCorsMappings()
:通过这个方法为所有路径/**
启用跨域请求。allowedOrigins("http://example.com")
:仅允许来自http://example.com
的请求跨域访问。allowedMethods("GET", "POST")
:只允许GET
和POST
方法的跨域请求。allowCredentials(true)
:允许客户端发送 Cookies 等凭证信息。maxAge(3600)
:缓存跨域请求的验证结果,减少跨域请求时的重复检查。
3. @CrossOrigin
与全局配置的区别
@CrossOrigin
注解:适用于控制器类或方法级别的跨域配置,通常用于局部配置某个控制器允许跨域请求,灵活性高,但只影响单个控制器或方法。- 全局配置:通过实现
WebMvcConfigurer
接口进行跨域配置,适合全局管理跨域请求。可以为整个应用或多个控制器统一设置跨域规则。
注解/配置 | 作用 | 适用场景 | 示例解释 |
---|---|---|---|
@CrossOrigin | 控制器类或方法级别的跨域请求配置 | 局部控制器或方法需要允许跨域请求 | 允许来自指定域名、方法的跨域请求,适用于单个控制器的配置。 |
@Configuration 配置跨域 | 全局跨域请求配置 | 全局管理跨域请求,适合大规模应用 | 通过配置类实现全局的跨域控制,适用于需要为整个应用启用跨域。 |
@CrossOrigin
是最常用的注解,允许在控制器类或方法上灵活地设置跨域规则。- 如果需要全局配置跨域规则,可以通过
WebMvcConfigurer
接口进行集中管理。
十、总结
注解类型 | 注解 | 作用 | 说明 |
---|---|---|---|
核心控制器注解 | @Controller , @RestController | 定义类为控制器,处理 HTTP 请求。 | @Controller 返回视图,@RestController 返回 JSON、XML 等数据格式。 |
请求映射注解 | @RequestMapping , @GetMapping , @PostMapping | 将 HTTP 请求映射到控制器的方法上。 | 根据 URL 和请求方法(如 GET、POST)将请求映射到对应的方法。 |
跨域相关注解 | @CrossOrigin | 允许跨域请求访问资源。 | 用于处理跨域资源共享,配置允许的域、HTTP 方法等。 |
拦截器相关方法 | preHandle , postHandle , afterCompletion | 处理请求前后的操作。 | preHandle 预处理,postHandle 方法后处理,afterCompletion 完成请求后的清理工作。 |
拦截器配置注解 | @Configuration | 注册拦截器、配置请求拦截行为。 | 用于通过实现 WebMvcConfigurer 配置拦截器。 |
安全和认证相关注解 | @PreAuthorize , @Secured | 检查用户是否有权限访问控制器方法。 | 进行安全验证,确保用户具备访问资源的权限。 |
请求参数绑定注解 | @RequestParam , @PathVariable , @RequestBody , @ModelAttribute | 将请求中的数据绑定到控制器方法参数。 | 提取 URL 参数、表单数据或 JSON 数据,并绑定到控制器方法参数。 |
响应相关注解 | @ResponseBody | 将控制器方法返回值作为 HTTP 响应体返回。 | 将 Java 对象直接转换为 JSON、XML 等格式并返回。 |
会话和请求作用域注解 | @RequestScope , @SessionScope | 控制 Bean 在请求或会话期间的生命周期。 | @RequestScope 管理请求期间的 Bean 生命周期,@SessionScope 管理会话期间的 Bean 生命周期。 |