概念
HttpMessageConverter
?是 Spring 框架中用于處理 HTTP 請求和響應數據的核心接口,負責在 Java 對象與 HTTP 消息體(請求體或響應體)之間進行雙向轉換。簡單來說,它是 Spring 用來將 HTTP 請求中的原始數據(如 JSON、XML、表單數據等)轉換為 Java 對象,或者將 Java 對象轉換為 HTTP 響應數據的“翻譯器”
就是返回的是 UserVO 對象,但是最后傳輸到前端時,變成了 Json 字符串
核心作用
- 序列化和反序列化
- 請求:將客戶端發送的 HTTP 請求體(如 JSON 字符串)反序列化為 Java 對象(如?
User
?類) - 響應:將 Java 對象(如?
User
?對象)序列化為客戶端需要的格式(如 JSON、XML)
- 請求:將客戶端發送的 HTTP 請求體(如 JSON 字符串)反序列化為 Java 對象(如?
- 內容協商:根據客戶端請求的?
Content-Type
(請求數據類型)和?Accept
(期望的響應數據類型),自動選擇匹配的?HttpMessageConverter
?處理數據格式
接口源碼
package org.springframework.http.converter;import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;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 !this.canRead(clazz, (MediaType)null) && !this.canWrite(clazz, (MediaType)null) ? Collections.emptyList() : this.getSupportedMediaTypes();}T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
根據源碼解釋作用:
- 在請求時,通過請求頭?
Content-Type
?上,表示請求內容(Request Body)的內容類型。這樣,Spring MVC 會從HttpMessageConverter
數組中,通過?canRead(clazz, mediaType)
?方法,判斷是否夠讀取指定的?mediaType
?內容類型,轉換成對應的?clazz
?對象。如果可以的話,則調用read(Class<? extends T> clazz, HttpInputMessage inputMessage)
?方法,讀取請求內容,轉換成?clazz
?對象。 - 在響應時,通過請求頭?
Accept
?上,表示請求內容(Response Body)的內容類型。Spring MVC 會從HttpMessageConverter
數組中,通過?canWrite(clazz, mediaType)
?方法,判斷是否能夠將?clazz
?對象,序列化成?mediaType
?內容類型。如果可以的話,則調用write(contentType, outputMessage)
?方法,將?clazz
?對象,序列化成?contentType
?內容類型,寫入到響應。
常見實現方法
內置了多種?HttpMessageConverter
?實現,支持不同數據格式
實現類 | 作用 |
---|---|
MappingJackson2HttpMessageConverter | 處理 JSON 格式(基于 Jackson 庫) |
GsonHttpMessageConverter | 處理 JSON 格式(基于 Gson 庫) |
Jaxb2RootElementHttpMessageConverter | 處理 XML 格式(基于 JAXB) |
StringHttpMessageConverter | 處理純文本(如?text/plain ) |
FormHttpMessageConverter | 處理表單數據(application/x-www-form-urlencoded ) |
案例
同時支持?JSON/XML?格式提交數據,也同時支持?JSON/XML?格式響應數據的案例
XmlMapper 是 Jackson 提供的用于處理 XML 的類,位于
jackson-dataformat-xml
模塊中。默認情況下,SpringBoot 并不會自動包含該模塊,需要手動添加相關依賴。
配置
重寫 MappingJackson2XmlHttpMessageConverter 配置類,新增 XML 格式
@Configuration
@RequiredArgsConstructor
public class SpringMVCConfiguration implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {Jackson2ObjectMapperBuilder xmlBuilder = Jackson2ObjectMapperBuilder.xml();xmlBuilder.indentOutput(true);converters.add(new MappingJackson2XmlHttpMessageConverter(xmlBuilder.build()));}
}
接口
新增接口
@RestController
@RequestMapping("/users")
public class UserController {@PostMapping(value = "/addXml",// ↓ 增加 "application/xml"、"application/json" ,針對 Content-Type 請求頭consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},// ↓ 增加 "application/xml"、"application/json" ,針對 Accept 請求頭produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})public UserVO addXml(@RequestBody UserAddDTO addDTO) {return new UserVO().setUsername("username: " + addDTO.getUsername());}}
- consumes 屬性:限制可接受的請求內容類型,不匹配時返回
415 Unsupported Media Type
狀態碼- produces 屬性:限制可返回的響應內容類型,不匹配時返回
406 Not Acceptable
狀態碼
請求接口
POST http://localhost:8080/users/addXml
Content-Type: application/xml
Accept: application/xml <user> <id>1</id> <username>張三</username> <password>123456</password>
</user>
返回
<Result><code>200</code><msg>成功</msg><data><id/><username>username: 張三</username></data>
</Result>
Fastjson 依賴
在 SpringBoot 中默認是用 Jackson 作為對 JSON 的序列化和反序列化,即默認使用?MappingJackson2HttpMessageConverter
(基于 Jackson 庫)處理 JSON 數據,有時候可以使用第三方依賴來替換 Jackson 實現對 JSON 的序列化和反序列化,比如 Fastjson 依賴。
Fastjson?是阿里巴巴開源的一款高性能 Java JSON 庫,用于實現 Java 對象與 JSON 數據之間的序列化(對象 → JSON)和反序列化(JSON → 對象)。它的核心目標是提供極致的 JSON 處理性能(號稱“最快的 JSON 庫”),同時支持復雜的 Java 類型(如泛型、枚舉、Lambda 表達式)和靈活的配置。
使用原因
- 性能優勢
- 更快的處理速度:在序列化和反序列化時通常比 Jackson 更快(尤其是處理大對象或復雜結構時),適合高并發場景
- 低內存占用:Fastjson 的設計優化了內存使用,減少 GC 壓力
- 功能豐富性
- 支持復雜類型:如泛型、
LocalDateTime
、枚舉等,無需額外配置 - 靈活的注解:通過?
@JSONField
?注解可自定義字段名稱、格式、忽略字段等 - 定制化配置
- 支持復雜類型:如泛型、
- 易用性
- 簡潔的API:Fastjson 提供類似?
JSON.toJSONString(obj)
?和?JSON.parseObject(json, User.class)
?的直接方法 - 中文支持友好
- 簡潔的API:Fastjson 提供類似?
配置過程
添加 Fastjson
依賴
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.50</version>
</dependency>
添加 Fastjson
依賴后,需要排除掉默認 Jackson
依賴(如果你不需要它的話)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></exclusion></exclusions>
</dependency>
配置 Fastjson
@Configuration
@RequiredArgsConstructor
public class SpringMVCConfiguration implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {// 定義一個convert轉換消息的對象FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();// 添加fastjson的配置信息FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(// 格式化輸出SerializerFeature.PrettyFormat,// 輸出空字段SerializerFeature.WriteMapNullValue,// 日期格式化SerializerFeature.WriteDateUseDateFormat);fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);// 處理中文亂碼問題List<MediaType> fastMediaTypes = new ArrayList<>();// fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);fastMediaTypes.add(MediaType.APPLICATION_JSON);fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);// 在converters中添加fastjson的配置信息converters.add(0, fastJsonHttpMessageConverter);}}
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8)
會有'APPLICATION_JSON_UTF8' is deprecated
提示,因為 Framework 自 5.2 起,推薦使用MediaType.APPLICATION_JSON
,因為主要瀏覽器(如 Chrome)現在遵循規范,能夠正確解析UTF-8
特殊字符,而無需在 Content-Type 中指定 charset=UTF-8 參數。
setSerializerFeatures
方法
config.setSerializerFeatures
?是 Fastjson 中用于配置 JSON?序列化行為的核心方法,它通過啟用或禁用不同的?SerializerFeature
?枚舉值,控制 Java 對象轉換為 JSON 字符串時的具體規則
Fastjson?默認的序列化行為較為簡潔(例如不輸出空字段、日期使用時間戳格式),但在實際開發中,我們通常需要更靈活的配置。
場景示例 | 默認行為 | 配置特性后的行為 |
---|---|---|
空字段處理 | 忽略?null ?字段 | 輸出?{"name": null} |
日期格式 | 日期轉為時間戳(如?1672531200000 ) | 轉為?"2023-01-01 00:00:00" |
JSON 可讀性 | 壓縮輸出(無縮進換行) | 格式化輸出(帶縮進和換行) |
枚舉類型處理 | 輸出枚舉的?name() ?值 | 輸出枚舉的?ordinal() ?值 |
PrettyFormat
:格式化 JSON 輸出,添加換行和縮進,使 JSON 更易閱讀
// 未啟用 PrettyFormat
{"name":"Alice","age":25}// 啟用 PrettyFormat
{"name": "Alice","age": 25
}
WriteMapNullValue
:序列化時保留值為?null
?的字段
// 未啟用 WriteMapNullValue
{"name":"Alice"}// 啟用 WriteMapNullValue
{"name":"Alice", "age":null}
WriteDateUseDateFormat
:將?Date
?類型字段按指定格式(如?yyyy-MM-dd HH:mm:ss
)序列化
config.setDateFormat("yyyy-MM-dd");
// 輸出
{"birthday": "2023-01-01"}
WriteEnumUsingToString
:將枚舉類型按?toString()
?方法的值輸出,而非默認的?name()
enum Status { OPEN("開啟"), CLOSE("關閉"); }
// 默認輸出 "OPEN"
// 啟用后輸出 "開啟"
參考
- 芋道 Spring Boot SpringMVC 入門 | 芋道源碼 —— 純源碼解析博客
- 使用HttpMessageConverter實現HTTP的序列化和反序列化 - duanxz - 博客園
- Title Unavailable | Site Unreachable