查看原文
其他

SpringBoot 全局日期格式化(基于注解)

MarkerHub 2022-11-21

小Hub领读:

json数据中的时间格式化一直都是程序员头疼的问题,这里看作者怎么使用 @JsonComponent来处理日期。另外还可以根据时区动态展示不同时间,厉害了,你会吗?


作者:yizhiwazi

链接:https://www.jianshu.com/p/f4654d251104

学习目标

快速学会通过注解 @JsonComponent自定义日期格式化的序列化器。

快速查阅

专题阅读:《SpringBoot 布道系列》:https://www.jianshu.com/p/964370d9374e

源码下载:SpringBoot Date Format Anno:https://github.com/yizhiwazi/springboot-socks

--- Hey Man,Don't forget to Star or Fork . ---

使用教程

根据官方文档 Custom JSON Serializers and Deserializers ,想要接管Jackson的JSON的序列化和反序列化,只需通过注解 @JsonComponent来声明其静态内部类即可。

首先根据项目要求提供自定义的日期序列化器和反序列化器,其中包括:

  • DateJsonSerializerextendsJsonSerializer<Date> 表示将Date格式化为日期字符串。

  • DateJsonDeserializerextendsJsonDeserializer<Date> 表示将日期字符串解析为Date日期。

  1. /**

  2. * 全局日期格式化

  3. */

  4. @JsonComponent

  5. public class DateFormatConfig {


  6. private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


  7. /**

  8. * 日期格式化

  9. */

  10. public static class DateJsonSerializer extends JsonSerializer<Date> {

  11. @Override

  12. public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

  13. jsonGenerator.writeString(dateFormat.format(date));

  14. }

  15. }


  16. /**

  17. * 解析日期字符串

  18. */

  19. public static class DateJsonDeserializer extends JsonDeserializer<Date> {

  20. @Override

  21. public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

  22. try {

  23. return dateFormat.parse(jsonParser.getText());

  24. } catch (ParseException e) {

  25. throw new RuntimeException(e);

  26. }


  27. }

  28. }

  29. }

然后提供相应的测试信息,这里以查询用户为例:

  1. /**

  2. * 查询用户信息

  3. */

  4. @RestController

  5. public class UserController {

  6. @GetMapping("/")

  7. public User get() {

  8. return new User("1", "socks", "123456", new Date(), "GMT");

  9. }

  10. }


  11. /**

  12. * 用户信息

  13. */

  14. public class User {


  15. private String userId;

  16. private String username;

  17. private String password;

  18. private Date createTime;

  19. private String timezone;


  20. public User(String userId, String username, String password, Date createTime, String timezone) {

  21. this.userId = userId;

  22. this.username = username;

  23. this.password = password;

  24. this.createTime = createTime;

  25. this.timezone = timezone;

  26. }


  27. //省略getters&setters

  28. }

大功告成,接下来启动应用并访问 http://127.0.0.1:8080 ,可以拿到正确结果:

  1. {

  2. "userId": "1",

  3. "username": "socks",

  4. "password": "123456",

  5. "createTime": "2018-12-26 01:03:25"

  6. }

除了日期格式化解析之外,我们还可以在 DateFormatConfig 注入业务变量,例如根据当前登录人的所属时区(虽然 SimpleDateFormat默认读取了当地时区,但在实际的国际化系统中,用户的所属时区是指其在系统录入的所属时区,而不是指当地时区。例如Tony这个用户账号挂在GMT+0时区,但此时他出差在香港使用,系统仍需要按照GMT+0时区来显示时间),为了解决这个问题,此时我们可以在 DateFormatConfig 注入当前登录人然后改变日期工具类的 TimeZone来动态修改时区。

Github上最值得学习的100个Java开源项目,涵盖各种技术栈!

根据当前登录人动态展示时区:

  1. /**

  2. * 全局日期格式化

  3. */

  4. @JsonComponent

  5. public class DateFormatConfig {


  6. private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z") {

  7. @Override

  8. public Date parse(String source) throws ParseException {

  9. try {

  10. if (StringUtils.isEmpty(source)) {

  11. return null;

  12. }

  13. return super.parse(source);

  14. } catch (Exception e) {

  15. return new StdDateFormat().parse(source);

  16. }

  17. }

  18. };


  19. private static UserController userController;//这里是指获取当前登录人的工具类


  20. @Autowired

  21. public void setUserController(UserController userController) {

  22. DateFormatConfig.userController = userController;

  23. }


  24. /**

  25. * 日期格式化

  26. */

  27. public static class DateJsonSerializer extends JsonSerializer<Date> {

  28. @Override

  29. public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

  30. //获取当前登录人的所属时区

  31. dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));

  32. //格式化日期

  33. jsonGenerator.writeString(dateFormat.format(date));

  34. }

  35. }


  36. /**

  37. * 解析日期字符串

  38. */

  39. public static class DateJsonDeserializer extends JsonDeserializer<Date> {

  40. @Override

  41. public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

  42. try {

  43. //获取当前登录人的所属时区

  44. dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));

  45. //解析日期

  46. return dateFormat.parse(jsonParser.getText());

  47. } catch (ParseException e) {

  48. throw new RuntimeException(e);

  49. }


  50. }

  51. }

  52. }

修改完后重新启动应用并访问 http://127.0.0.1:8080 ,可以拿到正确结果:

  1. {

  2. "userId": "1",

  3. "username": "socks",

  4. "password": "123456",

  5. "createTime": "2018-12-25 17:35:50 +0000",

  6. "timezone": "GMT"

  7. }

小结

1、使用注解 @JsonComponent 可以快速自定义日期格式化的序列化器,免除传统通过模块注册的烦恼。

2、使用注解 @JsonComponent 实现与当地无关的动态时区的精髓就在于将获取当前等人的方法写在解析日期和格式化日期的代码里。

3、使用注解 @JsonComponent 是直接处理String和Date的相互转换的,所以要注意空串问题。例如dateFormat.parse()要预防空串。


(完)

MarkerHub文章索引:(点击阅读原文直达)

https://github.com/MarkerHub/JavaIndex


【推荐阅读】

理解这9大内置过滤器,才算是精通Shiro

花30分钟,用Jenkins部署码云上的SpringBoot项目

只需要6个步骤,springboot集成shiro,并完成登录

eblog项目讲解视频上线啦,长达17个小时!!



好文!必须点赞

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存