Spring 校验(validator,JSR-303)简单实现方式

目录
  • Spring 校验(validator,JSR-303)实现
    • 什么是JSR-303规范
    • 与Spring MVC结合
    • 实体类添加验证注解
    • 控制器验证注解添加
  • Java Hibernate Validator JSR-303验证
    • 集成
    • 使用
    • 注解使用说明

Spring 校验(validator,JSR-303)实现

什么是JSR-303规范

JSR 303是Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是hibernate Validator,此实现与Hibernate ORM没有任何关系。JSR 303用于对Java Bean中的字段的值进行验证。

与Spring MVC结合

Spring-mvc.xml配置:

    <!--JSR-303-->
    <mvc:annotation-driven validator="validator"/>
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="validatemessage"/>
        <property name="useCodeAsDefaultMessage" value="false"/>
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="cacheSeconds" value="60"/>
    </bean>
    <bean  id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <property name="conversionService">
            <bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"></bean>
        </property>
        <property name="validator" ref="validator"/>
    </bean>

实体类添加验证注解

这里贴出部分代码,知道如何加注解即可:

import com.lemontree.common.utils.AjaxResult;
import com.lemontree.common.utils.StringUtil;
import com.lemontree.common.utils.email.EmailUtils;
import org.hibernate.validator.constraints.NotEmpty;
import java.util.Date;
public class User {
    /**
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user.id
     *
     * @mbg.generated Thu Mar 16 13:27:38 CST 2017
     */
    private Integer id;
    /**
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user.user_name
     *
     * @mbg.generated Thu Mar 16 13:27:38 CST 2017
     */
    @NotEmpty(message = "用户名不能为空")
    private String userName;
    /**
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user.password
     *
     * @mbg.generated Thu Mar 16 13:27:38 CST 2017
     */
    @NotEmpty(message = "密码不能为空")
    private String password;
    }

控制器验证注解添加

将@Validated 注解跟在实体类前面,BindingResult紧跟其后:

    @RequestMapping(value = "/login.htm", method = RequestMethod.POST)
    public @ResponseBody AjaxResult login(@Validated User user, BindingResult bindingResult,
                                          HttpServletRequest request, HttpServletResponse response) {
        if (bindingResult.hasErrors()){
            List<FieldError> errorses = bindingResult.getFieldErrors();
            if (CollectionUtils.isNotEmpty(errorses)){
                errorses.forEach(item->{
                    System.out.println(item.getDefaultMessage());
                });
            }
        }
      }

Java Hibernate Validator JSR-303验证

JSR-303是JAVA EE 6中的一项子规范,叫做 Bean Validation,Hibernate Validator是Bean Validation 的参考实现。

实际使用就是通过注解来给字段添加约束,然后校验字段是否符合规范,如果不符合就会抛出异常,以此来减少校验数据的代码,并保证拿到的数据都是符合规范的,也可以和Spring框架配合使用

集成

官方文档

https://mvnrepository.com/artifact/org.hibernate/hibernate-validator

https://mvnrepository.com/artifact/javax.validation/validation-api

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.el</artifactId>
            <version>3.0.1-b09</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

使用

校验对象

public class JsrTest {
    @NotNull(message = "id不能为空!")
    @Min(value = 1, message = "Id只能大于等于1")
    Integer id;
    @NotNull(message = "姓名不能为空!")
    String name;
    public void validateParams() {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();//获取一个验证器
        Set<ConstraintViolation<JsrTest>> violationSet = validator.validate(this);//验证数据,获取到错误集合
        Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();
        if (iterator.hasNext()) {
            String errorMessage = iterator.next().getMessage();//获取到错误信息
            throw new ValidationException(errorMessage);
        }
    }
    public static void main(String args[]) {
        JsrTest req = new JsrTest();
        req.id = 1;
        req.validateParams();
    }
}

像上面那样将在属性上添加注解即可声明约束

校验属性

上面是校验整个对象,也可以单独校验某个字段:

validator.validateProperty(object, "name");

分组校验

public class JsrTest {
    @NotNull(message = "id不能为空!", groups = {ValidationGroup.class})
    @Min(value = 1, message = "Id只能大于等于1")
    Integer id;
    @NotNull(message = "姓名不能为空!", groups = {ValidationGroup.class})
    String name;
    @DecimalMin(value = "1.1")
    double price;
    int date;
    public static void validateParams(JsrTest jsrTest) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<JsrTest>> violationSet = validator.validate(jsrTest, ValidationGroup.class);
        Iterator<ConstraintViolation<JsrTest>> iterator = violationSet.iterator();
        if (iterator.hasNext()) {
            String errorMessage = iterator.next().getMessage();
            throw new ValidationException(errorMessage);
        }
    }
    public static void main(String args[]) {
        JsrTest req = new JsrTest();
        validateParams(req);
    }
    public interface ValidationGroup {
    }
}

