优雅的参数校验@Validated 实战 + 统一异常处理返回前端json 最全解析
时间:2024-04-28 16:15:30 来源:网络cs 作者:亙句 栏目:电商平台 阅读:
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,使用@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")@Validatedpublic 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异常。
@Datapublic 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校验,控制台也打印了校验信息,但是前端就是没有收到我们返回的校验信息.是因为我们没有自定义捕获异常后的处理方式,没有返回给前端这些处理信息。
如果要将报错信息返回给前端只需要对信息做统一异常处理就好。
@ControllerAdvicepublic 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}
如果觉得文章对您有用,还请一键三连哦!!!更多实用文章在主页!
本文链接:https://www.kjpai.cn/news/2024-04-28/163278.html,文章来源:网络cs,作者:亙句,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!
上一篇:利用GitLab与jenkins借助webhooks实现代码同步
下一篇:返回列表