如上一节所述,core.convert
是一个
通用型转换系统。它提供了一个统一的 API 作为
以及用于从一种类型实现转换逻辑的强类型 SPI
到另一个。Spring 容器使用此系统来绑定 Bean 属性值。在
此外,Spring Expression Language(SpEL)和使用此系统来
绑定字段值。例如,当 SpEL 需要强制 a 到 a 到
完成一次尝试,系统执行强制。ConversionService
Converter
DataBinder
Short
Long
expression.setValue(Object bean, Object value)
core.convert
现在考虑典型客户端环境的类型转换要求,例如
Web 或桌面应用程序。在此类环境中,通常从支持客户端回发进程以及转换回以支持客户端回发进程,以及转换回支持客户端回发进程
查看渲染过程。此外,您经常需要本地化值。越多
一般 SPI 不满足此类格式要求
径直。为了直接解决这些问题,Spring 提供了一个方便的 SPI 来
为客户端的实现提供简单而强大的替代方案
环境。String
String
String
core.convert
Converter
Formatter
PropertyEditor
通常,当需要实现通用类型时,可以使用SPI
转换逻辑 — 例如,用于在 A 和 A 之间进行转换。
在客户端环境(如 Web
application),并且需要解析和打印本地化的字段值。为两个 SPI 提供统一的类型转换 API。Converter
java.util.Date
Long
Formatter
ConversionService
SPI的Formatter
用于实现字段格式化逻辑的 SPI 简单且类型强大。这
以下列表显示了接口定义:Formatter
Formatter
package org.springframework.format;
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
Formatter
从 和 构建块接口扩展而来。这
以下列表显示了这两个接口的定义:Printer
Parser
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;
}
要创建自己的接口,请实现前面所示的接口。
参数化为要设置格式的对象类型,例如 .实现打印 for 实例的操作
在客户端区域设置中显示。实现从客户端区域设置返回的格式化表示法中解析实例的操作。如果解析尝试失败,则应抛出 a 或 an。拿
注意确保您的实现是线程安全的。Formatter
Formatter
T
java.util.Date
print()
T
parse()
T
Formatter
ParseException
IllegalArgumentException
Formatter
为了方便起见,子包提供了几种实现。
该包提供 、 和 来格式化使用 .
该包提供了一个用于格式化对象的
一个。format
Formatter
number
NumberStyleFormatter
CurrencyStyleFormatter
PercentStyleFormatter
Number
java.text.NumberFormat
datetime
DateFormatter
java.util.Date
java.text.DateFormat
下面是一个示例实现:DateFormatter
Formatter
-
Java
-
Kotlin
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;
}
}
class DateFormatter(private val pattern: String) : Formatter<Date> {
override fun print(date: Date, locale: Locale)
= getDateFormat(locale).format(date)
@Throws(ParseException::class)
override fun parse(formatted: String, locale: Locale)
= getDateFormat(locale).parse(formatted)
protected fun getDateFormat(locale: Locale): DateFormat {
val dateFormat = SimpleDateFormat(this.pattern, locale)
dateFormat.isLenient = false
return dateFormat
}
}
Spring 团队欢迎社区驱动的贡献。请参阅 GitHub Issues to contribute。Formatter
注释驱动的格式
字段格式可以按字段类型或注释进行配置。绑定
对 a 的注释,实现 。以下
列表显示了接口的定义:Formatter
AnnotationFormatterFactory
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
annotationType
org.springframework.format.annotation.DateTimeFormat
-
必须返回可以使用批注的字段类型。
getFieldTypes()
-
返回 a 以打印带注释字段的值。
getPrinter()
Printer
-
返回 a 来解析带注释字段的 a。
getParser()
Parser
clientValue
下面的示例实现将批注绑定到格式化程序,以指定数字样式或模式:AnnotationFormatterFactory
@NumberFormat
-
Java
-
Kotlin
public final class NumberFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<NumberFormat> {
private static final Set<Class<?>> FIELD_TYPES = Set.of(Short.class,
Integer.class, Long.class, Float.class, Double.class,
BigDecimal.class, BigInteger.class);
public Set<Class<?>> getFieldTypes() {
return FIELD_TYPES;
}
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 NumberStyleFormatter(annotation.pattern());
}
// else
return switch(annotation.style()) {
case Style.PERCENT -> new PercentStyleFormatter();
case Style.CURRENCY -> new CurrencyStyleFormatter();
default -> new NumberStyleFormatter();
};
}
}
class NumberFormatAnnotationFormatterFactory : AnnotationFormatterFactory<NumberFormat> {
override fun getFieldTypes(): Set<Class<*>> {
return setOf(Short::class.java, Int::class.java, Long::class.java, Float::class.java, Double::class.java, BigDecimal::class.java, BigInteger::class.java)
}
override fun getPrinter(annotation: NumberFormat, fieldType: Class<*>): Printer<Number> {
return configureFormatterFrom(annotation, fieldType)
}
override fun getParser(annotation: NumberFormat, fieldType: Class<*>): Parser<Number> {
return configureFormatterFrom(annotation, fieldType)
}
private fun configureFormatterFrom(annotation: NumberFormat, fieldType: Class<*>): Formatter<Number> {
return if (annotation.pattern.isNotEmpty()) {
NumberStyleFormatter(annotation.pattern)
} else {
val style = annotation.style
when {
style === NumberFormat.Style.PERCENT -> PercentStyleFormatter()
style === NumberFormat.Style.CURRENCY -> CurrencyStyleFormatter()
else -> NumberStyleFormatter()
}
}
}
}
要触发格式设置,您可以使用 注释字段,如下所示
示例显示:@NumberFormat
-
Java
-
Kotlin
public class MyModel {
@NumberFormat(style=Style.CURRENCY)
private BigDecimal decimal;
}
class MyModel(
@field:NumberFormat(style = Style.CURRENCY) private val decimal: BigDecimal
)
格式注释 API
包中存在可移植格式注释 API。您可以使用 格式化 和 、 等字段,并设置 、 、 的格式(用于毫秒时间戳)以及 JSR-310 。org.springframework.format.annotation
@NumberFormat
Number
Double
Long
@DateTimeFormat
java.util.Date
java.util.Calendar
Long
java.time
以下示例用于将 a 格式化为 ISO 日期
(年-月-日):@DateTimeFormat
java.util.Date
-
Java
-
Kotlin
public class MyModel {
@DateTimeFormat(iso=ISO.DATE)
private Date date;
}
class MyModel(
@DateTimeFormat(iso=ISO.DATE) private val date: Date
)
SPI的FormatterRegistry
这是一个用于注册格式化程序和转换器的 SPI。 是适用于
大多数环境。您可以通过编程或声明方式配置此变体
作为 Spring Bean,例如通过使用 .因为这个
实现也实现,可以直接配置
用于 Spring 和 Spring 表达式语言 (SpEL)。FormatterRegistry
FormattingConversionService
FormatterRegistry
FormattingConversionServiceFactoryBean
ConversionService
DataBinder
以下列表显示了 SPI:FormatterRegistry
package org.springframework.format;
public interface FormatterRegistry extends ConverterRegistry {
void addPrinter(Printer<?> printer);
void addParser(Parser<?> parser);
void addFormatter(Formatter<?> formatter);
void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);
void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);
void addFormatterForFieldAnnotation(AnnotationFormatterFactory<? extends Annotation> annotationFormatterFactory);
}
如前面的清单所示,您可以按字段类型或注释注册格式化程序。
SPI 允许您集中配置格式化规则,而不是
在控制器之间复制此类配置。例如,您可能希望
强制所有日期字段都以某种方式设置格式,或者将字段设置为特定
批注的格式是以某种方式进行的。使用共享 ,您可以定义
这些规则只有一次,每当需要格式化时都会应用它们。FormatterRegistry
FormatterRegistry
SPI的FormatterRegistrar
FormatterRegistrar
是一个 SPI,用于通过
格式化注册表。以下列表显示了其接口定义:
package org.springframework.format;
public interface FormatterRegistrar {
void registerFormatters(FormatterRegistry registry);
}
A 在注册多个相关转换器时很有用,并且
给定格式类别的格式化程序,例如日期格式。它也可以是
在声明性注册不足时很有用,例如,当格式化程序
需要在与自己的特定字段类型不同的特定字段类型下进行索引,或者何时
注册一个/对。下一节将提供有关以下内容的详细信息
转换器和格式化程序注册。FormatterRegistrar
<T>
Printer
Parser
在Spring MVC中配置格式
请参阅 Spring MVC 章节中的转换和格式设置。