如何指定 mysql 數(shù)據(jù)庫 datetime 數(shù)據(jù)的顯示時區(qū)
當使用 Java 語言和 spring boot 框架與 mysql 數(shù)據(jù)庫交互時,datetime 數(shù)據(jù)類型的默認時區(qū)會轉(zhuǎn)換為應(yīng)用程序服務(wù)器的時區(qū)。在部署場景中,需要針對不同時區(qū)的客戶端進行相應(yīng)的時區(qū)調(diào)整。
問題:
已有一款部署在東八區(qū)的 spring boot 應(yīng)用,需要為印度(東五區(qū))和越南(東七區(qū))兩國的客戶端提供統(tǒng)一的訪問。應(yīng)用程序已采用多數(shù)據(jù)源模式,不同國家的數(shù)據(jù)庫在數(shù)據(jù)庫結(jié)構(gòu)上完全相同,字段類型均為 datetime。目標是實現(xiàn)以下需求:
- 印度用戶查詢時,返回東五區(qū)的時間。
- 越南用戶查詢時,返回東七區(qū)的時間。
限制條件:
- 應(yīng)用程序代碼固定,無法進行大范圍的修改。
- 由于業(yè)務(wù)邏輯的復(fù)雜性,無法全局配置 spring.jackson.time-zone。
解決思路:
由于數(shù)據(jù)庫字段類型無法修改,因此需要從 controller 層進行時區(qū)調(diào)整。controller 中可以根據(jù) Session 信息判斷出用戶的所屬國家/地區(qū),再通過適當?shù)臅r區(qū)轉(zhuǎn)換操作實現(xiàn)需求。
具體步驟:
1. 創(chuàng)建 jackson2objectmapperbuilder bean
@bean @primary public jackson2objectmapperbuilder jackson2objectmapperbuilder() { return new jackson2objectmapperbuilder().serializerbytype(date.class, new dateserializer()); }
2. 自定義 date 序列化器 dateserializer
public class dateserializer extends stdserializer<date> { protected dateserializer() { super(date.class); } @override public void serialize(date value, jsongenerator gen, serializerprovider provider) throws ioexception { // 根據(jù) session 信息獲取目標時區(qū) timezone targettimezone = gettargettimezone(); // 將 date 對象轉(zhuǎn)換為指定時區(qū)的字符串 gen.writestring(new simpledateformat("yyyy-mm-dd hh:mm:ss").format(value)); } }
3. 獲取目標時區(qū)
private TimeZone getTargetTimeZone() { // 根據(jù) Session 信息判斷用戶所屬國家/地區(qū),并返回對應(yīng)的時區(qū) if (isIndia()) { return TimeZone.getTimeZone("Asia/Kolkata"); } else if (isVietnam()) { return TimeZone.getTimeZone("Asia/Ho_Chi_Minh"); } // 默認返回服務(wù)器時區(qū) return TimeZone.getDefault(); }
通過以上步驟,可以在不修改數(shù)據(jù)庫字段類型的情況下,實現(xiàn)不同國家/地區(qū)客戶端訪問同一數(shù)據(jù)庫不同時區(qū)時間的需求。