Hibernate-Validator(数据校验框架)

Posted 活学编程思想

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate-Validator(数据校验框架)相关的知识,希望对你有一定的参考价值。

目录

一、Hibernate-Validator 简介

hibernate-validatorHibernate项目中的一个数据校验框架,它能够将数据校验从业务代码中脱离出来,增加代码可读性,同时也让数据校验变得更加方便、简单。

官网地址:http://hibernate.org/validator/documentation


二、项目中为什么要用校验框架

Java程序开发中,当你要处理一个程序的业务逻辑时,请求参数的数据校验是必须要处理的。当请求参数格式不正确的时候,需要程序监测到,并且返回对应的错误提示,以此来达到数据校验的目的。对于前后端分离开发过程中,数据校验还需要返回对应的状态码和错误提示信息。

三、添加依赖

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

如果使用了springboot,则不需要引用任何依赖,因为spring-boot-starter-web包中已经包含了Hibernate-Validator 依赖。


四、看一个入门级案例

  • 现有一个实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class StudentPo 
        @NotBlank(message = "用户名不能为空")
        private String name;
    
        @NotBlank(message = "邮箱不能为空")
        private String email;
    
    
  • POST接口控制器
    POST请求必须要加@Valid

    // 注意:@Valid 不加这个注解,@NotBlank注解不生效
    @RestController
    public class StudentPoController 
        @RequestMapping(value = "/addStudent", method = RequestMethod.POST)
        public String addStudent(@Valid @RequestBody StudentPo student)
            System.out.println("student = [" + student + "]");
            return "ok";
        
    
    
  • 用postman测试

  • 这种参数校验出现的异常,我们可以用全局异常处理类处理

    @ControllerAdvice
    public class GlobalExceptionHandler 
        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseBody
        public ResultEntity handleBindException(MethodArgumentNotValidException ex) 
            FieldError fieldError = ex.getBindingResult().getFieldError();
            return ResultEntity.faill(211, fieldError.getDefaultMessage(), null);
        
    
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ResultEntity<T> 
        private Integer code;
    
        private String message;
    
        private T data;
    
        public static <T> ResultEntity<T> faill(Integer code, String msg, T t) 
            return new ResultEntity<T>(code, msg, t);
        
    
    
  • 再次用postman测试

  • 外加一个GET接口的控制器的写法

    // Get请求需要在类上添加@Validated
    @RestController
    @Validated
    public class StudentController 
     
        @RequestMapping(value = "/addStudent1",method = RequestMethod.GET)
        public String addStudent1(@NotBlank(message = "name不能为空") String name)
            System.out.println("name = [" + name + "]");
            return "ok addStudent1";
        
    
    

五、常用注解

注解说明用法例子
@Nul被注释的元素必须为 null
@NotNull被注释的元素必须不为 null@NotNull 用在基本类型
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)被注释的元素的大小必须在指定的范围内,元素必须为集合,代表集合个数
@Pattern(regexp = )正则表达式校验
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Email被注释的元素必须是电子邮箱地址
@Length(min=, max=)被注释的字符串的大小必须在指定的范围内,必须为数组或者字符串,若微数组则表示为数组长度,字符串则表示为字符串长度
@NotEmpty被注释的字符串的必须非空@NotEmpty 用在集合类上面
@Range(min=, max=)被注释的元素必须在合适的范围内
@NotBlank被注释的字符串的必须非空@NotBlank 用在String上面
@URI字符串是否是一个有效的URL

