Java 如何将Spring引导解析属性绑定到ISO8601格式的LocalTime?

Java 如何将Spring引导解析属性绑定到ISO8601格式的LocalTime?,java,spring,spring-boot,Java,Spring,Spring Boot,我有一个Spring Boot 2.2.6应用程序,它使用@ConfigurationProperties组件,如下所示: @Component @ConfigurationProperties("myapplication") public class MyApplicationSettings { private LocalTime startOfDay; // getter and setters here } Description: Failed to bind

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

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

    // getter and setters here
}
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
我的集成测试突然开始在Jenkins上失败,但在本地运行良好。例外情况如下所示:

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

    // getter and setters here
}
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指示

我的问题:

如何配置SpringBoot以将配置属性解析为ISO-8601格式,独立于JVM的默认区域设置


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

有办法做到这一点,但没有直接的解决方案。您需要创建一个自定义的
ConversionService
bean,将此代码片段放入应用程序文件中,它应该可以工作

这里我注册了一个新的转换器,它将始终以ISO_LOCAL_TIME格式转换
LocalTime
。您也可以选择使用其他日期格式化程序

  @Bean
  public ConversionService conversionService() {
    ApplicationConversionService conversionService = new ApplicationConversionService();
    conversionService.addConverter(
        String.class,
        LocalTime.class,
        (Converter) source -> LocalTime.parse((String) source, DateTimeFormatter.ISO_LOCAL_TIME));
    return conversionService;
  }

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

  • 使用
    LocalTime
    字段创建
    @ConfigurationProperties
    带注释的类(在您的情况下是MyApplicationSettings),并使用
    @EnableConfigurationProperties(MyApplicationSettings.class)
    @Configuration
    中注册它
  • application.properties
    中定义值:
  • 创建一个特殊的转换器,并确保它被Spring Boot应用程序扫描和加载。实际解析的逻辑可能不同,当然,实现任何您想要的,任何特定格式,语言环境-任何:
  • @组件
    @配置属性绑定
    公共类LocalTimeConverter实现转换器{
    @凌驾
    公共本地时间转换(字符串源){
    if(source==null){
    返回null;
    }
    返回LocalTime.parse(模式的source、DateTimeFormatter.of(“HH:mm:ss”);
    }
    }
    
  • 现在,
    @ConfigurationProperties
    类中的所有
    LocalTime
    项都将通过此转换器
    谢谢,这确实有效。我做了两个更改:
    source
    永远不能为
    null
    ,因此可以删除检查。我使用了
    LocalTime.parse(source)
    ,因为它默认为我想要的ISO-8601格式。