SpringFramework核心技术三:Spring时间处理和类型转换

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: 使用在(1)中,我们学习了蛮多的基本概念,在(2)中咱们看一下如何使用的问题。一、以编程方式使用ConversionService要以编程方式使用ConversionService实例,只需为其他bean注入一...

使用

在(1)中,我们学习了蛮多的基本概念,在(2)中咱们看一下如何使用的问题。


一、以编程方式使用ConversionService

要以编程方式使用ConversionService实例,只需为其他bean注入一个引用即可:

@Service
public class MyService {

    @Autowired
    public MyService(ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    public void doIt() {
        this.conversionService.convert(...)
    }
}

对于大多数用例,可以使用convert指定targetType的方法,但它不适用于更复杂的类型,如参数化元素的集合。如果你想转换List的Integer到List的String程序,例如,你需要提供的源和目标类型的正式定义。

幸运的是,TypeDescriptor提供了各种选项来简单明了:

DefaultConversionService cs = new DefaultConversionService();

List<Integer> input = ....
cs.convert(input,
    TypeDescriptor.forObject(input), // List<Integer> type descriptor
    TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));

请注意,DefaultConversionService自动注册转换器适用于大多数环境。这包括收集器,标转换器,也基本Object到String转换器。相同的转换器可以ConverterRegistry使用该类 上的静态 addDefaultConverters方法进行注册DefaultConversionService。

值类型转换器将被重新用于数组和集合,所以没有必要创建一个特定的转换器从转换Collection的S到 Collection的T,假设标准收集处理是适当的。

二、Spring字段格式

正如前一节所讨论的,core.convert是一种通用型转换系统。它提供统一的ConversionService API以及用于实现从一种类型到另一种类型的转换逻辑的强类型转换器SPI。Spring容器使用这个系统绑定bean属性值。另外,Spring表达式语言(SpEL)和DataBinder都使用这个系统来绑定字段值。例如,当使用SpEL需要强迫一个Short到一个Long完成的expression.setValue(Object bean, Object value)尝试,core.convert系统执行强制。

现在考虑典型客户端环境(如Web或桌面应用程序)的类型转换要求。在这样的环境中,您通常从String转换 为支持客户端回发过程,并返回String以支持视图呈现过程。另外,您经常需要本地化字符串值。更一般的core.convert Converter SPI没有直接解决这种格式化要求。为了直接解决它们,Spring 3引入了一个方便的Formatter SPI,为客户端环境提供了PropertyEditor的一个简单而强大的替代方案。

通常,在需要实现通用类型转换逻辑时使用Converter SPI; 例如,用于在java.util.Date和java.lang.Long之间进行转换。在客户端环境(如Web应用程序)中工作时需要使用Formatter SPI,并且需要解析和打印本地化的字段值。ConversionService为两个SPI提供统一的类型转换API。

1.格式化器SPI

格式化器SPI实现字段格式化逻辑很简单并且强类型化:

package org.springframework.format;

public interface Formatter<T> extends Printer<T>, Parser<T> {
}

Formatter从打印机和解析器构建块接口扩展而来:

public interface Printer<T> {
    String print(T fieldValue, Locale locale);
}
import java.text.ParseException;

public interface Parser<T> {
    T parse(String clientValue, Locale locale) throws ParseException;
}

要创建自己的格式化程序,只需实现上面的格式化接口即可。例如,将T指定为要格式化的对象的类型 java.util.Date。实施print()操作以打印T的实例以在客户端区域设置中显示。实现parse()操作以从客户机语言环境返回的格式化表示中解析T的实例。如果解析尝试失败,则格式化程序应该抛出ParseException或IllegalArgumentException。注意确保您的Formatter实现是线程安全的。

format为方便起见,在子包中提供了几个格式化器实现。该number包提供了一个NumberFormatter,CurrencyFormatter并 使用a PercentFormatter来格式化java.lang.Number对象java.text.NumberFormat。该datetime包提供了一个用a DateFormatter来格式化java.util.Date对象java.text.DateFormat。该datetime.joda软件包提供基于Joda-Time库的综合日期时间格式化支持。

考虑DateFormatter作为一个示例Formatter实现:

package org.springframework.format.datetime;

