首页 > 解决方案 > 如何以 ISO8601 格式将 Spring Boot 解析属性绑定到 LocalTime?

问题描述

我有一个使用@ConfigurationProperties组件的 Spring Boot 2.2.6 应用程序,如下所示:

@Component
@ConfigurationProperties("myapplication")
public class MyApplicationSettings {
    private LocalTime startOfDay;

    // getter and setters here
}

我的集成测试突然开始在 Jenkins 上失败,但在本地运行良好。异常显示如下:

Description:

Failed to bind properties under 'myapplication.start-of-day' to java.time.LocalTime:

    Property: myapplication.start-of-day
    Value: 06:00
    Origin: class path resource [application-integration-test.properties]:29:62
    Reason: failed to convert java.lang.String to java.time.LocalTime

Action:

Update your application's configuration

完整的异常跟踪的根本原因是:

Caused by: java.time.format.DateTimeParseException: Text '06:00' could not be parsed at index 5
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalTime.parse(LocalTime.java:463)
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:72)
    at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:46)
    at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:217)

在对代码进行了一些挖掘之后,我发现 Spring 将使用默认语言环境来解析LocalTime. 由于我的本地机器使用 24 小时制,它可以工作。构建服务器使用 12 小时语言环境,因此它无法解析字符串,因为没有 am/pm 指示。

我的问题:

如何配置 Spring Boot 以将配置属性解析为 ISO-8601 格式,独立于 JVM 的默认语言环境?

我还检查了文档,但“属性转换”一章没有提到LocalTime(或LocalDate

标签: javaspringspring-boot

解决方案


解决方案应包括以下步骤:

  1. 使用字段创建@ConfigurationProperties带注释的类LocalTime(在您的情况下为 MyApplicationSettings)并将其注册@Configuration@EnableConfigurationProperties(MyApplicationSettings.class)
  2. application.properties定义值时:
myapplication.startOfDay=06:00:00
  1. 创建一个特殊的转换器并确保它被 Spring Boot 应用程序扫描和加载。实际解析的逻辑当然可以不同,在那里实现你想要的任何东西,任何特定的格式,语言环境——随便什么:
@Component
@ConfigurationPropertiesBinding
public class LocalTimeConverter implements Converter<String, LocalTime> {
    @Override
    public LocalTime convert(String source) {
        if(source==null){
            return null;
        }
        return LocalTime.parse(source, DateTimeFormatter.ofPattern("HH:mm:ss"));
    }
}
  1. 现在类中的所有LocalTime条目@ConfigurationProperties都将通过这个转换器。

推荐阅读