数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,使用@Valid和@Validated注解可以很好的避免后端代码满屏if-else。
1 引入依赖
springboot版本小于2.3时spring-boot-starter-web包含了依赖不用再引入
当springboot版本大于2.3时需要手动引入依赖
<!--第一种方式导入校验依赖:使用springboot时,在org\springframework\spring-context\5.2.1.RELEASE\spring-context-5.2.1.RELEASE.jar-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--第二种方式导入校验依赖-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--第三种方式导入校验依赖-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
2 @Valid和@Validated的用法(区别)
二者主要作用在于 都作为标准JSR-303规范,在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同:
@Valid注解用于校验,所属包为:javax.validation.Valid。
用在方法入参上无法单独提供嵌套验证功能。**能够用在成员属性(字段)**上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
@Validated是@Valid 的一次封装,是Spring提供的校验机制使用。
用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
3 常用校验注解
@NotEmpty 被注释的字符串的不能为 null 也不能为空
@NotBlank 被注释的字符串非 null,并且必须包含一个非空白字符
@Null 被注释的元素(数字)必须为 null
@NotNull 被注释的元素(数字)必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Pattern(regex=,flag=)被注释的元素必须符合指定的正则表达式
@Email 被注释的元素必须是 Email 格式。
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素(集合)的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
4 参数校验
4.1 控制器上加校验注解
千万不要忘记在类上加@Validated注解,否则验证注解不生效
@RestController
@Api("阅读记录")
@RequestMapping("/record")
@Validated
public class ReadRecordController {
@Autowired
private ReadRecordService readRecordService;
@PostMapping("/addRecord")
@ApiOperation("新增阅读记录")
public ResponseResult addRecord(@RequestBody @Valid ReadRecord readRecord){
return readRecordService.addRecord(readRecord);
}
@ApiOperation("查询阅读记录")
@GetMapping("/getReadRecord")
public ResponseResult getReadRecord(@Valid @NotBlank(message = "fileCode不能传空值") String fileCode){
return readRecordService.getReadRecord(fileCode);
}
}
4.2 实体类上加校验注解
对接受实体加注解的字段进行校验,如果验证失败,它将抛出MethodArgumentNotValidException异常。
@Data
public class ReadRecord {
private String id;
private String companyName;
private String deleteFlag;
@NotBlank(message = "loginName不能传空")
private String loginName;
@NotBlank(message = "fileCode不能传空")
private String fileCode;
}
5 自定义注解
如果在写项目的过程中,参数需要的条件注解满足不上,则我们需要自定义注解来完成
5.1 创建一个自定义的注解类
@Documented
@Constraint(validatedBy = PhoneNumberValidator.class)
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public@interface PhoneNumber {
String message() default "Invalid phone number";
Class[] groups() default {};
Class[] payload() default {};
}
5.2 创建一个逻辑处理数据的方法
publicclass PhoneNumberValidator implements ConstraintValidator<PhoneNumber,String> {
@Override
public boolean isValid(String phoneField, ConstraintValidatorContext context) {
if (phoneField == null) {
// can be null
returntrue;
}
return phoneField.matches("^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|70)\\d{8}$") && phoneField.length() > 8 && phoneField.length() < 14;
}
}
5.3使用自定义注解
@PhoneNumber(message = "phoneNumber 格式不正确")
@NotNull(message = "phoneNumber 不能为空")
private String phoneNumber;
6 统一异常处理
我们使用了@valiated注解,也写了@NotBlank校验,控制台也打印了校验信息,但是前端就是没有收到我们返回的校验信息.是因为我们没有自定义捕获异常后的处理方式,没有返回给前端这些处理信息。
如果要将报错信息返回给前端只需要对信息做统一异常处理就好。
@ControllerAdvice
public class CustomHandle {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseResult methodArgumentNotValidException(MethodArgumentNotValidException e){
List<ObjectError> allErrors = e.getAllErrors();
List<String> collect = allErrors.stream()
.map(error -> error.getDefaultMessage())
.collect(Collectors.toList());
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,collect.toString());
}
}
至此便可将报错信息返回前端
{
"token": null,
"code": 501,
"message": "[loginName不能传空]",
"data": null,
"status": null
}
如果觉得文章对您有用,还请一键三连哦!!!更多实用文章在主页!