千家信息网

Spring如何实现校验validator和JSR-303

发表于:2024-09-23 作者:千家信息网编辑
千家信息网最后更新 2024年09月23日,这篇文章将为大家详细讲解有关Spring如何实现校验validator和JSR-303,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Spring 校验(valida
千家信息网最后更新 2024年09月23日Spring如何实现校验validator和JSR-303

这篇文章将为大家详细讲解有关Spring如何实现校验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配置:

                                                                                                                

实体类添加验证注解

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

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 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

            org.hibernate            hibernate-validator            6.0.10.Final                            org.glassfish            javax.el            3.0.1-b09                            javax.validation            validation-api            2.0.1.Final        

使用

校验对象

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> violationSet = validator.validate(this);//验证数据,获取到错误集合        Iterator> 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> violationSet = validator.validate(jsrTest, ValidationGroup.class);        Iterator> 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[] payload() default {}; //这个属性可以用来标注错误的严重等级,但是并不被API自身所使用    String value() default " ";}
import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;/** * 需要实现ConstraintValidator接口 * 泛型的第一个参数是自定义的注解,第二个参数注解所注释的字段的类型 */public class CustomValidator implements ConstraintValidator {    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> violationSet = validator.validate(object);//验证数据,获取到错误集合        Iterator> 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

关于"Spring如何实现校验validator和JSR-303"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0