Spring Validator解读

来源:互联网 发布:壁纸桌面软件下载 编辑:程序博客网 时间:2024/06/05 16:34

模板消息怎么能在解析时候读取对应国际化message的文件的key

  • 首先找到ConstraintViolation 类
  • 看到 一下的内容声明的接口
    String getMessage();//校验错误信息    String getMessageTemplate();//错误信息模版     T getRootBean();//被校验的根实体对象     Class<T> getRootBeanClass();//被校验的根实体类.    Object getLeafBean();//约束是添加在一个实体对象上,那么则返回对象, 约束是定义在一个属性上的,返回这个属性所属的实例对象.    Object[] getExecutableParameters();//方法或构造器返回参数    Object getExecutableReturnValue();//方法或构造器返回值    Path getPropertyPath();//从被验证的根对象到被验证的属性的路径.    Object getInvalidValue();//校验失败的值    ConstraintDescriptor<?> getConstraintDescriptor();//返回验证数据的描述    <U> U unwrap(Class<U> var1);//包装MessageInterpolator 
  • 找到getMessageTemplate的默认实现
  • 一直会追溯到ConstraintViolationCreationContext这个类的toString方法
@Override    public String toString() {        final StringBuilder sb = new StringBuilder( "ConstraintViolationCreationContext{" );        sb.append( "message='" ).append( message ).append( '\'' );        sb.append( ", propertyPath=" ).append( propertyPath );        sb.append( ", messageParameters=" ).append( expressionVariables );        sb.append( '}' );        return sb.toString();    }

spring工厂生产出校验器

  • 校验器会丢失hibernate的HibernateValidatorConfiguration的配置参数不能用设置failFast(true)主要在LocalValidatorFactoryBean以下位置
