Spring 3 类型转换和验证

工程 | Keith Donald | 2009 年 11 月 17 日 | ...

Spring 3 最终版本即将发布,这将是一个很棒的版本。在本篇博文中,我将带您了解 Spring 3 的一些类型转换和验证增强功能。无论您是开发传统的 Web 应用程序、桌面应用程序还是“下一代”RIA,数据绑定、类型转换和验证都是重要的领域。正如您在本篇博文中将看到的,Spring 3 在这些领域都为您提供了重大改进,同时保留了与先前版本的向后兼容性。

新的系统目标

在深入了解功能之前,我想先强调一下我们在着手改进 Spring 3 数据绑定系统时所设定的目标。

  1. 提供一个无状态、强类型的类型转换器 SPI,以取代 JavaBean 属性编辑器。
  2. 提供一个统一的类型转换 API,用于在需要转换的任何地方使用,包括 Spring 的 DataBinder 和表达式语言。
  3. 允许通过 Java 注解元数据驱动类型转换。
  4. 通过注册合理的默认值并应用约定优于配置来简化。
随着 Spring 3 最终版本的临近,我相信我们已经实现了每个目标。请继续阅读,并由您来评判。

功能

第一个充分利用新类型转换系统的环境是 Spring MVC,我将从中提取示例来演示新功能。这从新的 Spring MVC 3 配置命名空间开始。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <mvc:annotation-driven />

</beans>

前面的最小配置导致 Spring 自动安装默认类型转换器,这些转换器可以本地化数字和日期字段,包括如果您的类路径上存在流行的 Joda Time 库,则完全支持该库。此外,如果您的类路径上存在 JSR-303 提供程序(例如 Hibernate Validator),Spring 会自动启用注解驱动的声明式验证。

现在,当您绑定到某个字段时,该字段将使用合理的默认格式为用户的区域设置打印和解析。为了说明这一点,请考虑以下模型。


public class Account {

    private Date activationDate = new Date(1258466400);

    private BigDecimal balance = new BigDecimal("3000.25");
}

...在针对美国和德国区域设置的用户打印的表单中。

Locale.US Locale.DE
激活日期

余额

激活日期

余额

使用注解覆盖默认值

通常,您需要以与默认格式不同的方式格式化字段。在前面的示例中,您可能希望activationDate字段使用短日期格式进行格式化,而balance字段使用货币格式进行格式化。在 Spring 的早期版本中,您将在 Controller 中注册一个自定义 PropertyEditor 来实现此目的。在 Spring 3 中,您只需注释您的字段即可。


private class Account {

    @DateTimeFormat(style="S-")
    private Date activationDate = new Date(1258466400);

    @NumberFormat(style=Style.CURRENCY)
    private BigDecimal balance = new BigDecimal("3000.25");
}

使用注解覆盖,将为美国和德国区域设置打印以下内容。

Locale.US Locale.DE
激活日期

余额

激活日期

余额

参数注解

注解驱动的覆盖也可以应用于方法参数。考虑以下 Controller 方法,该方法获取特定日期的即将到来的预约,其中日期是 URL 路径变量,以 ISO 日期格式编码。


    @RequestMapping(value = "/appointments/{day}", method = RequestMethod.GET)
    public String getAppointmentsForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day) {
        ...
    }

向 /appointments/2009-11-17 发送 GET 请求将获取 2009 年 11 月 17 日的所有预约。将 @DateTimeFormat 的iso属性设置为ISO.DATE指示 Spring 将传入的日期字符串解析为 ISO 日期 (yyyy-mm-dd)。

验证

在将用户输入绑定到模型之后验证模型是很常见的。Spring 3 提供了对使用 JSR-303 进行声明式验证的支持。如果您的类路径上存在 JSR-303 提供程序(例如 Hibernate Validator),则会自动启用此支持。启用后,您只需使用 @Valid 注解注释 Controller 方法参数即可触发验证。


    @RequestMapping(value = "/appointments", method = RequestMethod.POST)
    public String add(@Valid AppointmentForm form, BindingResult result) {
        ....
    }

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }

绑定传入的 POST 参数后,将验证 AppointmentForm;在本例中,验证日期字段值不为空且发生在未来。

约定优于配置

最后,考虑如何将约定优于配置原则应用于类型转换。在业务应用程序中,您通常会定义自己的自定义字段类型。在 Spring 的早期版本中,要格式化此类类型,您将创建一个自定义 PropertyEditor 实现并在 Controller 中注册它。使用 Spring 3,在大多数情况下,您只需遵守以下约定即可。

  1. 定义一个静态 valueOf(String) 方法或 Constructor(String) 以从其字符串表示形式解析您的值。
  2. 实现 toString() 以打印您的值以供显示。

考虑一个符合此约定的 SocialSecurityNumber 类型。


    public class SocialSecurityNumber {

        @Size(9)
        @Mask("###-##-####")
        private String value;

        public SocialSecurityNumber(String value) {
            this.value = value;
        }

        public String toString() {
            return this.value;
        }
    }

当 SocialSecurityNumber 字段打印以供显示时,将调用 toString();当解析客户端值时,将调用 Constructor。不需要单独的 Formatter 或 PropertyEditor 实现。

总结

本篇博文介绍了 Spring 3 的一些新的类型转换和验证功能。要了解更多信息,包括如何实现自己的类型转换器,请查看Spring 3 参考指南。此外,请关注未来几周内修订版 Petclinic 3 示例应用程序的发布(此示例应用程序演示了此处突出显示的所有功能,目前可在我们的 SVN 存储库此处中进行抢先体验)。

我对这些新功能为我们提供的基础感到兴奋!请告诉我您在应用和扩展这些功能方面的经验,并继续在jira.springframework.org上提供反馈和想法。

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部