1. 程式人生 > >【Spring】HttpMessageConverter的作用及替換

【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了。

相關推薦

SpringHttpMessageConverter作用替換

相信使用過Spring的開發人員都用過@RequestBody、@ResponseBody註解,可以直接將輸入解析成Json、將輸出解析成Json,但HTTP 請求和響應是基於文字的,意味著瀏覽器和伺服器通過交換原始文字進行通訊,而這裡其實就是HttpMessageConverter發揮著作用。HttpMes

SpringSpring MVC原理配置詳解

進行 return sub sca scrip uil 線程安全 松耦合 必須 1.Spring MVC概述: Spring MVC是Spring提供的一個強大而靈活的web框架。借助於註解,Spring MVC提供了幾乎是POJO的開發模式,使得控制器的開發和測試更加簡

SpringSpring各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中,雖然

SpringSpringMVC之異常處理

存儲 targe 存在 cnblogs del file 處理機制 href click java中的異常分為兩類,一種是運行時異常,一種是非運行時異常。在JavaSE中,運行時異常都是通過try{}catch{}捕獲的,這種只能捕獲顯示的異常,通常項目上拋出的異常都是不可

SpringSpringMVC之攔截器

https javax request orm bin 支持 exceptio 賬號 intern Spring的HandlerMapping處理器支持攔截器應用。當需要為某些請求提供特殊功能時,例如實現對用戶進行身份認證、登錄檢查等功能。 攔截器必須實現HandlerI

SpringSpringMVC之REST編程風格

data springmvc 4.0 gen rip servle truct -name insert REST架構是一個抽象的概念,目前主要是基於HTTP協議實現,其目的是為了提高系統的可伸縮性、降低應用之間的耦合度、便於架構分布式處理程序。 在URL中設置使用

Spring16、註解事務 @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架構,進程架構。在服務器端有主進程、服務進程、子進程、共享

Spring27、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