1. 程式人生 > >SpringMVC DateTimeFormat和Converter衝突問題

SpringMVC DateTimeFormat和Converter衝突問題

專案老介面中日期引數是通過@DateTimeFormat接收並格式化的,而且多有種日期格式,為了統一管理,準備將新介面日期引數統一為時間戳。新增時間戳日期轉換類後,發現之前介面的@DateTimeFormat都失效了,為了相容老介面,只能檢視原始碼對有無@DateTimeFormat的日期型別分別怎樣處理。

結果發現,當引數解析需要型別轉換時,會先查詢轉換器,並檢查轉換器是否匹配,然後通過轉換器做型別轉換。

當沒有加入Converter<String, Date>時,帶有@DateTimeFormat註解的日期引數會得到DateTimeFormatAnnotationFormatterFactory作為轉換器工廠,實現型別轉換。沒有@DateTimeFormat註解的日期引數會得到ObjectToObjectConverter作為轉換器實現型別轉換。

當加入Converter<String, Date>後,所有的日期引數都會優先獲得這個轉換器,因此導致@DateTimeFormat註解失效。

在新增型別轉換工具時,會將新加入的Bean放在儲存連結串列的前面,保證比預設轉換器優先找到。相關程式碼如下

// GenericConversionService的內部類
private static class ConvertersForPair {
		// 儲存型別轉換工具的List
		private final LinkedList<GenericConverter> converters = new LinkedList<
>(); public void add(GenericConverter converter) { this.converters.addFirst(converter); } //其他屬性方法略 }

個人感覺,無法通過修改配置的的手段解決衝突問題,所以只能通過修改Converter<String, Date>類以相容之前的日期格式來解決問題了,最後貼出日期轉化工具。

/**
 * 字串->日期轉換器
 *
 * @author ly
 */
public class StringToDateConverter implements Converter
<String, Date> { /** * 日期正則表示式 */ private static final String DATE_REGEX = "[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])"; /** * 日期格式 */ private static final String DATE_PATTERN = "yyyy-MM-dd"; /** * 時間正則表示式 */ private static final String TIME_REGEX = "(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d"; /** * 時間格式 */ private static final String TIME_PATTERN = "HH:mm:ss"; /** * 日期和時間正則表示式 */ private static final String DATE_TIME_REGEX = DATE_REGEX + "\\s" + TIME_REGEX; /** * 日期和時間格式 */ private static final String DATE_TIME_PATTERN = DATE_PATTERN + " " + TIME_PATTERN; /** * 13位時間戳正則表示式 */ private static final String TIME_STAMP_REGEX = "1\\d{12}"; /** * 年和月正則表示式 */ private static final String YEAR_MONTH_REGEX = "[1-9]\\d{3}-(0[1-9]|1[0-2])"; /** * 年和月格式 */ private static final String YEAR_MONTH_PATTERN = "yyyy-MM"; @Override public Date convert(String source) { if (StringUtils.isEmpty(source)) { return null; } if (source.matches(TIME_STAMP_REGEX)) { return new Date(Long.valueOf(source)); } DateFormat format; if (source.matches(DATE_TIME_REGEX)) { format = new SimpleDateFormat(DATE_TIME_PATTERN); } else if (source.matches(DATE_REGEX)) { format = new SimpleDateFormat(DATE_PATTERN); } else if (source.matches(YEAR_MONTH_REGEX)) { format = new SimpleDateFormat(YEAR_MONTH_PATTERN); } else { throw new IllegalArgumentException(); } try { return format.parse(source); } catch (ParseException e) { throw new RuntimeException(e); } } }