【Spring】HttpMessageConverter的作用及替換
相信使用過Spring的開發人員都用過@RequestBody、@ResponseBody註解,可以直接將輸入解析成Json、將輸出解析成Json,但HTTP 請求和響應是基於文字的,意味著瀏覽器和伺服器通過交換原始文字進行通訊,而這裡其實就是HttpMessageConverter發揮著作用。
HttpMessageConverter
Http請求響應報文其實都是字串,當請求報文到java程式會被封裝為一個ServletInputStream流,開發人員再讀取報文,響應報文則通過ServletOutputStream流,來輸出響應報文。
從流中只能讀取到原始的字串報文,同樣輸出流也是。那麼在報文到達SpringMVC / SpringBoot和從SpringMVC / SpringBoot出去,都存在一個字串到java物件的轉化問題。這一過程,在SpringMVC / SpringBoot中,是通過HttpMessageConverter來解決的。HttpMessageConverter介面原始碼:
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, MediaType mediaType);
boolean canWrite(Class<?> clazz, MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
下面以一例子來說明:
@RequestMapping("/test")
@ResponseBody
public String test(@RequestBody String param) {
return "param '" + param + "'";
}
在請求進入test方法前,會根據@RequestBody註解選擇對應的HttpMessageConverter實現類來將請求引數解析到param變數中,因為這裡的引數是String型別的,所以這裡是使用了StringHttpMessageConverter類,它的canRead()方法返回true,然後read()方法會從請求中讀出請求引數,繫結到test()方法的param變數中。
同理當執行test方法後,由於返回值標識了@ResponseBody,SpringMVC / SpringBoot將使用StringHttpMessageConverter的write()方法,將結果作為String值寫入響應報文,當然,此時canWrite()方法返回true。
借用下圖簡單描述整個過程:
00001.png
在Spring的處理過程中,一次請求報文和一次響應報文,分別被抽象為一個請求訊息HttpInputMessage和一個響應訊息HttpOutputMessage。
處理請求時,由合適的訊息轉換器將請求報文繫結為方法中的形參物件,在這裡同一個物件就有可能出現多種不同的訊息形式,如json、xml。同樣響應請求也是同樣道理。
在Spring中,針對不同的訊息形式,有不同的HttpMessageConverter實現類來處理各種訊息形式,至於各種訊息解析實現的不同,則在不同的HttpMessageConverter實現類中。
替換@ResponseBody預設的HttpMessageConverter
這裡使用SpringBoot演示例子,在SpringMVC / SpringBoot中@RequestBody這類註解預設使用的是jackson來解析json,看下面例子:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testt")
@ResponseBody
public User testt() {
User user = new User("name", 18);
return user;
}
}
public class User {
private String username;
private Integer age;
private Integer phone;
private String email;
public User(String username, Integer age) {
super();
this.username = username;
this.age = age;
}
}
瀏覽器訪問/user/testt返回如下:
00002.png
這就是使用jackson解析的結果,現在來改成使用fastjson解析物件,這裡就是替換預設的HttpMessageConverter,就是將其改成使用FastJsonHttpMessageConverter來處理Java物件與HttpInputMessage/HttpOutputMessage間的轉化。
首先新建一配置類來新增配置FastJsonHttpMessageConverter,Spring4.x開始推薦使用Java配置加註解的方式,也就是無xml檔案,SpringBoot就更是了。
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import java.nio.charset.Charset;
@Configuration
public class HttpMessageConverterConfig {
//引入Fastjson解析json,不使用預設的jackson
//必須在pom.xml引入fastjson的jar包,並且版必須大於1.2.10
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
//1、定義一個convert轉換訊息的物件
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//2、新增fastjson的配置資訊
FastJsonConfig fastJsonConfig = new FastJsonConfig();
SerializerFeature[] serializerFeatures = new SerializerFeature[]{
// 輸出key是包含雙引號
// SerializerFeature.QuoteFieldNames,
// 是否輸出為null的欄位,若為null 則顯示該欄位
// SerializerFeature.WriteMapNullValue,
// 數值欄位如果為null,則輸出為0
SerializerFeature.WriteNullNumberAsZero,
// List欄位如果為null,輸出為[],而非null
SerializerFeature.WriteNullListAsEmpty,
// 字元型別欄位如果為null,輸出為"",而非null
SerializerFeature.WriteNullStringAsEmpty,
// Boolean欄位如果為null,輸出為false,而非null
SerializerFeature.WriteNullBooleanAsFalse,
// Date的日期轉換器
SerializerFeature.WriteDateUseDateFormat,
// 迴圈引用
SerializerFeature.DisableCircularReferenceDetect,
};
fastJsonConfig.setSerializerFeatures(serializerFeatures);
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
//3、在convert中新增配置資訊
fastConverter.setFastJsonConfig(fastJsonConfig);
//4、將convert新增到converters中
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
}
這裡將字串型別的值如果是null就返回“”,數值型別的如果是null就返回0,重啟應用,再次訪問/user/testt介面,返回如下:
00003.png
可以看到此時null都轉化成“”或0了。
相關推薦
【Spring】HttpMessageConverter的作用及替換
相信使用過Spring的開發人員都用過@RequestBody、@ResponseBody註解,可以直接將輸入解析成Json、將輸出解析成Json,但HTTP 請求和響應是基於文字的,意味著瀏覽器和伺服器通過交換原始文字進行通訊,而這裡其實就是HttpMessageConverter發揮著作用。HttpMes
【Spring】Spring MVC原理及配置詳解
進行 return sub sca scrip uil 線程安全 松耦合 必須 1.Spring MVC概述: Spring MVC是Spring提供的一個強大而靈活的web框架。借助於註解,Spring MVC提供了幾乎是POJO的開發模式,使得控制器的開發和測試更加簡
【Spring】Spring各jar包的作用(轉載)
除了spring.jar檔案,Spring還包括有其它13個獨立的jar包,各自包含著對應的Spring元件,使用者可以根據自己的需要來選擇組合自己的jar包,而不必引入整個spring.jar的所有類檔案。 (1) spring-core.jar 這個jar檔案包含Spring框架基本
【Spring】的@scope註解作用
一般我們看程式碼都少會寫這個註解,因為預設不寫是單例模式,即scope="singleton"。另外scope還有prototype、request、session、global session作用域。 scope="prototype"多例 @scope預設是單例模式(singleto
【Spring】例項化上下文物件及載入多個配置檔案
一、例項化上下文物件 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Car car = (Car) ctx.getBean("car");
【Spring 】【AOP】註解開發及excution函式的使用
一、excution函式的使用 語法:[訪問修飾符] 返回值 包名.類名.方法名 (引數) 舉例1:public * com.test.Dao.userDal.save(..)//*任意返回值, .. 任意引數 二、註解開發 步驟1:引入相關JAR包
【Spring】——事務實現過程及原理
1、Spring中事務處理的作用: Spring事務處理,是將事務處理的工作統一起來,併為事務處理提供通用的支援。 2、工作原理及實現 a、劃分處理單元——IOC 由於spring解決的問
【Spring】- 自定義標籤及工作原理
浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>
【Spring】使用Spring和AMQP發送接收消息(上)
com load 設定 支持 消息發送 結果 alt 來看 接下來 講AMQP之前,先講下傳統的JMS的消息模型,JMS中主要有三個參與者:消息的生產者、消費者、傳遞消息的通道(隊列或者主題),兩種消息模型如下:通道是隊列: 通道是隊列: 通道是主題: 在JMS中,雖然
【Spring】SpringMVC之異常處理
存儲 targe 存在 cnblogs del file 處理機制 href click java中的異常分為兩類,一種是運行時異常,一種是非運行時異常。在JavaSE中,運行時異常都是通過try{}catch{}捕獲的,這種只能捕獲顯示的異常,通常項目上拋出的異常都是不可
【Spring】SpringMVC之攔截器
https javax request orm bin 支持 exceptio 賬號 intern Spring的HandlerMapping處理器支持攔截器應用。當需要為某些請求提供特殊功能時,例如實現對用戶進行身份認證、登錄檢查等功能。 攔截器必須實現HandlerI
【Spring】SpringMVC之REST編程風格
data springmvc 4.0 gen rip servle truct -name insert REST架構是一個抽象的概念,目前主要是基於HTTP協議實現,其目的是為了提高系統的可伸縮性、降低應用之間的耦合度、便於架構分布式處理程序。 在URL中設置使用
【Spring】16、註解事務 @Transactional
引用 相關 連接池 每次 one 作用 事務性 簡單 這一 概述 事務管理對於企業應用來說是至關重要的,即使出現異常情況,它也可以保證數據的一致性。Spring Framework對事務管理提供了一致的抽象,其特點如下: 為不同的事務API提供一致的編程模型,
大數據【二】HDFS部署及文件讀寫(包含eclipse hadoop配置)
throw 大數據 我的電腦 ssh 生效 manager 方法 slave .sh 一 原理闡述 1‘ DFS 分布式文件系統(即DFS,Distributed File System),指文件系統管理的物理存儲資源不一定直接連接在本地節點上,而是通過計算機網
【PostgreSQL】進程及體系結構
體系結構 同時 image add 負責 com blog images 後臺 本文主要講述了PG的幾個主要進程,以及PG的核心架構。進程和體系結構詳見下圖: 從上面的體系結構圖可以看出來,PG使用經典的C/S架構,進程架構。在服務器端有主進程、服務進程、子進程、共享
【Spring】27、JPA 實現樂觀鎖@Version註解的使用
線程並發 基礎上 nal where 本質 項目需求 得到 業務 -s 持久層使用jpa時,默認提供了一個註解@Version來實現樂觀鎖 簡單來說就是用一個version字段來充當樂觀鎖的作用。先來設計實體類 /** * Created by xujingfeng on
【Linux】 JDK安裝及配置 (tar.gz版)
ubuntu logs 環境 pat source alt 修改 8.0 添加 安裝環境 Linux(Ubuntu 版) JDK安裝 tar.gz為解壓後就可以使用的版本,這裏我將使用jdk-8u65-linux-x64.tar.gz版,安裝到/usr/java/下
【一】MongoDB安裝及配置
.org root 終端 配置 conn tin serve cal 數據文件 一、MongoDB安裝 1、下載並解壓 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.0.tgz
Fiddler抓包【1】_介紹及界面概述
緩存 沒有 user 編輯器 主菜單 selected ble bar 文件格式 一、 主要抓包工具介紹與對比 1、Wireshark :通用抓包工具,抓取信息量龐大,需要過濾才能得到有用信息,只抓HTTP請求有點大財小用。 2、Firebug、HttpWatch等We