✒ 作者 - Lex 📝 博客 - 掘金 📚 源码地址 - github
-
本地化和国际化(i18n)
- 了解如何根据不同的地区设置(Locale)进行数据格式化,这在全球化的应用开发中非常重要。
-
Java API for Formatting
- 熟悉 Java 的格式化相关 API,例如
java.text.DateFormat
、java.text.SimpleDateFormat
和java.time.format.DateTimeFormatter
,因为这些通常在实现Printer
接口时使用。
- 熟悉 Java 的格式化相关 API,例如
-
ConversionService
ConversionService
是 Spring 中用于管理转换器(Converters
)和格式化器(Formatters
,包括Printer
和Parser
)的服务。理解ConversionService
如何工作,可以帮助您更好地集成和使用Printer
接口。
Parser
接口在Spring框架中是一个关键的数据转换工具,专门用于将字符串格式的数据转换为更复杂的对象类型。这个接口提供了一个简洁的方法,允许我们自定义如何将文本输入转换成所需的数据类型,如从或者字符串到 Number
。此接口的灵活性在于支持国际化,因此可以根据不同地区的标准来解析数据。
-
字符串到对象的转换
- 将字符串数据转换成更复杂的对象类型。这对于处理来自用户输入或外部数据源的文本数据尤其重要。
-
支持自定义类型转换
- 我们可以创建自定义的解析器来处理特定类型的数据转换,例如日期时间、货币或任何自定义的数据类型。
-
国际化支持
Parser
接口的方法通常包括一个Locale
参数,这使得解析器可以根据不同的地区设置来正确解析字符串,支持多语言和区域的格式差异。
Parser<T>
接口是Spring框架中用于从字符串到特定对象类型转换的关键接口。它定义了一个单一的方法 parse
,该方法接受一个字符串和区域设置(Locale),返回一个指定类型(T)的实例。
/**
* 用于将文本字符串解析为T类型实例的接口。
*
* @author Keith Donald
* @since 3.0
* @param <T> 这个解析器生成的对象类型
*/
@FunctionalInterface
public interface Parser<T> {
/**
* 解析文本字符串以生成T类型的实例。
* @param text 要解析的文本字符串
* @param locale 当前用户的区域设置
* @return T类型的实例
* @throws ParseException 当java.text解析库发生解析异常时抛出
* @throws IllegalArgumentException 当发生解析异常时抛出
*/
T parse(String text, Locale locale) throws ParseException;
}
-
CharArrayFormatter
- 用于将字符串解析为字符数组。适用于需要将文本数据转换为字符数组形式的场景。
-
CurrencyParser
- 专门用于解析货币值的字符串,例如将 "$1,234.56" 解析成相应的数值表示。
-
CurrencyStyleFormatter
- 用于格式化和解析货币值,不仅支持解析还支持将数值格式化为货币字符串。
-
CurrencyUnitFormatter
- 用于格式化和解析货币单位,例如将 "USD" 或 "EUR" 等货币代码转换成相应的货币单位对象。
-
DateFormatter
- 专门用于解析日期字符串,如将 "2023-12-31" 转换成
java.util.Date
对象。
- 专门用于解析日期字符串,如将 "2023-12-31" 转换成
-
DateTimeParser
- 用于解析日期和时间的字符串,转换为
java.time.LocalDateTime
或类似的日期时间对象。
- 用于解析日期和时间的字符串,转换为
-
DurationFormatter
- 用于解析表示时间长度的字符串,如 "PT10M"(表示10分钟),转换为
java.time.Duration
对象。
- 用于解析表示时间长度的字符串,如 "PT10M"(表示10分钟),转换为
-
InetAddressFormatter
- 用于解析IP地址的字符串,将其转换为
java.net.InetAddress
对象。
- 用于解析IP地址的字符串,将其转换为
-
InstantFormatter
- 用于解析表示特定时刻的字符串,如 "2020-01-01T00:00:00Z",转换为
java.time.Instant
对象。
- 用于解析表示特定时刻的字符串,如 "2020-01-01T00:00:00Z",转换为
-
IsoOffsetFormatter
- 用于解析带时区偏移的日期时间字符串,转换为
java.time.OffsetDateTime
等类型。
- 用于解析带时区偏移的日期时间字符串,转换为
-
LocalDateParser
- 专门用于解析仅包含日期部分的字符串,如 "2020-01-01",转换为
java.time.LocalDate
对象。
- 专门用于解析仅包含日期部分的字符串,如 "2020-01-01",转换为
-
LocalDateTimeParser
- 用于解析包含日期和时间的字符串,转换为
java.time.LocalDateTime
对象。
- 用于解析包含日期和时间的字符串,转换为
-
LocalTimeParser
- 专门用于解析时间字符串,如 "23:59",转换为
java.time.LocalTime
对象。
- 专门用于解析时间字符串,如 "23:59",转换为
-
MonetaryAmountFormatter
- 用于格式化和解析表示货币金额的字符串。
-
MonthDayFormatter
- 用于解析表示月和日的字符串,如 "12-31",转换为
java.time.MonthDay
对象。
- 用于解析表示月和日的字符串,如 "12-31",转换为
-
MonthFormatter
- 用于解析表示月份的字符串,如 "January" 或 "01",转换为
java.time.Month
枚举。
- 用于解析表示月份的字符串,如 "January" 或 "01",转换为
-
NumberDecoratingFormatter
- 一个装饰器,用于增强对数字的格式化和解析功能。
-
PatternDecoratingFormatter
- 用于在解析和格式化时应用特定的模式或模板。
-
PeriodFormatter
- 用于解析表示一段时间长度的字符串,如 "P1Y2M"(1年2个月),转换为
java.time.Period
对象。
- 用于解析表示一段时间长度的字符串,如 "P1Y2M"(1年2个月),转换为
-
TemporalAccessorParser
- 用于解析
java.time.temporal.TemporalAccessor
的实现类,如LocalDate
、LocalDateTime
等。
- 用于解析
-
YearFormatter
- 用于解析年份字符串,如 "2020",转换为
java.time.Year
对象。
- 用于解析年份字符串,如 "2020",转换为
-
YearMonthFormatter
- 用于解析表示年和月的字符串,如 "2020-01",转换为
java.time.YearMonth
对象。
- 用于解析表示年和月的字符串,如 "2020-01",转换为
使用Spring框架的 FormattingConversionService
来进行货币字符串的解析。它首先创建了一个 FormattingConversionService
实例,并向其添加了一个 CurrencyParser
实现。通过设置 LocaleContextHolder
的区域设置,该代码能够根据不同的地区(美国和中国)解析相应格式的货币字符串(美元和人民币)。
public class ParserDemo {
public static void main(String[] args) {
// 创建一个格式化转换服务
FormattingConversionService conversionService = new FormattingConversionService();
// 向转换服务中添加一个货币解析器
conversionService.addParser(new CurrencyParser());
// 设置当前线程的区域设置为美国
LocaleContextHolder.setLocale(Locale.US);
// 将美元格式的字符串转换为数值类型
Number formattedAmountForUS = conversionService.convert("$1,234.56", Number.class);
System.out.println("Parsed Currency (US): " + formattedAmountForUS);
// 改变区域设置为中国
LocaleContextHolder.setLocale(Locale.CHINA);
// 将人民币格式的字符串转换为数值类型
Number formattedAmountForCHINA = conversionService.convert("¥1,234.56", Number.class);
System.out.println("Parsed Currency (CHINA): " + formattedAmountForCHINA);
}
}
CurrencyParser
类,它实现了 Spring 框架中的 Parser<Number>
接口,用于将货币格式的字符串解析为数值类型。这个类的 parse
方法接收一个货币格式的字符串和一个 Locale
对象作为参数。使用 Locale
参数,它创建了一个 NumberFormat
实例,这个实例专门用于解析特定区域(如美国、中国等)的货币格式。
public class CurrencyParser implements Parser<Number> {
@Override
public Number parse(String text, Locale locale) throws ParseException {
if (text == null) {
throw new ParseException("Null string cannot be parsed to number", 0);
}
// 创建适用于特定区域的货币格式化器
NumberFormat format = NumberFormat.getCurrencyInstance(locale);
// 解析字符串为数字
return format.parse(text);
}
}
运行结果发现,CurrencyParser
类如何成功地将不同地区格式的货币字符串解析为数值。无论是美国的 "$1,234.56" 还是中国的 "¥1,234.56",都被正确地解析为相同的数值 1234.56
。
Parsed Currency (US): 1234.56
Parsed Currency (CHINA): 1234.56
-
Printer
Printer
接口的职责是将对象格式化为字符串。这在显示数据或将对象序列化为字符串形式以便于存储和传输时非常有用。
-
Formatter
Formatter
接口是Parser
接口的补充,不仅提供了从字符串到对象的解析功能(与Parser
相同),还提供了将对象格式化为字符串的功能。在实际应用中,很多时候Formatter
同时实现了解析和格式化两种功能。
-
FormattingConversionService
FormattingConversionService
是Spring的一个核心类,用于注册和使用格式化器和解析器。它可以注册实现了Parser
接口的类,从而提供字符串到对象的类型转换服务。
-
DataBinder&WebDataBinder
- 这些类用于数据绑定和类型转换。在处理表单提交或其他用户输入时,
DataBinder
和WebDataBinder
可以利用注册到FormattingConversionService
的Parser
实现,将字符串转换为相应的对象类型。
- 这些类用于数据绑定和类型转换。在处理表单提交或其他用户输入时,
-
LocaleContextHolder
LocaleContextHolder
提供了一种访问当前线程特定区域设置(Locale)的方式。由于Parser
接口的parse
方法通常需要一个Locale
参数,LocaleContextHolder
可以在解析过程中提供必要的区域信息,使解析能够适应不同的地区特定格式。
-
Locale
Parser
接口的parse
方法接受一个Locale
参数,这允许实现类根据不同的地区设置来格式化对象,支持国际化和本地化需求。
-
复杂的解析逻辑
- 面对复杂的数据类型或需支持多种地区设置的复杂解析逻辑时,建议利用现有的 Java API(如
DateFormat
,NumberFormat
等)进行处理。同时,可以结合Spring的国际化支持(如MessageSource
)来简化实现。
- 面对复杂的数据类型或需支持多种地区设置的复杂解析逻辑时,建议利用现有的 Java API(如
-
处理不同的地区设置(Locale)
- 在国际化应用程序中,正确处理不同地区设置是一个挑战。确保
parse
方法适当地使用传入的Locale
参数,并在可能的情况下利用Spring的本地化和国际化支持,以确保数据正确地解析。
- 在国际化应用程序中,正确处理不同地区设置是一个挑战。确保
-
与Spring MVC的集成
- 在Spring MVC应用程序中,正确注册和使用自定义的
Parser
实现需要确保它在FormattingConversionService
中被正确注册。此外,应检查控制器方法是否正确使用了数据绑定和解析逻辑。
- 在Spring MVC应用程序中,正确注册和使用自定义的
-
保证解析和格式化的一致性
- 当同时使用
Parser
和对应的Printer
时,非常重要的一点是保证它们对于相同类型的数据有着一致的解析和格式化规则。这意味着相同类型的数据应该能够在解析和格式化之间无缝转换,而不会引入任何不一致性。
- 当同时使用