從 Spring 3.x 之後,提供了 org.springframework.core.convert 定義了通用的型態轉換介面等機制,在 Spring MVC 中,可做為 PropertyEditor 的替代機制。
型態轉換的邏輯,主要可實作 Converter 介面來達成:
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
S 是來源型態,T 是目標型態,例如,若想將 String 轉換為 LocalDateTime:
package cc.openhome.aspect;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.springframework.core.convert.converter.Converter;
public class StringToLocalDateTimeConvertor implements Converter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String millis) {
System.out.println("converter");
return Instant.ofEpochMilli(Long.parseLong(millis))
.atZone(ZoneId.of("Asia/Taipei"))
.toLocalDateTime();
}
}
WebDataBinder 內部會使用一些 Converter 來進行型態轉換,例如,若請求參數值實際上代表某個整數值,在處理器的參數為 Long 的話,就會自動將之剖析為 Long(透過 StringToNumberConverterFactory);如果要加入自定義的 Converter 實例,可以在 WebConfig 中定義:
... 略
public class WebConfig implements WebMvcConfigurer, ApplicationContextAware {
...
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToLocalDateTimeConvertor());
}
}
這麼一來,若有個控制器中有處理器被標示為:
@PostMapping("do_foo")
protected String doFoo(@RequestParam("millis") LocalDateTime localDateTime) {
/// ...做點事
}
就會使用以上定義的 LocalDateTimeConvertor 將字串轉換為 LocalDateTime 實例。
如上所述,Spring 內建了一些轉換器,例如,Spring 可使用請求參數值中的 , 來切割請求參數值,視你處理器上的參數而定,若為 String[] millis,就會使用 StringToArrayConverter 將 millis=1234,5678 轉換為陣列,若為 List<String> millis,就會使用 StringToCollectionConverter 轉換。
PropertyEditor 仍然適用於簡單的場合,然而,使用 Converter 的好處在於可以彼此銜接,如果你定義了上面的 StringToLocalDateTimeConvertor,而處理器參數為 List<LocalDateTime> millis,millis=1234,5678 這樣的請求參數,就會被轉換為 List<LocalDateTime> 實例。
如果請求參數已經被 PropertyEditor 編輯過了,那麼就不會套用 Converter 的機制。