@Override    public void afterPropertiesSet() {//主要是在这里我们没有设置,应该是hibernateValidate的话使用                                             //Validation.byProvider(this.providerClass).configure().failFast(true)        @SuppressWarnings({"rawtypes", "unchecked"})        Configuration<?> configuration = (this.providerClass != null ?                Validation.byProvider(this.providerClass).configure() :                Validation.byDefaultProvider().configure());        // Try Hibernate Validator 5.2's externalClassLoader(ClassLoader) method        if (this.applicationContext != null) {            try {                Method eclMethod = configuration.getClass().getMethod("externalClassLoader", ClassLoader.class);                ReflectionUtils.invokeMethod(eclMethod, configuration, this.applicationContext.getClassLoader());            }            catch (NoSuchMethodException ex) {                // Ignore - no Hibernate Validator 5.2+ or similar provider            }        }        MessageInterpolator targetInterpolator = this.messageInterpolator;        //这里将hibernate的配置丢失了        if (targetInterpolator == null) {            targetInterpolator = configuration.getDefaultMessageInterpolator();        }        configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));        if (this.traversableResolver != null) {            configuration.traversableResolver(this.traversableResolver);        }        ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;        if (targetConstraintValidatorFactory == null && this.applicationContext != null) {            targetConstraintValidatorFactory =                    new SpringConstraintValidatorFactory(this.applicationContext.getAutowireCapableBeanFactory());        }        if (targetConstraintValidatorFactory != null) {            configuration.constraintValidatorFactory(targetConstraintValidatorFactory);        }        if (this.parameterNameDiscoverer != null) {            configureParameterNameProviderIfPossible(configuration);        }        if (this.mappingLocations != null) {            for (Resource location : this.mappingLocations) {                try {                    configuration.addMapping(location.getInputStream());                }                catch (IOException ex) {                    throw new IllegalStateException("Cannot read mapping resource: " + location);                }            }        }        for (Map.Entry<String, String> entry : this.validationPropertyMap.entrySet()) {            configuration.addProperty(entry.getKey(), entry.getValue());        }        // Allow for custom post-processing before we actually build the ValidatorFactory.        postProcessConfiguration(configuration);        this.validatorFactory = configuration.buildValidatorFactory();        setTargetValidator(this.validatorFactory.getValidator());    }
package com.jd.hotel.validate;import org.hibernate.validator.HibernateValidator;import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;import org.springframework.context.MessageSource;import org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator;import javax.validation.*;import java.util.Set;/** * 主要使用用于在业务逻辑中使用校验 * 可以使用hibernate的校验,但是为了支持统一的国际化封装 * Created by lijianzhen1 on 2017/3/20. */public class BeanValidators {    /**     * 快速的响应验证     */    private boolean failFast;    /**     * 绑定的校验国际化资源     */    private MessageSource messageSource;    private Validator getValidator() {        Validator validator = null;        if (null != messageSource) {            validator =                    Validation.byProvider(HibernateValidator.class).configure().failFast(failFast).messageInterpolator(HibernateValidatorDelegate.buildMessageInterpolator(messageSource))                            .buildValidatorFactory()                            .getValidator();        } else {            validator =                    Validation.buildDefaultValidatorFactory()                            .getValidator();        }        return validator;    }    /**     * 支持默认组校验和指定的组校验     * 使用校验时候需要处理对应的异常     *     * @param object     * @param groups     * @throws ValidatorException     */    public <T> void validate(T object, Class<?>... groups) throws ValidatorException {        Set<ConstraintViolation<T>> constraintViolations = getValidator().validate(object);        validateWithException(constraintViolations);    }    /**     * 校验一个对象的默认,校验组的一个指定的属性值。     *     * @param object     * @param propertyName     * @param groups     * @param <T>     * @throws ValidatorException     */    public <T> void validate(T object, String propertyName, Class<?>... groups) throws ValidatorException {        Set<ConstraintViolation<T>> constraintViolations = getValidator().validateProperty(object, propertyName, groups);        validateWithException(constraintViolations);    }    /**     * 校验一个对象属性值。是否是指定组应该有的值     *     * @param object     * @param propertyName     * @param value     * @param groups     * @param <T>     * @throws ValidatorException     */    public <T> void validateValue(Class<T> object, String propertyName, Object value, Class<?>... groups) throws ValidatorException {        Set<ConstraintViolation<T>> constraintViolations = getValidator().validateValue(object, propertyName, value, groups);        validateWithException(constraintViolations);    }    /**     * 调用验证器 验证失败抛出ValidatorException     *     * @param constraintViolations     * @param <T>     * @throws ValidatorException     */    private <T> void validateWithException(Set<ConstraintViolation<T>> constraintViolations) throws ValidatorException {        if (!constraintViolations.isEmpty()) {            throw new ValidatorExceptionConverter().convert(new ConstraintViolationException(constraintViolations));        }    }    /**     * 内部类声明硬编码的Hibernate Validator 依赖     */    private static class HibernateValidatorDelegate {        public static MessageInterpolator buildMessageInterpolator(MessageSource messageSource) {            return new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(messageSource));        }    }    public void setFailFast(boolean failFast) {        this.failFast = failFast;    }    public void setMessageSource(MessageSource messageSource) {        this.messageSource = messageSource;    }}public class ValidatorException extends Exception {    private String className;    private String attr;    private String errorMsg;    public ValidatorException(String className, String attr, String errorMsg) {        super(className+attr+errorMsg);        this.className = className;        this.attr = attr;        this.errorMsg = errorMsg;    }    public String getClassName() {        return className;    }    public String getAttr() {        return attr;    }    public String getErrorMsg() {        return errorMsg;    }    public String getMessage() {        StringBuffer sb = new StringBuffer(className);        sb.append(attr).append(":").append(errorMsg);        return sb.toString();    }}//异常装换为对应的校验异常public class ValidatorExceptionConverter<T> implements Converter<ConstraintViolationException, ValidatorException> {    public ValidatorExceptionConverter() {    }    @Override    public ValidatorException convert(ConstraintViolationException ce) {        if (null == ce && CollectionUtils.isEmpty(ce.getConstraintViolations()))            return null;        //只会校验对应的一个异常        ConstraintViolation violation = ce.getConstraintViolations().iterator().next();        return new ValidatorException(violation.getRootBean().getClass().getName(), "." + violation.getPropertyPath(), violation.getMessage());    }}//关于自定义预定时间校验@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Constraint(validatedBy = CheckInAndOutValidatorForDate.class)public @interface CheckInAndOut {    String message() default "{com.jd.hotel.constraints.CheckInAndOut.error}";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};    /**     * 入住时间     * @return     */    String checkIn() default "checkIn";    /**     * 离店时间     * @return     */    String checkOut() default "checkOut";}public class CheckInAndOutValidatorForDate implements ConstraintValidator<CheckInAndOut, Object> {    private String checkIn;    private String checkOut;    @Override    public void initialize(CheckInAndOut constraintAnnotation) {        this.checkIn = constraintAnnotation.checkIn();        this.checkOut = constraintAnnotation.checkOut();    }    @Override    public boolean isValid(Object value, ConstraintValidatorContext context) {        Date checkInDate = null;        Date checkOutDate = null;        //如果为空 不进行空校验        if (value == null) {            return true;        }        try {            checkInDate = (Date) PropertyUtils.getProperty(value, this.checkIn);            checkOutDate = (Date) PropertyUtils.getProperty(value, this.checkOut);            if (checkInDate == null || checkOutDate == null) {                return true;            }        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        //校验入住的时间必须大于当前时间        if (checkInDate.before(DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))) {            context.disableDefaultConstraintViolation();            //获得当前校验的国际化消息            context.buildConstraintViolationWithTemplate("{com.jd.hotel.constraints.CheckInAndOut.timeAfter}").addPropertyNode(this.checkIn).addConstraintViolation();            return false;        }        //校验入住的和离店时间不能大于15天        if (checkOutDate.after(DateUtils.addDays(new Date(), 15))) {            context.disableDefaultConstraintViolation();            context.buildConstraintViolationWithTemplate("{com.jd.hotel.constraints.CheckInAndOut.between15}").addPropertyNode(this.checkOut).addConstraintViolation();            return false;        }        //入住时间不能选择大于1年,和当前的年份+1比较        if (checkInDate.after(DateUtils.addYears(new Date(), 1))) {            context.disableDefaultConstraintViolation();            context.buildConstraintViolationWithTemplate("{com.jd.hotel.constraints.CheckInAndOut.currentYear}").addPropertyNode(this.checkIn).addConstraintViolation();            return false;        }        //并且不再同一天        if (DateUtils.isSameDay(checkInDate, checkOutDate)) {            context.disableDefaultConstraintViolation();            context.buildConstraintViolationWithTemplate("{com.jd.hotel.constraints.CheckInAndOut.notSameDay}").addPropertyNode(this.checkIn).addConstraintViolation();            return false;        }        return true;    }}
原创粉丝点击