《Spring 5 官方文档》5. 验证、数据绑定和类型转换(三)

    xiaoxiao2024-01-29  144

    5.7 配置一个全局的日期&时间格式

    默认情况下,未被@DateTimeFormat注解的日期和时间字段会使用DateFormat.SHORT风格从字符串转换。如果你愿意,你可以定义你自己的全局格式来改变这种默认行为。

    你将需要确保Spring不会注册默认的格式化器,取而代之的是你应该手动注册所有的格式化器。请根据你是否依赖Joda Time库来确定是使用org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar类还是org.springframework.format.datetime.DateFormatterRegistrar类。

    例如,下面的Java配置会注册一个全局的’yyyyMMdd’格式,这个例子不依赖于Joda Time库:

    @Configuration public class AppConfig { @Bean public FormattingConversionService conversionService() { // Use the DefaultFormattingConversionService but do not register defaults DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); // Ensure @NumberFormat is still supported conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); // Register date conversion with a specific global format DateFormatterRegistrar registrar = new DateFormatterRegistrar(); registrar.setFormatter(new DateFormatter("yyyyMMdd")); registrar.registerFormatters(conversionService); return conversionService; } }

    如果你更喜欢基于XML的配置,你可以使用一个FormattingConversionServiceFactoryBean,这是同一个例子,但这次使用了Joda Time:

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="registerDefaultFormatters" value="false" /> <property name="formatters"> <set> <bean class="org.springframework.format.number.NumberFormatAnnotationFormatterFactory" /> </set> </property> <property name="formatterRegistrars"> <set> <bean class="org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar"> <property name="dateFormatter"> <bean class="org.springframework.format.datetime.joda.DateTimeFormatterFactoryBean"> <property name="pattern" value="yyyyMMdd"/> </bean> </property> </bean> </set> </property> </bean> </beans>

    Joda Time提供了不同的类型来表示date、time和date-time的值,JodaTimeFormatterRegistrar中的dateFormatter、timeFormatter和dateTimeFormatter属性应该为每种类型配置不同的格式。DateTimeFormatterFactoryBean提供了一种方便的方式来创建格式化器。

    如果你在使用Spring MVC,请记住要明确配置所使用的转换服务。针对基于@Configuration的Java配置方式这意味着要继承WebMvcConfigurationSupport并且覆盖mvcConversionService()方法。针对XML的方式,你应该使用mvc:annotation-drive元素的'conversion-service'属性。更多细节请看Section 18.16.3 “Conversion and Formatting”。

     

    5.8 Spring验证

    Spring 3对验证支持引入了几个增强功能。首先,现在全面支持JSR-303 Bean Validation API;其次,当采用编程方式时,Spring的DataBinder现在不仅可以绑定对象还能够验证它们;最后,Spring MVC现在已经支持声明式地验证@Controller的输入。

    5.8.1 JSR-303 Bean Validation API概述

    JSR-303对Java平台的验证约束声明和元数据进行了标准化定义。使用此API,你可以用声明性的验证约束对领域模型的属性进行注解,并在运行时强制执行它们。现在已经有一些内置的约束供你使用,当然你也可以定义你自己的自定义约束。

    为了说明这一点,考虑一个拥有两个属性的简单的PersonForm模型:

    public class PersonForm { private String name; private int age; }

    JSR-303允许你针对这些属性定义声明性的验证约束:

    public class PersonForm { @NotNull @Size(max=64) private String name; @Min(0) private int age; }

    当此类的一个实例被实现JSR-303规范的验证器进行校验的时候,这些约束就会被强制执行。

    有关JSR-303/JSR-349的一般信息,可以访问网站Bean Validation website去查看。有关默认参考实现的具体功能的信息,可以参考网站Hibernate Validator的文档。想要了解如何将Bean验证器提供程序设置为Spring bean,请继续保持阅读。

    5.8.2 配置Bean验证器提供程序

    Spring提供了对Bean Validation API的全面支持,这包括将实现JSR-303/JSR-349规范的Bean验证提供程序引导为Spring Bean的方便支持。这样就允许在应用程序任何需要验证的地方注入javax.validation.ValidatorFactory或者javax.validation.Validator。

    把LocalValidatorFactoryBean当作Spring bean来配置成默认的验证器:

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

    以上的基本配置会触发Bean Validation使用它默认的引导机制来进行初始化。作为实现JSR-303/JSR-349规范的提供程序,如Hibernate Validator,可以存在于类路径以使它能被自动检测到。

    注入验证器

    LocalValidatorFactoryBean实现了javax.validation.ValidatorFactory和javax.validation.Validator这两个接口,以及Spring的org.springframework.validation.Validator接口,你可以将这些接口当中的任意一个注入到需要调用验证逻辑的Bean里。

    如果你喜欢直接使用Bean Validtion API,那么就注入javax.validation.Validator的引用:

    import javax.validation.Validator; @Service public class MyService { @Autowired private Validator validator;

    如果你的Bean需要Spring Validation API,那么就注入org.springframework.validation.Validator的引用:

    import org.springframework.validation.Validator; @Service public class MyService { @Autowired private Validator validator; }

    配置自定义约束

    每一个Bean验证约束由两部分组成,第一部分是声明了约束和其可配置属性的@Constraint注解,第二部分是实现约束行为的javax.validation.ConstraintValidator接口实现。为了将声明与实现关联起来,每个@Constraint注解会引用一个相应的验证约束的实现类。在运行期间,ConstraintValidatorFactory会在你的领域模型遇到约束注解的情况下实例化被引用到的实现。

    默认情况下,LocalValidatorFactoryBean会配置一个SpringConstraintValidatorFactory,其使用Spring来创建约束验证器实例。这允许你的自定义约束验证器可以像其他Spring bean一样从依赖注入中受益。

    下面显示了一个自定义的@Constraint声明的例子,紧跟着是一个关联的ConstraintValidator实现,其使用Spring进行依赖注入:

    @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=MyConstraintValidator.class) public @interface MyConstraint { } import javax.validation.ConstraintValidator; public class MyConstraintValidator implements ConstraintValidator { @Autowired; private Foo aDependency; ... }

    如你所见,一个约束验证器实现可以像其他Spring bean一样使用@Autowired注解来自动装配它的依赖。

    Spring驱动的方法验证

    被Bean Validation 1.1以及作为Hibernate Validator 4.3中的自定义扩展所支持的方法验证功能可以通过配置MethodValidationPostProcessor的bean定义集成到Spring的上下文中:

    <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

    为了符合Spring驱动的方法验证,需要对所有目标类用Spring的@Validated注解进行注解,且有选择地对其声明验证组,这样才可以使用。请查阅MethodValidationPostProcessor的java文档来了解针对Hibernate Validator和Bean Validation 1.1提供程序的设置细节。

    附加配置选项

    对于大多数情况,默认的LocalValidatorFactoryBean配置应该足够。有许多配置选项来处理从消息插补到遍历解析的各种Bean验证结构。请查看LocalValidatorFactoryBean的java文档来获取关于这些选项的更多信息。

     

    5.8.3 配置DataBinder

    从Spring 3开始,DataBinder的实例可以配置一个验证器。一旦配置完成,那么可以通过调用binder.validate()来调用验证器,任何的验证错误都会自动添加到DataBinder的绑定结果(BindingResult)。

    当以编程方式处理DataBinder时,可以在绑定目标对象之后调用验证逻辑:

    Foo target = new Foo(); DataBinder binder = new DataBinder(target); binder.setValidator(new FooValidator()); // bind to the target object binder.bind(propertyValues); // validate the target object binder.validate(); // get BindingResult that includes any validation errors BindingResult results = binder.getBindingResult();

    通过dataBinder.addValidators和dataBinder.replaceValidators,一个DataBinder也可以配置多个Validator实例。当需要将全局配置的Bean验证与一个DataBinder实例上局部配置的Spring Validator结合时,这一点是非常有用的。

    5.8.4 Spring MVC 3 验证

    请查看Spring MVC章节的Section 18.16.4 “Validation”。

    转载自 并发编程网 - ifeve.com

    最新回复(0)