首先根據項目要求提供自定義的日期序列化器和反序列化器,其中包括:
- DateJsonSerializerextendsJsonSerializer 表示將Date格式化為日期字符串。
- DateJsonDeserializerextendsJsonDeserializer 表示將日期字符串解析為Date日期。
使用注解 @JsonComponent 可以快速自定義日期格式化的序列化器,免除傳統通過模塊注冊的煩惱。
使用注解 @JsonComponent 實現與當地無關的動態時區的精髓就在于將獲取當前等人的方法寫在解析日期和格式化日期的代碼里。
使用注解 @JsonComponent 是直接處理String和Date的相互轉換的,所以要注意空串問題。例如dateFormat.parse()要預防空串
@JsonComponent自定義日期格式化的序列化器
@JsonComponent
public class DateFormatCofig{private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** 日期格式化*/public static class DateJsonSerializer extends JsonSerializer<Date> {@Overridepublic void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeString(dateFormat.format(date));}}/*** 解析日期字符串*/public static class DateJsonDeserializer extends JsonDeserializer<Date> {@Overridepublic Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {try {return dateFormat.parse(jsonParser.getText());} catch (ParseException e) {throw new RuntimeException(e);}}}
}
Controller進行測試
@RestController
public class UserController {@GetMapping("/")public User get() {return new User("1", "socks", "123456", new Date(), "GMT");}
}
public class User {private String userId;private String username;private String password;private Date createTime;private String timezone;public User(String userId, String username, String password, Date createTime, String timezone) {this.userId = userId;this.username = username;this.password = password;this.createTime = createTime;this.timezone = timezone;}//省略getters&setters
}
啟動應用并訪問 http://127.0.0.1:8080 ,可以拿到正確結果:
{"userId": "1","username": "socks","password": "123456","createTime": "2018-12-26 01:03:25"
}
除了日期格式化解析之外,我們還可以在 DateFormatConfig 注入業務變量,例如根據當前登錄人的所屬時區(雖然 SimpleDateFormat默認讀取了當地時區,但在實際的國際化系統中,用戶的所屬時區是指其在系統錄入的所屬時區,而不是指當地時區。例如Tony這個用戶賬號掛在GMT+0時區,但此時他出差在香港使用,系統仍需要按照GMT+0時區來顯示時間),為了解決這個問題,此時我們可以在 DateFormatConfig 注入當前登錄人然后改變日期工具類的 TimeZone來動態修改時區。
@JsonComponent
public class DateFormatConfig {private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z") {@Overridepublic Date parse(String source) throws ParseException {try {if (StringUtils.isEmpty(source)) {return null;}return super.parse(source);} catch (Exception e) {return new StdDateFormat().parse(source);}}};private static UserController userController;//這里是指獲取當前登錄人的工具類@Autowiredpublic void setUserController(UserController userController) {DateFormatConfig.userController = userController;}/*** 日期格式化*/public static class DateJsonSerializer extends JsonSerializer<Date> {@Overridepublic void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {//獲取當前登錄人的所屬時區dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));//格式化日期jsonGenerator.writeString(dateFormat.format(date));}}/*** 解析日期字符串*/public static class DateJsonDeserializer extends JsonDeserializer<Date> {@Overridepublic Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {try {//獲取當前登錄人的所屬時區dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));//解析日期return dateFormat.parse(jsonParser.getText());} catch (ParseException e) {throw new RuntimeException(e);}}}
}
修改完后重新啟動應用并訪問 http://127.0.0.1:8080 ,可以拿到正確結果:
{"userId": "1","username": "socks","password": "123456","createTime": "2018-12-25 17:35:50 +0000","timezone": "GMT"
}