1 Formatting
在Spring中用于格式化数据及根据地域展示不同格式的数据。
图 Formatting接口 UML
1.1 注解驱动Formatting
自定义像“@DateTimeFormat”注解来对相关字段格式化的步骤为:
- 自定义注解。
- 定义一个实现AnnotationFormatterFactory接口的工厂类。
- 往容器注册步骤二创建的工厂类。
@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");@Overridepublic Set<Class<?>> getFieldTypes() {Set<Class<?>> classSet = new HashSet<>();classSet.add(String.class);return classSet;}@Overridepublic Printer<?> getPrinter(CustomTimeFormatter annotation, Class<?> fieldType) {return new Printer<Date>() {@Overridepublic String print(Date date, Locale locale) {return dateFormat.format(date);}};}@Overridepublic Parser<?> getParser(CustomTimeFormatter annotation, Class<?> fieldType) {return new Parser<Date>() {@Overridepublic 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;}@Overridepublic Set<ConvertiblePair> getConvertibleTypes() {return Collections.singleton(new ConvertiblePair(String.class, this.fieldType));}@Override@Nullablepublic 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;}@Overridepublic 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"/>