public final class DateFormatter implements Formatter<Date> {

    private String pattern;

    public DateFormatter(String pattern) {
        this.pattern = pattern;
    }

    public String print(Date date, Locale locale) {
        if (date == null) {
            return "";
        }
        return getDateFormat(locale).format(date);
    }

    public Date parse(String formatted, Locale locale) throws ParseException {
        if (formatted.length() == 0) {
            return null;
        }
        return getDateFormat(locale).parse(formatted);
    }

    protected DateFormat getDateFormat(Locale locale) {
        DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale);
        dateFormat.setLenient(false);
        return dateFormat;
    }

}

2.注释驱动的格式

您将会看到,字段格式可以通过字段类型或注释进行配置。要将注释绑定到格式化程序,请实现AnnotationFormatterFactory:

package org.springframework.format;

public interface AnnotationFormatterFactory<A extends Annotation> {

    Set<Class<?>> getFieldTypes();

    Printer<?> getPrinter(A annotation, Class<?> fieldType);

    Parser<?> getParser(A annotation, Class<?> fieldType);

}

例如,参数化A是您希望将格式逻辑与之关联的字段批注类型org.springframework.format.annotation.DateTimeFormat。已经 getFieldTypes()返回类型字段中的注释,可以使用上。已经 getPrinter()返回打印机打印的注释字段的值。已经 getParser()返回解析器解析一个clientValue一个注释字段。

下面的示例AnnotationFormatterFactory实现将@NumberFormat注释绑定到格式化程序。此注释允许指定数字样式或模式:

public final class NumberFormatAnnotationFormatterFactory
        implements AnnotationFormatterFactory<NumberFormat> {

    public Set<Class<?>> getFieldTypes() {
        return new HashSet<Class<?>>(asList(new Class<?>[] {
            Short.class, Integer.class, Long.class, Float.class,
            Double.class, BigDecimal.class, BigInteger.class }));
    }

    public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterFrom(annotation, fieldType);
    }

    public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterFrom(annotation, fieldType);
    }

    private Formatter<Number> configureFormatterFrom(NumberFormat annotation,
            Class<?> fieldType) {
        if (!annotation.pattern().isEmpty()) {
            return new NumberFormatter(annotation.pattern());
        } else {
            Style style = annotation.style();
            if (style == Style.PERCENT) {
                return new PercentFormatter();
            } else if (style == Style.CURRENCY) {
                return new CurrencyFormatter();
            } else {
                return new NumberFormatter();
            }
        }
    }
}

要触发格式化,只需使用@NumberFormat注释字段即可:

public class MyModel {

    @NumberFormat(style=Style.CURRENCY)
    private BigDecimal decimal;

}
  • 格式注释API
    org.springframework.format.annotation 包中存在可移植的格式注释API 。使用@NumberFormat格式化java.lang.Number字段。使用@DateTimeFormat格式化java.util.Date,java.util.Calendar,java.util.Long或Joda-Time字段。

以下示例使用@DateTimeFormatjava.util.Date格式化为ISO日期(yyyy-MM-dd):

public class MyModel {

    @DateTimeFormat(iso=ISO.DATE)
    private Date date;

}

3.FormatterRegistry SPI

FormatterRegistry是用于注册格式化程序和转换程序的SPI。 FormattingConversionService是适用于大多数环境的FormatterRegistry的实现。这个实现可以通过编程或声明方式配置为Spring bean FormattingConversionServiceFactoryBean。因为这个实现也实现了ConversionService,所以它可以直接配置用于Spring的DataBinder和Spring表达式语言(SpEL)。

查看下面的FormatterRegistry SPI:

package org.springframework.format;

public interface FormatterRegistry extends ConverterRegistry {

    void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);

    void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);

    void addFormatterForFieldType(Formatter<?> formatter);

    void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);

}

如上所示,格式化程序可以通过fieldType或注释进行注册。

FormatterRegistry SPI允许您集中配置格式化规则,而不是在控制器中复制这种配置。例如,您可能希望强制所有日期字段以特定方式格式化,或者使用特定批注的字段以特定方式格式化。通过共享的FormatterRegistry,您可以定义这些规则一次,并在需要格式化时应用这些规则。

