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

2022-09-14 11:35:44

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

使用教程

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

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

  • DateJsonSerializer extends JsonSerializer<Date> 表示将Date格式化为日期字符串。
  • DateJsonDeserializer extends JsonDeserializer<Date> 表示将日期字符串解析为Date日期。
/**
 * 全局日期格式化
 */@JsonComponentpublicclassDateFormatConfig{privatestaticSimpleDateFormat dateFormat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");/**
     * 日期格式化
     */publicstaticclassDateJsonSerializerextendsJsonSerializer<Date>{@Overridepublicvoidserialize(Date date,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throwsIOException{
            jsonGenerator.writeString(dateFormat.format(date));}}/**
     * 解析日期字符串
     */publicstaticclassDateJsonDeserializerextendsJsonDeserializer<Date>{@OverridepublicDatedeserialize(JsonParser jsonParser,DeserializationContext deserializationContext)throwsIOException,JsonProcessingException{try{return dateFormat.parse(jsonParser.getText());}catch(ParseException e){thrownewRuntimeException(e);}}}}

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

/**
 * 查询用户信息
 */@RestControllerpublicclassUserController{@GetMapping("/")publicUserget(){returnnewUser("1","socks","123456",newDate(),"GMT");}}/**
 * 用户信息
 */publicclassUser{privateString userId;privateString username;privateString password;privateDate createTime;privateString timezone;publicUser(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来动态修改时区。

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

/**
 * 全局日期格式化
 */@JsonComponentpublicclassDateFormatConfig{privatestaticSimpleDateFormat dateFormat=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"){@OverridepublicDateparse(String source)throwsParseException{try{if(StringUtils.isEmpty(source)){returnnull;}returnsuper.parse(source);}catch(Exception e){returnnewStdDateFormat().parse(source);}}};privatestaticUserController userController;//这里是指获取当前登录人的工具类@AutowiredpublicvoidsetUserController(UserController userController){DateFormatConfig.userController= userController;}/**
     * 日期格式化
     */publicstaticclassDateJsonSerializerextendsJsonSerializer<Date>{@Overridepublicvoidserialize(Date date,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throwsIOException{//获取当前登录人的所属时区
            dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));//格式化日期
            jsonGenerator.writeString(dateFormat.format(date));}}/**
     * 解析日期字符串
     */publicstaticclassDateJsonDeserializerextendsJsonDeserializer<Date>{@OverridepublicDatedeserialize(JsonParser jsonParser,DeserializationContext deserializationContext)throwsIOException,JsonProcessingException{try{//获取当前登录人的所属时区
                dateFormat.setTimeZone(TimeZone.getTimeZone(userController.get().getTimezone()));//解析日期return dateFormat.parse(jsonParser.getText());}catch(ParseException e){thrownewRuntimeException(e);}}}}

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

{"userId":"1","username":"socks","password":"123456","createTime":"2018-12-25 17:35:50 +0000","timezone":"GMT"}

小结

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

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

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

  • 作者:一个普通但努力的程序猿
  • 原文链接:https://blog.csdn.net/weixin_51977686/article/details/121262805
    更新时间:2022-09-14 11:35:44