前言

公司项目是前后端分离的,为了保证前端传输数据的合法性,对参数进行校验就很有必要。hibernate-validator就是一个不错的参数校验的解决方法。spring-boot-starter-web包里面有hibernate-validator的包,所以不需要引用hibernate validator依赖,直接就可以用。

一、配置validator

Validator是javax包下的一个接口,hibernate对其进行了一系列的实现。我们需要构建Validator,注入spring中,然后就可以直接引用使用了。

先写个配置类,配置一下Validator。

failFast(true)的意思是快速失败,当检测到第一处不符合的时候就直接返回,不再校验下一个参数。

MethodValidationPostProcessor是controller层参数校验必须的一个Bean。

@Configuration
public class ValidatorConfig {@Beanpublic MethodValidationPostProcessor methodValidationPostProcessor() {MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();/**设置validator模式为快速失败返回*/postProcessor.setValidator(validator());return postProcessor;}@Beanpublic Validator validator(){ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ).configure().failFast(true).buildValidatorFactory();Validator validator = validatorFactory.getValidator();return validator;}}

二、设置校验规则

大多数时候,参数校验是对象属性的校验,所以需要对对象的属性设置校验的规则,java和hibernate提供了一系列注解来帮助我们实现规则的设置。

注解 释义
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
以下为Hibernate提供
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内

写一个实体类,使用这些注解,@IsPhone是自定义的注解,后面会说到。

public class User {private Integer id;@NotBlank(message="手机号不能为空")@IsPhoneprivate String phone;@NotEmpty(message = "用户名不能为空")private String username;@Range(min=1,max=200,message="年龄不能小于1大于200")private Integer age;//省略setter和getter
}

二、@RequestBody 请求参数校验

当使用标准的Restful格式的请求时,参数是json格式,参数会自动转为对象。在@RequestBody后面加个@Valid注解就可以进行参数校验了,参数里添加一个BindingResult就可以接受参数校验结果了。当有错误时,可以返回错误结果响应前端了。

 @PutMapping("/user")public ResponseEntity<Object> changeUser(@RequestBody @Valid User user,BindingResult result)throws Exception{if(result.hasErrors()){for (ObjectError error : result.getAllErrors()) {System.out.println(error.getDefaultMessage());}}return ResponseEntity.ok().build();}

三、@RequestParam 请求参数校验

但是当我们使用@RequestParam来接收参数时,再使用上面的方法就不太好使了。毕竟没有自动生成实体类,无法校验实体类里属性的规则。这时候就需要直接在请求参数上进行校验了。

首先,我们要在类上加一个@Validated注解,然后再使用第二部的注解来标明参数的规则。

@RestController
@Validated
public class UserController {@GetMapping("/user")public ResponseEntity<Object> getUser(@NotBlank(message="手机号不能为空")@IsPhone(message="手机号格式不正确")@RequestParam String phone,@NotEmpty(message="用户名不能为空")@RequestParam String username,@Range(min = 1, max = 200, message = "年龄范围为1-200")@RequestParam Integer age)throws Exception{return ResponseEntity.ok().build();}
}

当参数不符合规范的时候,就会抛出ConstraintViolationException,所以我们就要捕获这个异常,响应前端。因为设置了快速失败,所以msg信息里只会有一条错误信息。

@ControllerAdvice
@Component
@Order(1)
public class ValidatorExceptionHandler {@ExceptionHandler(value=ValidationException.class)@ResponseBodypublic Object exceptionHandler(ValidationException e,HttpServletRequest request){String msg = new String();if(e instanceof ConstraintViolationException){ConstraintViolationException exs = (ConstraintViolationException) e;Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();for (ConstraintViolation<?> item : violations) {msg = item.getMessage();}}return ResponseEntity.badRequest().body(msg);}}

四、自定义校验过程

如果要校验的参数不是请求参数或者以上方法都不适用,我们也可以自定义校验的过程。直接注入Validator进行校验即可。

首先写一个存放校验结果的类