4.FormatterRegistrar SPI

FormatterRegistrar是一个用于通过FormatterRegistry注册格式化器和转换器的SPI:

package org.springframework.format;

public interface FormatterRegistrar {

    void registerFormatters(FormatterRegistry registry);

}

FormatterRegistrar在为给定格式类别(例如日期格式)注册多个相关转换器和格式化程序时非常有用。在声明性注册不足的情况下,它也很有用。例如,格式化程序需要在与其自己的不同的特定字段类型下或在注册打印机/解析器对时进行索引。下一节提供了有关转换器和格式化程序注册的更多信息。

三、配置全球日期和时间格式

默认情况下,不使用注释的日期和时间字段@DateTimeFormat使用DateFormat.SHORT样式从字符串转换。如果你愿意,你可以通过定义你自己的全局格式来改变它。

您需要确保Spring不会注册默认格式化程序,而应该手动注册所有格式化程序。根据您是否使用Joda-Time库,使用 org.springframework.format.datetime.joda.JodaTimeFormatterRegistrarororg.springframework.format.datetime.DateFormatterRegistrarclass

例如,以下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的配置,你可以使用a FormattingConversionServiceFactoryBean。这是同一个例子,这次使用乔达时间:

<?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>

乔达时提供单独的不同类型来表示date,time和date-time 的值。的dateFormatter,timeFormatter和dateTimeFormatter的性质 JodaTimeFormatterRegistrar,应使用来配置不同的格式为每种类型。在DateTimeFormatterFactoryBean提供了一个方便的方法来创建格式化。

如果您使用Spring MVC,请记住明确配置使用的转换服务。对于基于Java的@Configuration这意味着扩展 WebMvcConfigurationSupport类和重写mvcConversionService()方法。对于XML,您应该使用元素的’conversion-service’属性 mvc:annotation-driven。有关详细信息,请参阅转换和格式。

目录
相关文章
|
3月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
365 0
|
4月前
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
382 0
|
3月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
222 1
|
3月前
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
424 1
|
3月前
|
Java 数据库连接 开发者
Spring Framework 核心技术详解
本文档旨在深入解析 Java Spring Framework 的核心技术原理与应用。与侧重于快速开发的 Spring Boot 不同,本文将聚焦于 Spring 框架本身的设计理念、核心容器、控制反转(IoC)、面向切面编程(AOP)、数据访问与事务管理等基础且强大的模块。通过理解这些核心概念,开发者能够更深刻地领悟 Spring 生态系统的设计哲学,并具备解决复杂企业级应用开发问题的能力。
256 4
|
4月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
352 2
|
3月前
|
监控 Java API
Spring WebFlux 响应式编程技术详解与实践指南
本文档全面介绍 Spring WebFlux 响应式编程框架的核心概念、架构设计和实际应用。作为 Spring 5 引入的革命性特性,WebFlux 提供了完全的响应式、非阻塞的 Web 开发栈,能够显著提升系统的并发处理能力和资源利用率。本文将深入探讨 Reactor 编程模型、响应式流规范、WebFlux 核心组件以及在实际项目中的最佳实践,帮助开发者构建高性能的响应式应用系统。
641 0
|
3月前
|
监控 Cloud Native Java
Spring Integration 企业集成模式技术详解与实践指南
本文档全面介绍 Spring Integration 框架的核心概念、架构设计和实际应用。作为 Spring 生态系统中的企业集成解决方案,Spring Integration 基于著名的 Enterprise Integration Patterns(EIP)提供了轻量级的消息驱动架构。本文将深入探讨其消息通道、端点、过滤器、转换器等核心组件,以及如何构建可靠的企业集成解决方案。
316 0
|
3月前
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
442 0
|
3月前
|
安全 Java 数据安全/隐私保护
Spring Security 核心技术解析与实践指南
本文档深入探讨 Spring Security 框架的核心架构、关键组件和实际应用。作为 Spring 生态系统中负责安全认证与授权的关键组件,Spring Security 为 Java 应用程序提供了全面的安全服务。本文将系统介绍其认证机制、授权模型、过滤器链原理、OAuth2 集成以及最佳实践,帮助开发者构建安全可靠的企业级应用。
215 0

热门文章

最新文章