|
|
java中@Validated和@RequestBody的用法和作用先说 `@Validated` 的基本功能,然后结合 `@RequestBody SendCodeRequest` 在 Controller 上的典型用法,解释它和 `@Valid` 的区别、触发时机、配合你的 `GlobalExceptionHandler` 的行为。
**1. `@Validated` 的基本作用**
- 用来 **启用 Spring 的校验(JSR-303/JSR-380 Bean Validation)**。
- 常配合参数对象上面的约束注解一起用,比如:
- `@NotNull`, `@NotBlank`, `@Size`, `@Pattern`, `@Email` 等。
- 标在:
- **方法参数**上:`(@Validated @RequestBody SendCodeRequest request)`
- 或 **类上**:`@Validated`(比如在 Service 类上启用方法级校验或分组校验)。
**2. 和 `@RequestBody SendCodeRequest` 一起时的流程**
在 Controller 里类似这样:
```java
@PostMapping("/sendCode")
public ResultUtil sendCode(@Validated @RequestBody SendCodeRequest request) {
...
}
```
执行流程大致是:
1. Spring MVC 先根据请求 JSON 把 body 反序列化为 `SendCodeRequest` 对象。
2. 因为参数上有 `@Validated`,Spring 会对 `SendCodeRequest` 对象做 **参数校验**:
- 读取 `SendCodeRequest` 类里的注解,比如:
```java
public class SendCodeRequest {
@NotBlank(message = "手机号不能为空")
private String phone;
...
}
```
3. 如果校验 **通过**:方法正常继续执行。
4. 如果校验 **不通过**:
- Spring 抛出 `MethodArgumentNotValidException`(你已经在 `GlobalExceptionHandler` 里处理了)。
- 你的 `GlobalExceptionHandler` 会捕获这个异常,拿到校验失败信息,最终返回 `ResultUtil.error(400, message)`。
也就是说:`@Validated` + 约束注解 + 你的全局异常处理器,构成一套「自动参数校验 → 统一错误返回」机制。
**3. `@Validated` vs `@Valid`**
两者都能触发 Bean Validation,但有几点差别:
- `@Valid`:标准 JSR-303 注解(javax.validation / jakarta.validation),**不支持分组**。
- `@Validated`:Spring 提供的注解,**支持分组校验**。
- 例如:
```java
@Validated(CreateGroup.class)
public class UserController { ... }
```
- 或在参数上:
```java
public ResultUtil createUser(@Validated(CreateGroup.class) @RequestBody UserDto dto)
```
- 这样只会校验标了 `groups = CreateGroup.class` 的约束。
在你现在这种最常见写法(不分组)下,`@Validated` 和 `@Valid` 的效果基本一样,只是用了 Spring 的扩展版本。
**4. 和你项目里 `GlobalExceptionHandler` 的关系**
你有如下处理器(简化):
```java
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResultUtil handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
String message = fieldErrors.isEmpty() ? "参数校验失败" : fieldErrors.get(0).getDefaultMessage();
return ResultUtil.error(400, message);
}
```
当 `@Validated @RequestBody SendCodeRequest request` 校验失败时:
- 抛出 `MethodArgumentNotValidException`
- 被上面这个方法捕获
- 返回统一格式:`{ "code": 400, "msg": "xxx", "data": null }`
所以:**`@Validated` 的核心作用,就是在请求进入业务之前,用 Bean Validation 帮你自动校验 `SendCodeRequest`,配合全局异常处理,实现统一的参数错误响应。**
**5. 简单示例帮助理解**
假设 `SendCodeRequest` 是这样:
```java
public class SendCodeRequest {
@NotBlank(message = "手机号不能为空")
private String phone;
// getter/setter...
}
```
Controller:
```java
@PostMapping("/sendCode")
public ResultUtil sendCode(@Validated @RequestBody SendCodeRequest request) {
// 这里能执行,说明 phone 已经通过「非空」校验
return ResultUtil.success(null);
}
```
- 请求 body:
```json
{ "phone": "" }
```
- 结果:
- 方法体不会进入
- 直接触发 `MethodArgumentNotValidException`
- 最终返回:`code=400, msg="手机号不能为空"`(来自你的全局异常处理器)
|
|