Spring 类型转换、数值绑定与验证(三)— Formatting 与 Validation

 1 Formatting

在Spring中用于格式化数据及根据地域展示不同格式的数据。

图 Formatting接口 UML

1.1 注解驱动Formatting

自定义像“@DateTimeFormat”注解来对相关字段格式化的步骤为:

  1. 自定义注解。
  2. 定义一个实现AnnotationFormatterFactory接口的工厂类。
  3. 往容器注册步骤二创建的工厂类。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CustomTimeFormatter {
}

public class CustomTimeFormatterAnnotationFormatterFactory implements AnnotationFormatterFactory<CustomTimeFormatter> {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd mm:hh");

    @Override
    public Set<Class<?>> getFieldTypes() {
        Set<Class<?>> classSet = new HashSet<>();
        classSet.add(String.class);
        return classSet;
    }

    @Override
    public Printer<?> getPrinter(CustomTimeFormatter annotation, Class<?> fieldType) {
        return new Printer<Date>() {
            @Override
            public String print(Date date, Locale locale) {
                return dateFormat.format(date);
            }
        };
    }

    @Override
    public Parser<?> getParser(CustomTimeFormatter annotation, Class<?> fieldType) {
        return new Parser<Date>() {
            @Override
            public Date parse(String text, Locale locale) throws ParseException {
                return dateFormat.parse(text);
            }
        };
    }
}

1.2 FormatterRegistry

继承于ConverterRegistry,是用来注册Formatter及Converter的接口。

图 FormatterRegistry

1.2.1 FormatterRegistry 的实现

图 FormattingConversionService

FormattingConversionService 是FormatterRegistry 的默认实现,其继承于GenericConversionService。该类主要工作是把Formatter 注册 转化为PrinterConverter 和ParserConverter两种转化的注册。通过其PrinterConverter、ParserConverter、AnnotationPrinterConverter及AnnotationParserConverter等内部类,把Formatter的Printer及Parser 转化成GenericConverter或ConditionalGenericConverter。

private static class ParserConverter implements GenericConverter {

		private final Class<?> fieldType;

		private final Parser<?> parser;

		private final ConversionService conversionService;

		public ParserConverter(Class<?> fieldType, Parser<?> parser, ConversionService conversionService) {
			this.fieldType = fieldType;
			this.parser = parser;
			this.conversionService = conversionService;
		}

		@Override
		public Set<ConvertiblePair> getConvertibleTypes() {
			return Collections.singleton(new ConvertiblePair(String.class, this.fieldType));
		}

		@Override
		@Nullable
		public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			String text = (String) source;
			if (!StringUtils.hasText(text)) {
				return null;
			}
			Object result;
			try {
				result = this.parser.parse(text, LocaleContextHolder.getLocale());
			}
			catch (IllegalArgumentException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException("Parse attempt failed for value [" + text + "]", ex);
			}
			TypeDescriptor resultType = TypeDescriptor.valueOf(result.getClass());
			if (!resultType.isAssignableTo(targetType)) {
				result = this.conversionService.convert(result, resultType, targetType);
			}
			return result;
		}

		@Override
		public String toString() {
			return (String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser);
		}
	}

1.3 FormattingConversionServiceFactoryBean

用于创建默认的FormattingConversionService,及配置自定义Formatter及Conversion。

而FormatterRegistar 这是Formatter注册器。用于为FormatterRegistry注册Formatter。

2 Validation

org.springframework.validation.Validator 是用来验证对象实例属性的接口。

图 Spring Validator UML

JSR 303(Bean Validation) 规范定义了一套用于JavaBean参数校验的标准。javax.validation.Validator 也是用于对指定的对象进行校验。

图 JSR 303 Validator UML

2.1 SpringValidatorAdapter 适配器模式

图 SpringValidatorAdapter UML

该适配器使用JSR 的Validator 来适配Spring 的Validator,其同时实现了JSR与Spring的Validator的接口。(即是对象适配器也是类适配器。)

2.1.1 自定义Validator注解

步骤为:1)自定义Constraint注解(该注解需要有@Constraint注解来标识校验类)。2)自定义校验类并实现ConstraintValidator接口。

图 ConstraintValidator UML

javax.validation.ConstraintValidator 是 Java Bean Validation 规范(JSR 303/JSR 380)中的一个核心接口。该接口用于实现自定义的约束验证逻辑。当你创建一个自定义的验证注解时,你需要提供一个实现了 ConstraintValidator 接口的类来定义如何验证该注解所标注的元素。

2.1.2 ConstraintValidator 与 Validator的关系

ConstraintValidator 是验证逻辑(比如自定义验证注解)的具体实现。而javax.validation.Validator 则是用来执行这些验证逻辑。

当需要对某个字段进行验证时,javax.validation.Validator  会找到这个字段所有的ConstraintValidator ,并执行其isValid方法。

2.1.3 LocalValidatorFactoryBean

图 LocalValidatorFactoryBean UML

是在Spring 上下文中使用JSR 的Validator的核心类。 其继承于Spring 及JSR Validator的适配器,并实现了Validator 工厂类接口(能创建已初始化的的Validator)。

可以用来在Spring中定义默认的Validator:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值