【SpringMVC】淺談Convert/Format機(jī)制與HttpMessageConverter的關(guān)系

簡(jiǎn)介

Spring3引入了較Spring2的PropertyEditor更加強(qiáng)大、通用的Convert/Format SPI,Convert SPI可以實(shí)現(xiàn)任意類型的轉(zhuǎn)換;Format SPI支持國(guó)際化,并在前者的基礎(chǔ)上實(shí)現(xiàn)了String與任意類型的轉(zhuǎn)換。這兩類SPI屬于spring-core,被整個(gè)spring-framework共享,是一種通用的類型轉(zhuǎn)換器。

HttpMessageConverter雖然功能上也表現(xiàn)為HttpMessage與任意類型的轉(zhuǎn)換,但其接口和Convert SPI并沒有繼承關(guān)系。HttpMessageConverter屬于spring-web。HttpMessage是SpringMVC對(duì)Servlet規(guī)范中HttpServletRequestHttpServletResponse的包裝,因此接受請(qǐng)求時(shí)需要把HttpMessage轉(zhuǎn)換成用戶需要的數(shù)據(jù),在生成響應(yīng)時(shí)需要把用戶生成的數(shù)據(jù)轉(zhuǎn)換成HttpMessage。如果用戶在XML的<mvc:message-converters>中沒有指定register-defaults=false,SpringMVC默認(rèn)至少會(huì)注冊(cè)一些自帶的HttpMessageConvertor(從先后順序排列分別為ByteArrayHttpMessageConverterStringHttpMessageConverter、ResourceHttpMessageConverterSourceHttpMessageConverter、AllEncompassingFormHttpMessageConverter)。

如果后端服務(wù)使用Restful API的形式,一般使用JSON作為前后端通信的格式規(guī)范,由于SpringMVC自帶MappingJackson2HttpMessageConverter,在依賴中引入jackson后,容器會(huì)把該轉(zhuǎn)換器自動(dòng)注冊(cè)到converter鏈的末尾。

兩者的分工

Http請(qǐng)求中有幾個(gè)常用的部分可以用來(lái)傳遞業(yè)務(wù)信息,以常見的GetPost方法為例。

是否可用 URL Parameter Header Body
Get
Post

那么上述的4個(gè)部分都是用HttpMessageConverter來(lái)進(jìn)行類型轉(zhuǎn)換的嗎?顯然不是,HttpMessageConverterConvert SPI各有分工,** HttpMessageConverte只負(fù)責(zé)解析Http包的Body體部分1,其余部分都交由相關(guān)的Convert SPI處理2。**

是否支持 URL Parameter Header Body
HttpMessageConverter
Convert SPI

除上表所示之外,SpringMVC還有一些需要Convert SPI的場(chǎng)景,如讀取Cookie值的@CookieValue(本質(zhì)是Header),解析矩陣URL的@MatrixVariable(本質(zhì)是URL),讀取本地會(huì)話的@SessionAttribute,解析SpEL的@Value。

Convert SPI類型轉(zhuǎn)換實(shí)例

在SpringMVC中,單次請(qǐng)求的整個(gè)處理流程中有哪些地方需要類型轉(zhuǎn)換?以Delete /ajax/shop/12345/blacklist?id=1請(qǐng)求為例,后端對(duì)應(yīng)的處理方法如下。

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

由于請(qǐng)求的URL為String類型,而接受的參數(shù)idshopId都是Integer類型,因此Spring會(huì)自動(dòng)查找合適的Converter(具體實(shí)現(xiàn)為StringToNumberConverterFactory的工廠產(chǎn)品)把字符串“12345”“1”轉(zhuǎn)化為數(shù)字123451,分別賦值給shopIdid。處理完業(yè)務(wù)邏輯后,方法返回true,但需要將其格式化成String類型的“true”才能輸出到響應(yīng)的Body中,這時(shí)Spring就會(huì)使用StringToBooleanConverter來(lái)完成轉(zhuǎn)換。如下圖所示,除了上述常見的數(shù)據(jù)綁定和格式化顯示功能,數(shù)據(jù)驗(yàn)證功能(JSR-303)基于數(shù)據(jù)綁定也間接利用了這兩套SPI。

轉(zhuǎn)換器

結(jié)語(yǔ)

在SpringMVC處理請(qǐng)求時(shí),HttpMessageConverterConvert SPI分別用來(lái)反序列化請(qǐng)求的Body和非Body部分,即HttpMessageConverter是一套小型、獨(dú)立、額外為用戶提供的專門的Body體的類型轉(zhuǎn)換器;而Convert SPI則與PropertyEditor類似,可以處理更為通用的類型轉(zhuǎn)換。

參考: SpringMVC數(shù)據(jù)類型轉(zhuǎn)換——第七章 注解式控制器的數(shù)據(jù)驗(yàn)證、類型轉(zhuǎn)換及格式化——跟著開濤學(xué)SpringMVC

轉(zhuǎn)載自: https://segmentfault.com/a/1190000010378116

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容