1. 概述
有時,我們希望能夠指定應用程序使用的 時區。對於全球運行的服務,這意味着所有服務器都使用相同的 時區 來發布事件,無論它們的位置如何。
我們可以通過多種方式實現這一點。一種方法是使用 JVM 參數在執行應用程序時進行配置。另一種方法是在應用程序啓動生命週期的各個階段,通過代碼在程序中進行更改。
在本簡短教程中,我們將探討幾種設置 Spring Boot 應用程序默認 時區 的方法。首先,我們將看到如何通過命令行實現這一點,然後,我們將深入研究在 Spring Boot 代碼中在啓動時以編程方式執行此操作的選項。最後,我們將研究這些方法的差異。
2. 核心概念
默認值 TimeZone 基於 JVM 運行的機器的操作系統。我們可以更改它:
- 通過傳遞 JVM 參數,使用 user.timezone 參數,具體方式取決於我們是否運行任務或 JAR 文件
- 通過程序方式,使用 Bean 生命週期配置選項(在 Bean 創建期間/之前,或在類內部,在執行期間)
設置 TimeZone 的默認值會影響不同的組件,例如日誌的時間戳、調度器、JPA/Hibernate 時間戳等。這意味着我們的選擇取決於何時需要它生效。例如,我們是在某個 Bean 的創建期間,還是在 WebApplicationContext 初始化之後?
確定設置此值的時間非常重要,因為它可能會導致應用程序出現意外行為。例如,一個警報服務可能會在時間區更改生效之前設置警報,從而導致警報在錯誤的時間激活。
在選擇哪種選項之前,還需要考慮可測試性。使用 JVM 參數是最簡單的選項,但測試起來可能會更困難,並且更容易出現錯誤。沒有保證單元測試將使用與生產部署相同的 JVM 參數。
3. 在 bootRun 任務中設置默認 時區
如果使用 bootRun 任務運行應用程序,可以在命令行中通過 JVM 參數設置默認 時區。在這種情況下,我們設置的值將在執行的開端立即可用:
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Duser.timezone=Europe/Athens"4. 在 JAR 執行時設置默認時區
類似於運行 bootRun 任務,在執行 JAR 文件時,我們可以通過命令行傳遞默認 TimeZone 值。 同樣地,我們設置的值將在執行的開始時可用:
java -Duser.timezone=Europe/Athens -jar spring-core-4-0.0.1-SNAPSHOT.jar5. 在 Spring Boot 啓動時設置默認時區
讓我們看看如何在 Spring 的啓動過程中插入時區更改。
5.1. 主方法
首先,假設我們設置了 main 方法內的值。在這種情況下,我們可以在執行的早期階段就獲得它,即使在檢測到 Spring Profile 之前也是如此:
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00"));
SpringApplication.run(MainApplication.class, args);
}
}
雖然這是生命週期中的第一步,但它沒有充分利用我們與 Spring 配置所提供的可能性。我們必須硬編碼時區,或者通過讀取環境變量等方式進行編程讀取。
5.2. <em >BeanFactoryPostProcessor</em>
其次,BeanFactoryPostProcessor 是一個工廠鈎子,允許我們修改應用程序上下文的 Bean 定義。 這樣,我們在 Bean 實例化之前設置了值:
@Component
public class GlobalTimezoneBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
TimeZone.setDefault(TimeZone.getTimeZone("GMT+08:00"));
}
}5.3. <em PostConstruct</em>>
最後,我們可以利用 <em PostConstruct</em>> 屬性來在 <em MainApplication</em>> 類中設置默認的 <em TimeZone</em>> 值,在 <em WebApplicationContext</em>> 初始化完成後立即執行。 在此時點,我們可以從我們的配置屬性中注入 <em TimeZone</em>> 值:
@SpringBootApplication
public class MainApplication {
@Value("${application.timezone:UTC}")
private String applicationTimeZone;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@PostConstruct
public void executeAfterMain() {
TimeZone.setDefault(TimeZone.getTimeZone(applicationTimeZone));
}
}6. 結論
在本簡短教程中,我們學習了多種設置 Spring Boot 應用程序默認 TimeZone 的方法。我們討論了更改默認值的潛在影響,並基於這些因素,我們應該能夠為我們的用例選擇合適的方案。