SpringMVC(八)使用@Valid注解实现后台表单校验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ditto_zhou/article/details/83009122

目录

 

依赖jar

配置spring对@valid注解的支持

JSR303定义的校验类型

如何使用

创建一个pojo类

controller中触发参数校验

硬编码校验

使用AOP的方式实现校验


依赖jar

        <dependency>  
            <groupId>javax.validation</groupId>  
            <artifactId>validation-api</artifactId>  
            <version>1.1.0.Final</version>  
        </dependency>  
        <dependency>  
            <groupId>org.hibernate</groupId>  
            <artifactId>hibernate-validator</artifactId>  
            <version>5.2.1.Final</version>  
        </dependency>

 @valid,java的jsr303声明了这类接口,hibernate-validator对接口进行实现

配置spring对@valid注解的支持

< mvc:annotation-driven/>  

JSR303定义的校验类型

空检查

@Null       验证对象是否为null

@NotNull    验证对象是否不为null, 无法查检长度为0的字符串

@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

 

Booelan检查

@AssertTrue     验证 Boolean 对象是否为 true  

@AssertFalse    验证 Boolean 对象是否为 false  

 

长度检查

@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  

@Length(min=, max=) Validates that the annotated string is between min and max included.

 

日期检查

@Past           验证 Date 和 Calendar 对象是否在当前时间之前  

@Future     验证 Date 和 Calendar 对象是否在当前时间之后  

@Pattern    验证 String 对象是否符合正则表达式的规则

 

数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null

@Min            验证 Number 和 String 对象是否大等于指定的值  

@Max            验证 Number 和 String 对象是否小等于指定的值  

@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

@Digits     验证 Number 和 String 的构成是否合法  

@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

 

@Range(min=, max=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum.

@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;

 

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

@CreditCardNumber信用卡验证

@Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。

@ScriptAssert(lang= ,script=, alias=)

@URL(protocol=,host=, port=,regexp=, flags=)

需要注意的是,NotEmpty,NotNull,NotBlank的区别

@NotEmpty 用在集合上

@NotNull用在基本类型上

@NotBlank用在String上

如何使用

创建一个pojo类

对于类中需要校验的字段,加上需要的校验注解

public class Book implements Serializable {

    /**
     * 编号
     */
    private Integer id;

    /**
     * 书名
     */
    @NotEmpty(message = "书名不能为空")
    private String name;

    /**
     * 作者
     */
    @NotEmpty(message = "作者不能为空")
    private String writer;

    /**
     * 简介
     */
    @NotEmpty(message = "简介不能为空")
    private String introduction;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public String getIntroduction() {
        return introduction;
    }

    public void setIntroduction(String introduction) {
        this.introduction = introduction;
    }
}

controller中触发参数校验

只需要在提交的校验pojo前面加上@Valid注解,BindingResult的hasError方法检查是否字段校验失败

 public static boolean validate(BindingResult result, Model model) {
        boolean validateResult = false;
        if (result.hasErrors()) {
            validateResult = true;
            if (model != null) {
                FieldError error = result.getFieldErrors().get(0);// 为了避免大量的校验在前端堆积,影响用户体验,只返回一个错误提示
                logger.debug("validate error: " + error.getDefaultMessage());
                model.addAttribute("msg", error.getDefaultMessage());
            }
        }
        return validateResult;
    }

    @RequestMapping("/update")
    public String updateBook(@Valid Book book,BindingResult bindingResult,Model model){
        if(BookController.validate(bindingResult,model)){
            model.addAttribute("action","update");
            return  "bookDetail";
        }
        service.updateBook(book);
        return "redirect:/book";
    }

错误信息的展示,前段使用thymeleaf模板的话,可以使用th:error输出错误信息。

硬编码校验

如果注解@Valid失效情况,可以使用下面方式进行校验

 /**
     * 返回空,表示校验成功,否则校验失败
     * @param object
     * @param <T>
     * @return
     */
    private <T> String  validateParam(T object){
        Validator validator =  Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<T>>  set =  validator.validate(object);
        if(set!=null&&set.size()>0){
            StringBuilder sb = new StringBuilder();
            for (ConstraintViolation<T> ct: set
            ) {
               if(ct.getMessage()!=null&&ct.getMessage().trim().length()>0){
                   sb.append("field:"+ct.getPropertyPath()+",error message:"+ct.getMessage());
               }

            }
            return sb.toString();
        }
        return null;
    }

使用AOP的方式实现校验

对需要参数校验的方法,织入增强,减少代码

@Aspect
@Component
public class CustomerValidatorAOP {
    @Before("execution(* com.example.chapter_1_web.controller.*.update*(..))")
    public void validatorBook(JoinPoint point) {
        //返回目标方法的参数
        Object[] objects =  point.getArgs();
        //获取目标方法签名
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        //获取方法注解
        Annotation[] annotationList = method.getAnnotations();
        //参数注解
        Annotation[][] argAnnotations = method.getParameterAnnotations();
        //参数名称
        String[] argNames = methodSignature.getParameterNames();
        Validator validator =  Validation.buildDefaultValidatorFactory().getValidator();
        for(int i = 0;i<objects.length;i++){
            //如果参数有BingResult,获取错误信息
            if(objects[i] instanceof  BindingResult){
                BindingResult result = (BindingResult) objects[i];
                if(result.hasErrors()){
                    FieldError error = result.getFieldError();
                    //获取错误信息
                    String errorMsg = error.getDefaultMessage();
                    ServletRequestAttributes req = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
                    HttpServletResponse rsp  =  req.getResponse();
                    //如果是返回的是json数据就可以将数据写回,省略。。
                }
            }
        }
    }
}

参考博客:

https://blog.csdn.net/DuShiWoDeCuo/article/details/79080237

https://my.oschina.net/itblog/blog/211693

http://exceptioneye.iteye.com/blog/1305040

猜你喜欢

转载自blog.csdn.net/Ditto_zhou/article/details/83009122