注意:
1.@NotNull:不能为null,但可以为empty(“”," “,” “)
2.@NotEmpty:不能为null,而且长度必须大于0 (” “,” ")
3.@NotBlank:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0(“test”) 即:必须有实际字符


六、使用groups的校验

  • 1、情景说明
    同一个对象要复用,比如UserDTO在更新时候要校验userId,在保存的时候不需要校验userId,在两种情况下都要校验username,那就用上groups了:

  • 第一步:先定义groups的分组接口Create和Update

    import javax.validation.groups.Default;
    
    public interface Create extends Default 
    
    
    import javax.validation.groups.Default;
    
    public interface Update extends Default
    
    
  • 第二步:再在需要校验的地方@Validated声明校验组

    /**
         * 走参数校验注解的 groups 组合校验
         *
         * @param userDTO
         * @return
         */
        @PostMapping("/update/groups")
        public RspDTO update(@RequestBody @Validated(Update.class) UserDTO userDTO) 
            userService.updateById(userDTO);
            return RspDTO.success();
        
    
    
  • 第三步:在DTO中的字段上定义好groups = 的分组类型

    @Data
    public class UserDTO implements Serializable 
    
        private static final long serialVersionUID = 1L;
    
        /*** 用户ID*/
        @NotNull(message = "用户id不能为空", groups = Update.class)
        private Long userId;
    
        /**
         * 用户名
         */
        @NotBlank(message = "用户名不能为空")
        @Length(max = 20, message = "用户名不能超过20个字符", groups = Create.class, Update.class)
        @Pattern(regexp = "^[\\\\u4E00-\\\\u9FA5A-Za-z0-9\\\\*]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
        private String username;
    
        /**
         * 手机号
         */
        @NotBlank(message = "手机号不能为空")
        @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]9$", message = "手机号格式有误", groups = Create.class, Update.class)
        private String mobile;
    
        /**
         * 性别
         */
        private String sex;
    
        /**
         * 邮箱
         */
        @NotBlank(message = "联系邮箱不能为空")
        @Email(message = "邮箱格式不对")
        private String email;
    
        /**
         * 密码
         */
        private String password;
    
        /*** 创建时间 */
        @Future(message = "时间必须是将来时间", groups = Create.class)
        private Date createTime;
    
    
    

hibernate-validator校验框架学习

1、引入jar包

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>2.2.4</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
     <artifactId>javax.el</artifactId>
    <version>2.2.4</version>
</dependency>

注意:

  • 当使用hibernate-validator更高版本时,会报一个java.lang.ClassNotFoundException: javax.el.ELManager错误,目前博主还未找到兼容的方案,因此采用了5.4.1.Final版本。
  • 当不添加javax.el-api和javax.el依赖时,项目也可以运行,因为tomcat容器包含hibernate-validator所依赖的类

2、spring-mvc配置

<mvc:annotation-driven conversion-service="conversionService" validator="validator"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
  <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
  <property name="validationMessageSource" ref="messageSource"></property>
</bean>
<!-- 检验错误信息资源配置文件 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  <property name="basenames">
    <list>
      <value>classpath:validator/validationMessages</value>
    </list>
  </property>
  <!-- 资源文件编码格式 -->
  <property name="fileEncodings" value="utf-8"/>
  <!-- 对资源文件内容的缓存时间,单位秒 -->
  <property name="cacheSeconds" value="120"/>
</bean>

3、在实体上增加相应注解校验信息

private Integer stuId;
@NotBlank(message = "{notnull}")
@Size(max = 20, min = 2, message = "姓名长度在2-20之间")
private String name;
@Max(value = 200, message = "最大年龄200岁")
@Min(value = 6, message = "最小年龄6岁")
private Integer age;

注意:

message=“{notnull}”会去配置的错误文件中查找,即validator/validationMessages.properties文件中查找notnull的配置对应的错误信息。

4、使用方式

a) 自动校验

  在实体上增加@Validated注解,表示要校验这个实体。BindingResult用于接收验证后的错误信息。

@RequestMapping(value = "/add", method = { RequestMethod.GET, RequestMethod.POST })
public String addStudent(Model model, HttpServletRequest request, @Validated Student stu,
        BindingResult bindingResult) {
    if (HttpRequestContext.GET.equalsIgnoreCase(request.getMethod())) {
        return "prictice/student/addStudent";
    } else {
        if (bindingResult.hasErrors()) {
            List<ObjectError> errors = bindingResult.getAllErrors();
            model.addAttribute("errors", errors);
            return "prictice/student/addStudent";
        }
        stu.setRegTime(new Date());
        stu.setStatus(true);
        studentService.addStudent(stu);
        return "redirect:/student/list";
    }
}

b) 主动校验

通过工具类,主动验证某个实体类

新建工具类ValidateUtil.java

public class ValidateUtil {

    public static <T> void validate(T obj) {
        LocalValidatorFactoryBean validator = (LocalValidatorFactoryBean) SpringContextHolder.getBean("validator");
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj);
        Iterator<ConstraintViolation<T>> iter = constraintViolations.iterator();
        while (iter.hasNext()) {
            ConstraintViolation<T> error = iter.next();
            StringBuffer buffer = new StringBuffer().append("[")
                    .append(error.getPropertyPath().toString()).append("]")
                    .append(error.getMessage());
            throw new IllegalArgumentException(buffer.toString());
        }
    }
}

或者可以使用下面的代码获取validator

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

 调用

@RequestMapping(value = "/add")
public String addStudent(@RequestParam Student stu) {
    ValidateUtil.validate(stu);
    return "redirect:/student/list"
}

5、常用注解

注解

作用

AssertTrue

布尔值为真

AssertFalse

布尔值为假

Null

引用为空

NotNull

引用不为空

NotEmpty

字符串引用和值都不是空

Min

数字的最小值

Max

数字的最大值

Past

日期必须是过去

Future

日期必须是未来

Pattern

字符串必须匹配正则表达式

Valid

递归验证引用

Size

验证字符串是否在Size范围内

Email

验证字符串是否是一个有效的电子邮箱

URL

字符串是否是一个有效的URL

注意:

  • @NotEmpty 用在集合类上面
  • @NotBlank 用在String上面
  • @NotNull 用在基本类型上
  • @Email和@URL是Hibernate Validator自定义的,假如使用其他的Bean Validation实现,可能没有这两个注解。
  • 和JPA注解一样,如果验证注解添加到字段上,Hibernate就会直接读取字段的值。如果注解到Getter方法上,Hibernate就会调用方法取得值。在一个类中不要同时应用这两种方式,会导致重复验证的问题。
  • 如果在一个集合上应用Valid注解, Hibernate就会递归验证集合中的每一个元素。



 

以上是关于Hibernate-Validator(数据校验框架)的主要内容,如果未能解决你的问题,请参考以下文章

JSR303校验 —— hibernate-validator实现

Java后端校验-使用hibernate-validator校验JavaBean

Hibernate-Validator框架完成服务端参数据校验(巨详细)

SpringBoot整合Hibernate-Validator校验器

SpringBoot整合Hibernate-Validator校验器

hibernate-validator校验参数(统一异常处理)