有时在Spring MVC中返回JSON格式的response的时候会使用@ResponseBody
注解,不过在处理时间的时候会很麻烦,一般我们使用的HTTPMessageConverter是MappingJackson2HttpMessageConverter
,它默认返回的时间格式是这种:
1 "startDate" : { 2 "year" : 2010, 3 "month" : "JANUARY", 4 "dayOfMonth" : 1, 5 "dayOfWeek" : "FRIDAY", 6 "dayOfYear" : 1, 7 "monthValue" : 1, 8 "hour" : 2, 9 "minute" : 2, 10 "second" : 0, 11 "nano" : 0, 12 "chronology" : { 13 "id" : "ISO", 14 "calendarType" : "iso8601" 15 } 16 }
但是一般情况下我们不会返回这种给前端使用,针对LocalDate想要返回的格式是2016-11-26,而LocalDateTime想要返回的格式是
2016-11-26
21:04:34
这样的数据。通过项目研究并查阅相关资料,这里介绍下个人研究中实现的两种方式。
解决方法一:
若是maven项目,在pom中引入下面的jar包:
1 <dependency> 2 <groupId>com.fasterxml.jackson.datatype</groupId> 3 <artifactId>jackson-datatype-jsr310</artifactId> 4 <version>2.8.5</version> 5 </dependency>
然后在你想要JSON化的POJO字段的get函数上加上一个@JsonSerializer
注解,如下
1 import com.fasterxml.jackson.annotation.JsonFormat; 2 3 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") 4 public LocalDateTime getBirthday() { 5 return this.loginTime; 6 } 7 8 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") 9 public LocalDateTime getLastLoginTime() { 10 return this.loginTime; 11 }
这种方式的优点是可以针对具体域类型设置不同显示方式,然而优点也是缺点,因为要在各个POJO上写上诸如上面的注解,并且需要额外引入jsr310的jar包。
解决方法二:
自定义LocalDate和LocalDateTime的序列化类,并注册到object mapper中
1 /** 2 * json处理工具类 3 * 4 * 5 */ 6 @Component 7 public class JsonUtil { 8 9 private static final ObjectMapper mapper; 10 11 public ObjectMapper getMapper() { 12 return mapper; 13 } 14 15 static { 16 17 mapper = new ObjectMapper(); 18 19 SimpleModule module = new SimpleModule(); 20 module.addSerializer(LocalDate.class, new LocalDateSerializer()); 21 module.addSerializer(LocalTime.class, new LocalTimeSerializer()); 22 module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); 23 mapper.registerModule(module); 24 } 25 26 public static String toJson(Object obj) { 27 try { 28 return mapper.writeValueAsString(obj); 29 } catch (Exception e) { 30 throw new RuntimeException("转换json字符失败!"); 31 } 32 } 33 34 public <T> T toObject(String json, Class<T> clazz) { 35 try { 36 return mapper.readValue(json, clazz); 37 } catch (IOException e) { 38 throw new RuntimeException("将json字符转换为对象时失败!"); 39 } 40 } 41 } 42 43 class LocalDateSerializer extends JsonSerializer<LocalDate> { 44 45 private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 46 47 @Override 48 public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) 49 throws IOException, JsonProcessingException { 50 jgen.writeString(dateFormatter.format(value)); 51 } 52 } 53 54 class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { 55 56 private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 57 58 @Override 59 public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider) 60 throws IOException, JsonProcessingException { 61 jgen.writeString(dateTimeFormatter.format(value)); 62 } 63 64 } 65 66 class LocalTimeSerializer extends JsonSerializer<LocalTime> { 67 68 private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); 69 70 @Override 71 public void serialize(LocalTime value, JsonGenerator jgen, SerializerProvider provider) 72 throws IOException, JsonProcessingException { 73 jgen.writeString(timeFormatter.format(value)); 74 75 } 76 77 }
然后在springmvc的配置文件中,再将<mvc:annotation-driven/>改为以下配置,配置一个新的json转换器,将它的ObjectMapper对象设置为JsonUtil中的objectMapper对象,此转换器比spring内置的json转换器优先级更高,所以与json有关的转换,spring会优先使用它。
1 <mvc:annotation-driven> 2 <mvc:message-converters> 3 <bean 4 class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 5 <property name="objectMapper" value="#{jsonUtil.mapper}" /> 6 <property name="supportedMediaTypes"> 7 <list> 8 <value>application/json;charset=UTF-8</value> 9 </list> 10 </property> 11 </bean> 12 </mvc:message-converters> 13 </mvc:annotation-driven>
然后java8中的几种日期和时间类型就可以正常友好的显示了。优点是全局统一管理日期和时间等类型,缺点对pojo中的某个域做特殊处理。
时间: 2024-10-10 17:18:32