最近工作中使用到了JDK1.8 time包,逐步取代以前的Date類,相比以前,time包的API的確好用多了,相關內容在網上有很多,就不累贅了。
但是有點蛋疼的地方在於LocalDateTime支持ISO8601標准,即[2018-10-10T05:51:31.924Z]。在MVC中,習慣性用[yyyy-MM-dd HH:mm:ss]。
好在Spring帶有注解。如:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss)
private LocalDateTime ldt;
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date
參數在Param上,可以使用@DateTimeFormat在參數或者參數實體的屬性上。對於參數在body上,則可以通過自定義拓展Formatter或者Converter<String, LocalDateTime>,網上也有很多,這里就提供一下代碼
@Configuration
public class LocalDateTimeFormatConfig {
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Formatter<span class="token generics function"><span class="token punctuation"><</span>LocalDate<span class="token punctuation">></span></span> <span class="token function">localDateFormatter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Formatter</span><span class="token generics function"><span class="token punctuation"><</span>LocalDate<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> String <span class="token function">print</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> LocalDate object<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Objects<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> object<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"yyyy-MM-dd"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> LocalDate <span class="token function">parse</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> String text<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> LocalDate<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"yyyy-MM-dd"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Formatter<span class="token generics function"><span class="token punctuation"><</span>LocalDateTime<span class="token punctuation">></span></span> <span class="token function">localDateTimeFormatter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Formatter</span><span class="token generics function"><span class="token punctuation"><</span>LocalDateTime<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> String <span class="token function">print</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> LocalDateTime object<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Objects<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> object<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"yyyy-MM-dd HH:mm:ss"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> LocalDateTime <span class="token function">parse</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> String text<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> LocalDateTime<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"yyyy-MM-dd HH:mm:ss"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Formatter<span class="token generics function"><span class="token punctuation"><</span>LocalTime<span class="token punctuation">></span></span> <span class="token function">localTimeFormatter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Formatter</span><span class="token generics function"><span class="token punctuation"><</span>LocalTime<span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> String <span class="token function">print</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> LocalTime object<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Objects<span class="token punctuation">.</span><span class="token function">isNull</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> object<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@Nullable</span> LocalTime <span class="token function">parse</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Nullable</span> String text<span class="token punctuation">,</span> <span class="token annotation punctuation">@Nullable</span> Locale locale<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>StringUtils<span class="token punctuation">.</span><span class="token function">hasText</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> null<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> LocalTime<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
public class LocalDateTimeConvertConfig {
<span class="token keyword">private</span> String dateTimePattern <span class="token operator">=</span> <span class="token string">"yyyy-MM-dd HH:mm:ss"</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> String datePattern <span class="token operator">=</span> <span class="token string">"yyyy-MM-dd"</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Converter<span class="token generics function"><span class="token punctuation"><</span>String<span class="token punctuation">,</span> LocalDateTime<span class="token punctuation">></span></span> <span class="token function">LocalDateTimeConvert</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span>
DateTimeFormatter df <span class="token operator">=</span> DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span>dateTimePattern<span class="token punctuation">)</span><span class="token punctuation">;</span>
LocalDateTime date <span class="token operator">=</span> null<span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
date <span class="token operator">=</span> LocalDateTime<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> df<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> date<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Converter<span class="token generics function"><span class="token punctuation"><</span>String<span class="token punctuation">,</span> LocalDate<span class="token punctuation">></span></span> <span class="token function">localDateConverter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span>
DateTimeFormatter df <span class="token operator">=</span> DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span>datePattern<span class="token punctuation">)</span><span class="token punctuation">;</span>
LocalDate date <span class="token operator">=</span> null<span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
date <span class="token operator">=</span> LocalDate<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span>df<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span><span class="token punctuation">{</span>
e<span class="token punctuation">.</span><span class="token function">printStackTrace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> date<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 這里是使用JackSon全局序列化LocalDateTime,而我使用是FastJso,蛋疼</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> LocalDateTimeSerializer <span class="token function">localDateTimeDeserializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">LocalDateTimeSerializer</span><span class="token punctuation">(</span>DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span>dateTimePattern<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Bean</span>
<span class="token keyword">public</span> Jackson2ObjectMapperBuilderCustomizer <span class="token function">jackson2ObjectMapperBuilderCustomizer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> builder <span class="token operator">-</span><span class="token operator">></span> builder<span class="token punctuation">.</span><span class="token function">serializerByType</span><span class="token punctuation">(</span>LocalDateTime<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token function">localDateTimeDeserializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
這里要說的問題就是現在工作項目中遇到的問題,使用的FastJson,而不是MVC默認的JackSon,在序列化LocalDateTime輸出到前端時候,是[2018-10-10T05:51:31.924Z],而想要輸出的是yyyy-MM-dd HH:mm:ss格式,至此我們需要定制LocalDateTime類的序列化。我們一樣可以使用注解解決,使用FastJson的@JSONField(format = “yyyy-MM-dd HH:mm:ss”),在需要特殊序列化的成員屬性上。
為了減少注解的使用,嘗試是否可以讓FastJson默認根據我們的規則去序列化LocalDateTime類。
首先祭出常規的FastJsonConfig:
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(
SerializerFeature.PrettyFormat,
SerializerFeature.WriteMapNullValue,
...
SerializerFeature.WriteNullStringAsEmpty);
fastJsonConfig.setCharset(Charset.forName("utf-8"));
...
使用ValueFilter:
ValueFilter valueFilter = (o, s, o1) -> {
if (null == o1) {
o1 = "";
}
if (o1 instanceof LocalDateTime){
o1 = ((LocalDateTime) o1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
return o1;
};
fastJsonConfig.setSerializeFilters(valueFilter);
// 缺點,這是過濾級別的序列化,序列化的結果取決於o1的值,如將LocalDateTime類型的o1轉換為String類型的o1,后續將不會調用LocalDateTime的序列化器,因為已經不是LocalDateTime類型了
指定fastJsonConfig的DateFormat:
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
...
// 缺點,指定后,將不會使用@JSONField注解上的format屬性,包括並不限於Date類,LocalDateTime類,LocalDate類。(慎用)
自定義LocalDateTimeSerializer實現ObjectSerializer接口,重寫write方法:
public class LocalDateTimeSerializer implements ObjectSerializer {
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> LocalDateTimeSerializer instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LocalDateTimeSerializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> String defaultPattern <span class="token operator">=</span> <span class="token string">"yyyy-MM-dd HH:mm:ss"</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token function">LocalDateTimeSerializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">write</span><span class="token punctuation">(</span>JSONSerializer serializer<span class="token punctuation">,</span> Object object<span class="token punctuation">,</span> Object fieldName<span class="token punctuation">,</span> Type fieldType<span class="token punctuation">,</span> <span class="token keyword">int</span> features<span class="token punctuation">)</span> <span class="token keyword">throws</span> IOException <span class="token punctuation">{</span>
SerializeWriter out <span class="token operator">=</span> serializer<span class="token punctuation">.</span>out<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>object <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token punctuation">{</span>
out<span class="token punctuation">.</span><span class="token function">writeNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
LocalDateTime result <span class="token operator">=</span> <span class="token punctuation">(</span>LocalDateTime<span class="token punctuation">)</span> object<span class="token punctuation">;</span>
out<span class="token punctuation">.</span><span class="token function">writeString</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>DateTimeFormatter<span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span>defaultPattern<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
}
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
serializeConfig.put(LocalDateTime.class, LocalDateTimeSerializer.instance);
fastJsonConfig.setSerializeConfig(serializeConfig);
// 缺點,@JSONField注解一樣會失效,僅限於LocalDateTime類
...
如果使用的是JackSon,只需要在實例化LocalDateTimeSerializer的時候,指定一個DateTimeFormatter即可,方便很多,FastJson完敗,有可能是我學藝不精,畢竟我是菜雞。
原文地址:https://blog.csdn.net/luomin369433047/article/details/88972543