hibernate Validator使用

概述

在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,所以java的JSR 303: Bean Validation 1.0 规范就是解决这个问题的。JSR 303只是个规范,并没有具体的实现,目前通常都是hibernate-validator进行统一参数校验。

开始使用

  • 环境 springboot 2.0.3
  • IDE IDEA
  • hibernate-validator 5.3.4

依赖导入

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.4.Final</version>
</dependency>

校验对象数据

import javax.validation.constraints.*;  // 注:不是用org.hibernate.validator.constraints
public class DemoModel {

    @NotBlank(message="用户名不能为空")
    @Length(min = 1, max = 20, message = "用户名应为1~20个字符")
    private String userName;

    @NotBlank(message="年龄不能为空")
    @Pattern(regexp="^[0-9]{1,2}$",message="年龄不正确")
    @Min(value = 18, message = "用户年龄必须大于18岁")
    @Max(value = 150, message = "用户年龄必须小于150岁")
    private String age;

    @AssertFalse(message = "必须为false")
    private Boolean isFalse;

    //如果是空,则不校验,如果不为空,则校验
    @Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",message="出生日期格式不正确")
    private String birthday;

    @NotEmpty
    @Email(message = "邮箱格式不正确")
    private String email;

    // get set 省略.....
}

校验方法

注解校验

import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;

@RestController
@RequestMapping(value = "/demo")
public class HibernateValidatorController {

    @PostMapping("/2")
    public void demo2(@RequestBody @Valid DemoModel demo, BindingResult result){
        //POST请求传入的参数:{"userName":"dd","age":160,"isFalse":true,"birthday":"21010-21-12","email":"alanchen@"}
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
                System.out.println(error.getDefaultMessage());
            }
        }
    }
}

自定义校验工具类

/*
 * Copyright 2014-2018 nickboyer.cn.
 * All rights reserved.
 */
package cn.nickboyer.pms.core.utils;


import cn.nickboyer.pms.core.exception.SystemException;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * @author Kang.Y
 * @Date 22:28 2018/11/29
 * @since 1.8
 */
public class ValidationUtil {

    private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    /**
     * 属性校验
     * @param t
     * @param <T>
     */
    public static <T> void validate(T t) {
        if(t != null){
            Set<ConstraintViolation<T>> set = validator.validate(t);
            for (ConstraintViolation<T> item : set) {
                throw new SystemException(item.getMessageTemplate());
            }
        }
    }
}


/*
 * Copyright 2014-2018 nickboyer.cn.
 * All rights reserved.
 */
package cn.nickboyer.pms.api.interceptor;

import cn.nickboyer.pms.api.common.ReqDto;
import cn.nickboyer.pms.api.common.RspBuilder;
import cn.nickboyer.pms.api.exception.BusinessCode;
import cn.nickboyer.pms.core.exception.BusinessException;
import cn.nickboyer.pms.core.exception.SystemException;
import cn.nickboyer.pms.core.utils.ValidationUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 系统处理拦截,用途:
 *  1. 请求传输对象校验
 *  2. 通用异常处理
 *
 * @author Kang.Y
 * @Date 17:02 2018/11/29
 * @since 1.8
 */
@Aspect
@Component
public class ControllerInterceptor {

    private static Logger logger = LoggerFactory.getLogger(ControllerInterceptor.class);


    @Pointcut("execution(public * cn.nickboyer.pms.api.modules..controller..*.*(..))")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint pjp) {
        ReqDto reqDto = null;
        for (Object obj : pjp.getArgs()) {
            if (obj instanceof ReqDto) {
                reqDto = (ReqDto) obj;
            }
        }
        try {
            ValidationUtil.validate(reqDto);
            return pjp.proceed();
        } catch (BusinessException e) {
            logger.error("", e);
            return RspBuilder.error(reqDto, e.getCode(), e.getMessage());
        } catch (SystemException e) {
            logger.error("", e);
            return RspBuilder.error(reqDto, BusinessCode.PR9998, e.getMessage());
        } catch (Throwable e) {
            logger.error("", e);
            return RspBuilder.error(reqDto, BusinessCode.PR9999, "未知异常");
        }
    }
}

自定义

通常有少许校验情况特殊,需要自定义校验

自定义注解

/*
 * Copyright 2014-2018 nickboyer.cn.
 * All rights reserved.
 */
package cn.nickboyer.pms.api.common.validate;

/**
 * @author Kang.Y
 * @Date 11:53 2018/12/10
 * @since 1.8
 */

import org.apache.ibatis.annotations.Insert;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.List;

@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)
public @interface EnumCheck {

    /**
     * 自定义部分
     */
    String[] allows();

    /**
     * 自定义错误信息
     */
    String message() default "{cn.nickboyer.pms.api.common.validate.EnumCheck.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

自定义注解对应校验方法

/*
 * Copyright 2014-2018 nickboyer.cn.
 * All rights reserved.
 */
package cn.nickboyer.pms.api.common.validate;

import org.apache.commons.lang3.StringUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

/**
 * @author Kang.Y
 * @Date 12:29 2018/12/10
 * @since 1.8
 */
public class EnumValidator implements ConstraintValidator<EnumCheck, String> {

    private List<String> allows;

    @Override
    public void initialize(EnumCheck constraintAnnotation) {
        allows = Arrays.asList(constraintAnnotation.allows());
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (StringUtils.isEmpty(s)) {
            return true;
        } else {
            return allows.contains(s);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35918357/article/details/89284678