HttpMessageConverter 簡介
HttpMessageConverter 是SpringMVC中提供的一個政策接口,它是一個消息轉換器類,Spring Mvc中就是由HttpMessageConverter負責轉換HTTP的請求和響應。
預設情況下,Spring Boot 會自動加載如下消息類型轉換器:
常見消息類型轉換器介紹:
- StringHttpMessageConverter:負責讀取字元串格式的資料和寫出二進制格式的資料(當傳回值是或者接受值是String類型時,是由這個處理)
- MappingJacksonHttpMessageConverter:負責讀取和寫入json格式的資料;(當傳回值是對象或者List,就由這個處理)
- ByteArrayHttpMessageConverter:負責讀取二進制格式的資料和寫出二進制格式的資料;
- FormHttpMessageConverter:負責讀取form送出的資料(能讀取的資料格式為 application/x-www-form-urlencoded,不能讀取multipart/form-data格式資料);負責寫入application/x-www-from-urlencoded和multipart/form-data格式的資料;
- ResourceHttpMessageConverter:負責讀取資源檔案和寫出資源檔案資料;
- SourceHttpMessageConverter:負責讀取和寫入xml中javax.xml.transform.Source定義的資料;
- Jaxb2RootElementHttpMessageConverter:負責讀取和寫入xml 标簽格式的資料;
- AtomFeedHttpMessageConverter:負責讀取和寫入Atom格式的資料;
- RssChannelHttpMessageConverter:負責讀取和寫入RSS格式的資料;
資料轉換流程
利用SpringMVC架構,可以使得我們在開發時,隻要在代碼中使用@RequestBody和@ResponseBody兩個注解,就可以分别完成從請求封包到對象和從對象到響應封包的轉換。而在源碼内部,其實這種靈活的消息轉換機制就是利用HttpMessageConverter來實作的。
HttpMessageConverter的調用是RequestResponseBodyMethodProcessor類的解析請求參數的方法resolveArgument()和處理傳回值的方法handleReturnValue()中進行調用的。這是關于@RequestBody和@ResponseBody兩個注解的原理。
消息轉換器接口
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
return (canRead(clazz, null) || canWrite(clazz, null) ?
getSupportedMediaTypes() : Collections.emptyList());
}
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
轉換器加載流程
消息轉換器是在項目啟動的時候通過WebMvcConfigurationSupport進行加載,當getMessageConverters()被調用的時候會通過configureMessageConverters()、addDefaultHttpMessageConverters()和extendMessageConverters()三個方法進行初始話消息轉換器。生成的消息轉換器放在List<HttpMessageConverter<?>> messageConverters集合中
protected final List<HttpMessageConverter<?>> getMessageConverters() {
if (this.messageConverters == null) {
this.messageConverters = new ArrayList();
// 加載委托給WebMvcConfigurer類型的Bean
this.configureMessageConverters(this.messageConverters);
if (this.messageConverters.isEmpty()) {
// 加載預設的轉換器
this.addDefaultHttpMessageConverters(this.messageConverters);
}
// 加載擴充消息轉換器
this.extendMessageConverters(this.messageConverters);
}
return this.messageConverters;
}
自定義消息轉換器
- FastJson 、Gson 等元件自帶常用json消息轉換器
- 實作HttpMessageConverter 接口
- 繼承 AbstractHttpMessageConverter 類
加載自定義消息轉換器
- 直接注入Bean 的方式替換
- 實作 WebMvcConfigurer#extendMessageConverters 接口方法
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
/**
* 直接注入 HttpMessageConverters
*/
@Bean
public HttpMessageConverters customConverters() {
return new HttpMessageConverters(configFastJsonHttpMessageConverter());
}
/**
* 實作 WebMvcConfigurer#extendMessageConverters 接口
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 注意加載順序
converters.add(0, configFastJsonHttpMessageConverter());
}
/**
* 配置JSON 消息轉換器
*/
private HttpMessageConverter<Object> configFastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
// 配置轉換特性
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringKeyAsString,
SerializerFeature.WriteMapNullValue
);
converter.setFastJsonConfig(fastJsonConfig);
// 設定處理消息類型
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
return converter;
}
}