分组校验所指定的calss必须是一个接口,可以指定多个

自定义约束

通常情况下,框架提供的注解已经可以满足正常的验证需求,但是我们也可以自定义注解来满足我们的需求

我们这里的例子是所注释的字符串中不能包含指定字符

@Target(FIELD)      //元注解,定义该注解使用在字段上
@Retention(RUNTIME) //定义注解的生命周期
@Constraint(validatedBy = CustomValidator.class)//指明该注解的校验器
@Documented         //表示该注解会被添加到JavaDoc中
public @interface CustomConstraints {
    String message() default "默认异常message";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {}; //这个属性可以用来标注错误的严重等级,但是并不被API自身所使用
    String value() default " ";
}
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
 * 需要实现ConstraintValidator接口
 * 泛型的第一个参数是自定义的注解,第二个参数注解所注释的字段的类型
 */
public class CustomValidator implements ConstraintValidator<CustomConstraints, String> {
    private String value;
    /**
     * 初始化调用,拿到注解所指定的value
     *
     * @param constraintAnnotation
     */
    @Override
    public void initialize(CustomConstraints constraintAnnotation) {
        value = constraintAnnotation.value();
    }
    /**
     * @param value   注释的字段的值
     * @param context
     * @return true 通过验证,false 未通过验证
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value != null && value.contains(this.value)) {
            context.disableDefaultConstraintViolation();//禁用默认的消息
            context.buildConstraintViolationWithTemplate("新添加的错误消息").addConstraintViolation();
            return false;
        }
        return true;
    }
}

然后就可以和其他注解一样使用它了

封装

或者是将验证参数的代码提取去出来,单独写一个方法

    public static void validateParams(Object object) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();//获取一个验证器
        Set<ConstraintViolation<Object>> violationSet = validator.validate(object);//验证数据,获取到错误集合
        Iterator<ConstraintViolation<Object>> iterator = violationSet.iterator();
        if (iterator.hasNext()) {
            String errorMessage = iterator.next().getMessage();//获取到错误信息
            throw new ValidationException(errorMessage);
        }
    }

当然这里也可以不抛出异常,而返回一个boolean值,如何封装看实际需求

配合Spring使用

    @GetMapping("/test")
    public Integer lookCanBuyGoods(@Valid JsrTest req, BindingResult result) throws Exception {
        if (result.hasErrors()) {
            throw new ValidationException(result.getAllErrors().get(0).getDefaultMessage());
        }
        //do something...
        return 1;
    }

@Valid添加这个注解之后就会对参数进行验证,如果在其后没有跟BindingResult,验证不通过就会直接抛出异常,如果添加了BindingResult参数,就不会直接抛出异常,而会把异常信息存储在BindingResult中,供开发者自行处理

如果想要使用分组可以这样

    @GetMapping("/test")
    public Integer test(@Validated (JsrTest.ValidationGroup.class) JsrTest req, BindingResult result) throws Exception {
        if (result.hasErrors()) {
            throw new ValidationException(result.getAllErrors().get(0).getDefaultMessage());
        }
        //do something...
        return 1;
    }

@Validated如果不使用分组其作用和@Valid一致

注解使用说明

Constraint 详细信息
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@PastOrPresent 被注释的元素必须是过去或现在的日期
@Future 被注释的元素必须是一个将来的日期
@FutureOrPresent 被注释的元素必须是将来或现在的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
@Digits(integer =, fraction =) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证
@NotBlank 字符串不能是Null还有被Trim的长度要大于0
@NotEmpty 不能为null,且长度大于0
@Negative 被注释的元素必须是负数
@NegativeOrZero 被注释的元素必须是负数或0
@Positive 必须是正数
@PositiveOrZero 必须是正数或0

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring中校验器(Validator)的深入讲解

    前言 Spring框架的 validator 组件,是个辅助组件,在进行数据的完整性和有效性非常有用,通过定义一个某个验证器,即可在其它需要的地方,使用即可,非常通用. 应用在执行业务逻辑之前,必须通过校验保证接受到的输入数据是合法正确的,但很多时候同样的校验出现了多次,在不同的层,不同的方法上,导致代码冗余,浪费时间,违反DRY原则. 每一个控制器都要校验 过多的校验参数会导致代码太长 代码的复用率太差,同样的代码如果出现多次,在业务越来越复杂的情况下,维护成本呈指数上升. 可以考虑把校验的代

  • SpringMVC实现Validation校验过程详解

    这篇文章主要介绍了SpringMVC实现Validation校验过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.概述 对前端的校验大多数通过js在页面校验,这种方法比较简单,如果对安全性考虑,还要在后台校验. springmvc使用JSR-303(javaEE6规范的一部分)校验规范,springmvc使用的是Hibernate Validator(和Hibernate的ORM) 二.步骤 2.1 引入 Hibernate Vali

  • SpringBoot后端进行数据校验JSR303的使用详解

    如果只想查看注解,请跳到文章末尾部分 简介 在前后端进行数据交互中,在前端把数据传送到后端前,一般会先进行校验一次,校验成功之后,才把数据发送到后端.但是我们在服务端还得在对数据进行一次校验.因为请求数据发送的链接很容易获取,可以不经过前端界面,使用postman等工具直接向后台发送数据,这就可能造成发送的数据是不合法的情况. 项目创建 首先创建一个springboot项目 使用的springboot版本为:(本文代码以该版本为准,不同版本springboot,在下面内容会出现一些差异) <pa

  • Spring 校验(validator,JSR-303)简单实现方式

    目录 Spring 校验(validator,JSR-303)实现 什么是JSR-303规范 与Spring MVC结合 实体类添加验证注解 控制器验证注解添加 Java Hibernate Validator JSR-303验证 集成 使用 注解使用说明 Spring 校验(validator,JSR-303)实现 什么是JSR-303规范 JSR 303是Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是hibernate Validator,此实现与Hib

  • Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化

    导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.5.Final</version> </dependency> <dependency> <

  • spring boot整合scurity做简单的登录校验的实现

    开发环境:springboot maven引入: <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> &

  • SpringBoot参数校验Validator框架详解

    目录 SpringBoot 如何进行参数校验 1.集成Validator校验框架 1.1. 引入依赖包 1.2. 定义要参数校验的实体类 1.3. 定义校验类进行测试 1.4. 测试结果1 1.5. 问题 1.6. 将参数异常加入全局异常 1.7. 测试结果2 2. 自定义注解 2.1. 第一步,创建自定义注解 2.2. 第二步,自定义校验逻辑 2.3. 第三步,在字段上增加注解 2.4. 第四步,体验效果 3. 分组校验 3.1. 第一步,定义分组接口 3.2. 第二步,在模型中给参数分配分组

  • SprinBoot如何集成参数校验Validator及参数校验的高阶技巧

    目录 为什么需要参数校验 SpringBoot中集成参数校验 第一步,引入依赖 第二步,定义要参数校验的实体类 第三步,定义校验类进行测试 第四步,体验效果 参数异常加入全局异常处理器 体验效果 自定义参数校验 第一步,创建自定义注解 第二步,自定义校验逻辑 第三步,在字段上增加注解 第四步,体验效果 分组校验 第一步:定义分组接口 第二步,在模型中给参数分配分组 第三步,给需要参数校验的方法指定分组 第四步,体验效果 小结 前几天写了一篇<SpringBoot如何统一后端返回格式?老鸟们都是这

  • Spring Boot的listener(监听器)简单使用实例详解

    监听器(Listener)的注册方法和 Servlet 一样,有两种方式:代码注册或者注解注册 1.代码注册方式 通过代码方式注入过滤器 @Bean public ServletListenerRegistrationBean servletListenerRegistrationBean(){ ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean

  • spring boot使用sharding jdbc的配置方式

    本文介绍了spring boot使用sharding jdbc的配置方式,分享给大家,具体如下: 说明 要排除DataSourceAutoConfiguration,否则多数据源无法配置 @SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class Application { public static void main(String[] arg

  • Spring Boot配置过滤器的2种方式示例

    前言 过滤器(Filter)是Servlet中常用的技术,可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,常用的场景有登录校验.权限控制.敏感词过滤等,下面介绍下Spring Boot配置过滤器的两种方式. 一.@WebFilter注解方式 使用@WebFilter注解为声明当前类为filter,第一个参数为该filter起一个名字,第二个参数为说明要拦截的请求地址,当前类需要实现Filter接口,里面有三个方法,分别为过滤器初始化.过滤方法和过滤器销毁. @Slf4j @Web

  • Spring Bean初始化及销毁多种实现方式

    这篇文章主要介绍了Spring Bean初始化及销毁多种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean 生命周期,可以在 Bean 创建过程初始化资源,以及销毁 Bean 过程释放资源.Spring 提供多种不同的方式初始化/销毁 Bean,如果同时使用这几种方式,Spring 如何处理这几

  • Spring Data Jpa的四种查询方式详解

    这篇文章主要介绍了Spring Data Jpa的四种查询方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> 使用这

随机推荐