【SpringMVC】淺談Convert/Format機制與HttpMessageConverter的關係

簡介

Spring3引入了較Spring2的PropertyEditor更增強大、通用的Convert/Format SPIConvert SPI能夠實現任意類型的轉換;Format SPI支持國際化,並在前者的基礎上實現了String與任意類型的轉換。這兩類SPI屬於spring-core,被整個spring-framework共享,是一種通用的類型轉換器。java

HttpMessageConverter雖然功能上也表現爲HttpMessage與任意類型的轉換,但其接口和Convert SPI並無繼承關係。HttpMessageConverter屬於spring-webHttpMessage是SpringMVC對Servlet規範中HttpServletRequestHttpServletResponse的包裝,所以接受請求時須要把HttpMessage轉換成用戶須要的數據,在生成響應時須要把用戶生成的數據轉換成HttpMessage。若是用戶在XML的<mvc:message-converters>中沒有指定register-defaults=false,SpringMVC默認至少會註冊一些自帶的HttpMessageConvertor(從前後順序排列分別爲ByteArrayHttpMessageConverterStringHttpMessageConverterResourceHttpMessageConverterSourceHttpMessageConverterAllEncompassingFormHttpMessageConverter)。web

若是後端服務使用Restful API的形式,通常使用JSON做爲先後端通訊的格式規範,因爲SpringMVC自帶MappingJackson2HttpMessageConverter,在依賴中引入jackson後,容器會把該轉換器自動註冊到converter鏈的末尾。ajax

二者的分工

Http請求中有幾個經常使用的部分能夠用來傳遞業務信息,以常見的GetPost方法爲例。spring

是否可用 URL Parameter Header Body
Get
Post

那麼上述的4個部分都是用HttpMessageConverter來進行類型轉換的嗎?顯然不是,HttpMessageConverterConvert SPI各有分工, HttpMessageConverte只負責解析Http包的Body體部分1,其他部分都交由相關的Convert SPI處理2後端

是否支持 URL Parameter Header Body
HttpMessageConverter
Convert SPI

除上表所示以外,SpringMVC還有一些須要Convert SPI的場景,如讀取Cookie值的@CookieValue(本質是Header),解析矩陣URL的@MatrixVariable(本質是URL),讀取本地會話的@SessionAttribute,解析SpEL的@Valuemvc

Convert SPI類型轉換實例

在SpringMVC中,單次請求的整個處理流程中有哪些地方須要類型轉換?以Delete /ajax/shop/12345/blacklist?id=1請求爲例,後端對應的處理方法以下。app

@DeleteMapping("/ajax/{shopId}/blacklist") @ResponseBody
public boolean deleteBlackItem(@RequestParam Integer id, @PathVariable Integer shopId) {
    //省略
    return true;
}

因爲請求的URL爲String類型,而接受的參數idshopId都是Integer類型,所以Spring會自動查找合適的Converter(具體實現爲StringToNumberConverterFactory的工廠產品)把字符串「12345」「1」轉化爲數字123451,分別賦值給shopIdid。處理完業務邏輯後,方法返回true,但須要將其格式化成String類型的「true」才能輸出到響應的Body中,這時Spring就會使用StringToBooleanConverter來完成轉換。以下圖所示,除了上述常見的數據綁定和格式化顯示功能,數據驗證功能(JSR-303)基於數據綁定也間接利用了這兩套SPI。spa

SpringMVC數據綁定、驗證與Convert SPI的關係

結語

在SpringMVC處理請求時,HttpMessageConverterConvert SPI分別用來反序列化請求的Body和非Body部分,即HttpMessageConverter是一套小型、獨立、額外爲用戶提供的專門的Body體的類型轉換器;而Convert SPI則與PropertyEditor相似,能夠處理更爲通用的類型轉換。3d

Reference

  1. SpringMVC數據類型轉換——第七章 註解式控制器的數據驗證、類型轉換及格式化——跟着開濤學SpringMVC

  1. 具體見HandlerMethodInvoker.readWithMessageConverters方法
  2. 具體見不一樣的HandlerMethodArgumentResolver實現
相關文章
相關標籤/搜索