提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 1 简述
- 1.1 @Validated作用
- 1.2 所有参数注解含义
- 1.3 异常处理
- 1.4 @Valid和@Validated比较
- @Valid级联校验
- 2.@Validated 分组校验
- 1.1为何要分组校验?
- 1.2 代码案例
- 1.3 @Validated分组校验顺序
- 分组校验顺序通过==使用 @GroupSequence注解==实现
- 3.@Validated的使用方法
- 3.1 在方法级别上使用@Validated
- 3.2 在==类级别==上使用@Validated
- 3.2 Get请求参数校验
1 简述
- @Validated是Spring框架中的一个注解,它是JSR-303规范的扩展,可以用于在方法级别上校验方法参数。
- 它可以用于验证请求参数和请求体中的数据。@Validated注解可以用于方法级别和类级别上,用于验证方法参数和类属性。
1.1 @Validated作用
@Validation是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束。
- @Validated作用在类、方法和参数上
1.2 所有参数注解含义
1.3 异常处理
错误的状态码:返回的响应码推荐使用400 bad request.
说明:若不做异常处理,@Validated注解的默认异常消息如下(示例):
2020-09-05 21:48:38.106 WARN 9796 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.bind.MethodArgumentNotValidException:
Validation failed for argument [0] in public java.lang.String com.example.validateddemo.controller.DemoController.validatedDemo1(com.example.validateddemo.entity.dto.UseDto):[Field error in object 'useDto' on field 'username': rejected value [null]; codes [NotBlank.useDto.username,NotBlank.username,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [useDto.username,username]; arguments []; default message [username]]; default message [用户名不能为空!]] ]
package com.example.validateddemo.handler;import com.example.validateddemo.base.Result;
import com.example.validateddemo.enums.ResultEnum;
import com.example.validateddemo.utils.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.util.List;@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {/*** 处理@Validated参数校验失败异常* @param exception 异常类* @return 响应*/@ResponseBody@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(MethodArgumentNotValidException.class)public Result exceptionHandler(MethodArgumentNotValidException exception){BindingResult result = exception.getBindingResult();StringBuilder stringBuilder = new StringBuilder();if (result.hasErrors()) {List<ObjectError> errors = result.getAllErrors();if (errors != null) {errors.forEach(p -> {FieldError fieldError = (FieldError) p;log.warn("Bad Request Parameters: dto entity [{}],field [{}],message [{}]",fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());stringBuilder.append(fieldError.getDefaultMessage());});}}return ResultUtil.validatedException(stringBuilder.toString());}
}
1.4 @Valid和@Validated比较
Spring Boot–09–注解@Valid
- @Valid支持级联校验,而@Validated不行
- @Validated支持分组校验,而@Valid不行
@Valid级联校验
级联校验: 也叫嵌套检测.嵌套就是一个实体类包含另一个实体类
@Valid和可以用在成员属性的字段上,因此 @Valid可以提供级联校验
@Data
public class Hair {@NotBlank(message = "头发长度必须提交!")private Double length;@NotBlank(message = "头发颜色必须提交!")private String color;
}@Data
public class Person {@NotBlank(message = "用户姓名必须提交!")@Size(min=2, max=8)private String userName;// 添加@Valid注解实现嵌套检测@Valid@NotEmpty(message = "用户要有头发!")private List<Hair> hairs;
}@PostMapping("/person")
public Result addPerson(@Valid @RequestBody Person person) {return Result.buildSuccess(person);
}
只是在方法参数前面添加 @Valid和 @Validated注解,不会对嵌套的实体类进行校验.要想实现对嵌套的实体类进行校验,需要在嵌套的实体类属性上添加 @Valid注解
2.@Validated 分组校验
1.1为何要分组校验?
假设有这样一种场景:
我们使用同一个VO(Request)类来传递save和update方法的数据,
- 但对于save方法来说,通常有框架帮我们生成id,我们不需要传id此时需要使用注解@Null表名id数据必须为空。
- 但对于update方法,我们必须传id才能进行update操作,所以同一个字段面对不同的场景不同需求就可以使用分组校验。
1.2 代码案例
(1)创建分组接口
这里并不需要实现编写什么代码,标明分类。
//分组接口 1
public interface InsertGroup {
}//分组接口 2
public class UpdateGroup {
}
(2)Request实体类
@Data
@NoArgsConstructor
public class TestRequest {@Null(message = "无需传id",groups = InsertGroup.class)@NotBlank(message = "必须传入id",groups = UpdateGroup.class)private String id;}
(3)controller接口
@RequestMapping("/valid/test")public ResponseEntity<ResponseResult> test(@Validated({UpdateGroup.class})@RequestBody TestRequest request) {System.out.println(request);return null;}
(4)postman测试
(5)注意事项!!!
当我们在controller层指定分组后,属性上没有表名分组的校验还执行么?
下面的Request实体中,id进行了分组,address没有进行分组:
@Data
@NoArgsConstructor
public class TestRequest {@Null(message = "无需传id",groups = InsertGroup.class)@NotBlank(message = "必须传入id",groups = UpdateGroup.class)private String id;@Length(max = 3, message = "address最大长度是3")private String address;}
postman测试:
如下图,校验没有成功!!!!说明一旦开启了分组校验,就必须把所有的校验规则都指定组别,不然不生效。
1.3 @Validated分组校验顺序
默认情况下,分组间的约束是无序的,但是在一些特殊的情况下可能对分组间的校验有一定的顺序
- 比如第二组的分组的约束的校验需要依赖第一组的稳定状态来进行,此时,要求分组间的约束校验一定要有顺序
分组校验顺序通过使用 @GroupSequence注解实现
@Data
public class UserGroupSequence {public interface FirstGroup {}public interface SecondGroup {}// 使用GroupSequence定义分组校验顺序:按照FirstGroup,SecondGroup分组顺序进行校验@GroupSequence({FirstGroup.class, SecondGroup.class})public interface Group {}@NotEmpty(message = "用户ID必须提交!", group = FirstGroup.class)private String userId;@NotEmpty(message = "用户姓名必须提交!", group = FirstGroup.class)@Size(min = 2, max = 8, message = "用户姓名的长度在2~8之间", goup = Second.class)private String userName;
}
Controller
@RestController
@RequestMapping("/user")
public class UserGroupSequenceController {// 这里方法中@Validated注解value的值是Group.class@PostMapping("/user")public Result addGroup(@Validated(value = Group.class) @RequestBody UserGroupSequence user) {return Result.buildSuccess(user);}
}
使用 @GroupSequence注解指定分组校验顺序后,第一组分组的约束的校验没有通过后,就不会进行第二组分组的约束的校验
3.@Validated的使用方法
3.1 在方法级别上使用@Validated
在方法级别上使用@Validated注解,需要在方法参数上添加该注解。下面是一个简单的示例,演示了如何在方法级别上使用@Validated注解。
@RestController
@RequestMapping("/users")
public class UserController {@PostMappingpublic User createUser(@RequestBody @Validated User user) {// 处理用户创建逻辑}}
在上面的示例代码中,@Validated注解被应用在User对象上,用于验证请求体中的数据是否符合要求。
3.2 在类级别上使用@Validated
在类级别上使用@Validated注解,需要在类上添加该注解。下面是一个简单的示例,演示了如何在类级别上使用@Validated注解。
@RestController
@RequestMapping("/users")
@Validated
public class UserController {@PostMappingpublic User createUser(@RequestBody User user) {// 处理用户创建逻辑}}
在上面的示例代码中,@Validated注解被应用在UserController类上,用于验证该类中所有方法的参数是否符合要求。
3.2 Get请求参数校验
get参数校验,需要在类上加@Validated
@RestController
@Slf4j
@RequestMapping("/api/test")
@Validated
public class TestController {@GetMapping(value = "/h11")public String test11( @NotEmpty(message = "姓名不能为空") String name) {System.out.println("kaidsd");System.out.println(name);return "applyInfoDTO";}
}