import org.apache.commons.lang3.StringUtils;public class ValidationResultBO {private boolean hasErrors = false;private Map<String,String> errorMsgMap = new HashMap<String, String>();//返回错误信息public String getErrorMsg(){return StringUtils.join(errorMsgMap.values().toArray(),",");}//省略setter和getter}

然后自定义校验过程

@Component
public class ValidatorImpl{@Autowiredprivate Validator validator;/*** 实现校验方式并返回检验结果* @param value* @return*/public ValidationResultBO validate(Object value){ValidationResultBO result = new ValidationResultBO();Set<ConstraintViolation<Object>> validateSet = validator.validate(value);if (!validateSet.isEmpty()) {result.setHasErrors(true);validateSet.forEach( (validation) -> {String errorMsg = validation.getMessage();String propertyName = validation.getPropertyPath().toString();result.getErrorMsgMap().put(propertyName, errorMsg);});}return result;}}

这样我们就可以在任何spring管理的类里直接注入ValidatorImpl来进行参数校验了。当校验结果ValidationResultBO里hasErrors为true时,就可以做相应的处理了。

举个栗子:

@Service
public class UserService {private static final Logger logger = LoggerFactory.getLogger(UserService.class);@Autowiredprivate ValidatorImpl validator;public ReturnDataDTO<Object> addUser(String phone,String username,Integer age){User user = new User();user.setPhone(phone);user.setUsername(username);user.setAge(age);logger.info("{}",user);ValidationResultBO validate = validator.validate(user);if (validate.isHasErrors()) {String errorMsg = validate.getErrorMsg();logger.info("错误信息:{}",errorMsg);throw new MyException(111,errorMsg);}return ReturnDataDTO.ok();}}
@RestController
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/user")public ResponseEntity<Object> addUser(@RequestParam String phone,@RequestParam String username,@RequestParam Integer age)throws Exception{userService.addUser(phone, username, age);return ResponseEntity.ok().build();}}

ReturnDataDTO只是封装的返回参数,随便什么都可以。

MyException是全局异常处理自定义的异常,继承RuntimeException。

五、自定义校验注解

有时候我们也会需要其他的校验规则,但是官方没有,怎么办?这个简单,自己实现呗。

照着官方注解的样子写一个。

@Target({ElementType.METHOD,ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {IsPhoneValidator.class})
public @interface IsPhone {String message() default "手机号格式错误";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}

最主要的还是@Constraint这个注解,它指定了实现校验的类。这个类实现了ConstraintValidator接口,主要是重写isValid方法来进行校验。

ConstraintValidator<IsPhone,String>有两个泛型,第一个是自定义的注解,也就是说自定义注解和实现校验的类是互相指定的关系。第二个是校验参数的类型,这里是校验手机号,所以是String。

public class IsPhoneValidator implements ConstraintValidator<IsPhone,String>{@Overridepublic void initialize(IsPhone constraintAnnotation) {}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {if ("".equals(value) || value.equals(null)) {return false;}else{return isPhone(value);}}/** 验证是否为手机号* @param phone* @return*/public static boolean isPhone (String phone){String pattern  = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$";if (Pattern.matches(pattern, phone)) {return true;}else{return false;}}
}

写好的注解,和其他注解使用方法一样,在上文中已经使用过了,再次不再赘述了。

写在最后的话

参数校验有三种使用方法,应该能满足大部分情况下的使用。所以,就这样。

springboot使用validator进行参数校验相关推荐

  1. SpringBoot使用validation-api实现参数校验

    SpringBoot使用validation-api实现参数校验 前言 我们在开发Java项目的时候,经常需要对参数进行一些必填项.格式.长度等进行校验,如果手写代码对参数校验,每个接口会需要很多低级 ...

  2. SpringBoot Validation优雅的参数校验

    前言:大多数项目中都需要后台对传过来的对象进行校验,所以经常需要写一些字段校验的代码,比如特殊字段非空.字段长度限制和邮箱格式验证等等.之前我们可能都是使用if-else-,写这些与业务逻辑关系不大的 ...

  3. SpringBoot @Validated注解实现参数校验

    1. 前言 做web开发有一点很烦人就是要校验参数,基本上每个接口都要对参数进行校验,比如一些格式校验 非空校验都是必不可少的.如果参数比较少的话还是容易 处理的一但参数比较多了的话代码中就会出现大量 ...

  4. 一波带走,SpringBoot 中的各种参数校验方案汇总

    点击关注公众号,实用技术文章及时了解 1.前言 在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点"low".业界有更好的处理方法,分别阐述如下. 2.Path ...

  5. 【Spring】Spring hibernate JSR-303 Validator 自定义参数校验器

    1.概述 在默认的情况下 Spring Boot 会引入关于 Hibernate Validator 机制来支持 JSR-303 验证规范:另外一方面 , 因为业务会 比较复杂,所以需要 自 定义验证 ...

  6. postmapping注解参数说明_这么写参数校验(validator)就不会被劝退了~

    作者: 锦成同学http://juejin.im/post/5d3fbeb46fb9a06b317b3c48 整理:后端技术精选 很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者不断的返回异常时 ...

  7. 参数校验(Validator)

    为什么要用validator 实战演练 1. @Validated 声明要检查的参数 2. 对参数的字段进行注解标注 3. 在全局校验中增加校验异常 4. 测试 自定义参数注解 1. 比如我们来个 自 ...

  8. 校验json格式_不来学一下SpringBoot统一参数校验?

    微服务架构之春招总结:SpringCloud.Docker.Dubbo与SpringBoot 一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官. 金三银四第一天,啃透这些Spr ...

  9. SpringBoot中的Validator参数校验器——通过注解的方式控制controler接收参数的规则

    前言 在日常的接口开发中,经常要对接口的参数做校验,例如,登录的时候要校验用户名密码是否为空.但是这种日常的接口参数校验太烦锁了,代码繁琐又多. Validator框架就是为了解决开发人员在开发的时候 ...

最新文章

  1. API pytorch tensorflow
  2. 2.2版本发布!TensorFlow推出开发者技能证书
  3. 实用的4W、5V直流开关稳压电源电路图及解析
  4. 如何修改 pdf 文件默认的显示图标
  5. Java生鲜电商平台-团购模块设计与架构
  6. 使用Preference保存设置
  7. 你可真行呀的飞鸽传书
  8. Bailian2787 算24【DFS】(POJ NOI0205-1789)
  9. 「leetcode」941. 有效的山脉数组:【双指针】详解
  10. 海思Hi3798MV300_Hi3798MV300H_Datasheet-系统
  11. Centos7.5 安装禅道16.x版本,Linux 安装最新版本的禅道
  12. linux profile文件,全面解析Linux profile文件
  13. VMware Guided Consolidation
  14. 万字吐血好文,一线分析师的4大总结。
  15. python调用chrome插件_使用Python开发chrome插件
  16. 浅析计算机主板故障,浅析计算机主板故障及维修
  17. 计算机学院教师老带新总结,教师“以老带新”工作总结
  18. 六零导航页 (LyLme Spage)网址导航源码
  19. UVA10382 - Watering Grass 题解
  20. Spring Boot 整合dubbo与zookeeper实现不同项目之间数据通过服务的传递

热门文章

  1. 记Linux服务器中的 kdevtmpfsi 挖矿病毒
  2. Python 能说话吗?调用Windows系统自带语音合成
  3. drupal安装模块
  4. 传感器原理与检测技术复习笔记第五章-电容式传感器
  5. java版mc多少钱_我的世界Java版20w48a
  6. 猜字游戏java_Java实现猜字小游戏
  7. 关于控制器及伺服电机的电子齿轮比 的设置
  8. 【VBA研究】Excel条码控件生成的Code-39码不能识别问题
  9. wetool 接入图灵机器人_wetool自动接受新好友wetool使用教程-客服
  10. 轻量化CICD平台建设