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

Java面经 2018-12-29 09:04:51

作者:yizhiwazi
链接:https://www.jianshu.com/p/f4654d251104

学习目标

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

 

使用教程

根据官方文档 Custom JSON Serializers and Deserializers ,想要提供自定义的序列化器和反序列化器给Jackson这位已经接@ResponseBody和@RestController的HTTP消息转换器老大哥,只要通过注解@JsonComponent声明其静态内部类即可。

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

  • DateJsonSerializer extends JsonSerializer<Date> 表示将Date格式化为日期字符串。
  • DateJsonDeserializer extends JsonDeserializer<Date> 表示将日期字符串解析为Date日期。
/**
 * 全局日期格式化
 */
@JsonComponent
public class DateFormatConfig {
 private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 /**
 * 日期格式化
 */
 public static class DateJsonSerializer extends JsonSerializer<Date> {
 @Override
 public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
 jsonGenerator.writeString(dateFormat.format(date));
 }
 }
 /**
 * 解析日期字符串
 */
 public static class DateJsonDeserializer extends JsonDeserializer<Date> {
 @Override
 public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
 try {
 return dateFormat.parse(jsonParser.getText());
 } catch (ParseException e) {
 throw new RuntimeException(e);
 }
 }
 }
}

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

/**
 * 查询用户信息
 */
@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") {
 @Override
 public 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;//这里是指获取当前登录人的工具类
 @Autowired
 public void setUserController(UserController userController) {
 DateFormatConfig.userController = userController;
 }
 /**
 * 日期格式化
 */
 public static class DateJsonSerializer extends JsonSerializer<Date> {
 @Override
 public 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> {
 @Override
 public 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"
}

小结

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

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

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值