SpringMVC HttpMessageConverter消息轉(zhuǎn)換器
Spring MVC 為開發(fā)者提供了方便的開發(fā)方式和豐富的功能。其中,HttpMessageConverter 是Spring MVC中非常重要的一個(gè)組件,它負(fù)責(zé)將客戶端提交的請求數(shù)據(jù)(如JSON、XML等)轉(zhuǎn)換為Java對象,同時(shí)也負(fù)責(zé)將 Java 對象轉(zhuǎn)換為客戶端需要的數(shù)據(jù)格式。本文將 從HttpMessageConverter 的作用和源碼實(shí)現(xiàn)兩個(gè)方面進(jìn)行講解。
作用
在 Spring MVC 中,客戶端通過發(fā)送請求,向服務(wù)器端請求數(shù)據(jù),服務(wù)器端接收到請求后需要將請求參數(shù)轉(zhuǎn)換為 Java 對象進(jìn)行處理,這就需要使用 HttpMessageConverter,它主要負(fù)責(zé)將HTTP請求中的請求參數(shù)轉(zhuǎn)換為 Java 對象或?qū)?Java 對象轉(zhuǎn)換為 HTTP 響應(yīng)中的內(nèi)容。
HttpMessageConverter 是一個(gè)接口,Spring MVC 中有很多實(shí)現(xiàn)類,用于處理不同的數(shù)據(jù)類型。常見的 HttpMessageConverter 實(shí)現(xiàn)類有:
- ByteArrayHttpMessageConverter:用于處理字節(jié)數(shù)組類型的數(shù)據(jù)。
- StringHttpMessageConverter:用于處理字符串類型的數(shù)據(jù)。
- FormHttpMessageConverter:用于處理表單類型的數(shù)據(jù)。
- MappingJackson2HttpMessageConverter:用于處理JSON類型的數(shù)據(jù)。
- Jaxb2RootElementHttpMessageConverter:用于處理XML類型的數(shù)據(jù)。
HttpMessageConverter 接口定義了兩個(gè)方法:canRead() 和 canWrite(),分別用于判斷當(dāng)前的 HttpMessageConverter 是否可以讀取或?qū)懭胫付ǖ臄?shù)據(jù)類型。
- 如果 canRead() 方法返回 true,那么當(dāng)前的 HttpMessageConverter 就可以將 HTTP 請求中的請求參數(shù)轉(zhuǎn)換為 Java 對象;
- 如果 canWrite() 方法返回 true,那么當(dāng)前的 HttpMessageConverter 就可以將Java對象轉(zhuǎn)換為 HTTP 響應(yīng)中的內(nèi)容。
源碼實(shí)現(xiàn)
下面以 MappingJackson2HttpMessageConverter 為例,講解 HttpMessageConverter 的源碼實(shí)現(xiàn)。
MappingJackson2HttpMessageConverter 是一個(gè)用于處理 JSON 類型數(shù)據(jù)的 HttpMessageConverter 實(shí)現(xiàn)類。它繼承了 AbstractJackson2HttpMessageConverter 類,并實(shí)現(xiàn)了 HttpMessageConverter 接口。
canRead()
@Override public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) { JavaType javaType = getJavaType(clazz, null); return (this.objectMapper.canDeserialize(javaType) && canRead(mediaType)); }
方法首先調(diào)用了 getJavaType() 方法獲取 JavaType 對象
然后判斷當(dāng)前的 ObjectMapper 是否可以反序列化 JavaType 對象。
如果當(dāng)前的 HttpMessageConverter 可以反序列化 JavaType 對象并且當(dāng)前的 MediaType 可以被處理,那么就返回 true,否則返回 false。
canWrite()
@Override public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) { return (this.objectMapper.canSerialize(clazz) && canWrite(mediaType)); }
方法首先判斷當(dāng)前的 ObjectMapper 是否可以序列化指定的 Java 對象
如果可以序列化并且當(dāng)前的 MediaType 可以被處理,那么就返回 true,否則返回 false。
read()
@Override public T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)throws IOException, HttpMessageNotReadableException { JavaType javaType = getJavaType(clazz, null); try { return this.objectMapper.readValue(inputMessage.getBody(), javaType); } catch (JsonProcessingException ex) { throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex, inputMessage); } }
方法首先調(diào)用 getJavaType() 方法獲取 JavaType 對象
然后通過 ObjectMapper 的 readValue() 方法將HTTP請求中的請求參數(shù)轉(zhuǎn)換為 Java 對象。
如果在轉(zhuǎn)換的過程中出現(xiàn)了異常,那么就拋出 HttpMessageNotReadableException 異常。
write()
@Override protected void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { try { JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType()); JsonGenerator jsonGenerator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding); writePrefix(jsonGenerator, t); this.objectMapper.writeValue(jsonGenerator, t); writeSuffix(jsonGenerator, t); jsonGenerator.flush(); } catch (JsonProcessingException ex) { throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex); } }
方法首先通過 getJsonEncoding() 方法獲取JSON編碼格式
然后通過 ObjectMapper 的 writeValue() 方法將 Java 對象轉(zhuǎn)換為 JSON 格式的字符串
并將結(jié)果輸出到 HTTP 響應(yīng)中。如果在轉(zhuǎn)換的過程中出現(xiàn)了異常,那么就拋出 HttpMessageNotWritableException 異常。
異同
大家是不是覺得與前面文章所講的 MethodArgumentResolver 很相似,都能夠?qū)⒄埱髤?shù)轉(zhuǎn)換為Java對象,但它們的作用和處理流程不同:
- HttpMessageConverter 會(huì)在請求到達(dá) Controller 方法之前進(jìn)行處理,這意味著它只處理請求參數(shù),而不管 Controller 方法的簽名和參數(shù)類型;
- MethodArgumentResolver 會(huì)在 Controller 方法執(zhí)行之前進(jìn)行處理,它的作用是將請求參數(shù)按照 Controller 方法的參數(shù)順序進(jìn)行解析,并將解析結(jié)果映射到 Controller 方法的參數(shù)上,然后再調(diào)用 Controller 方法
總結(jié)
HttpMessageConverter 是Spring MVC 中非常重要的一個(gè)組件,它主要負(fù)責(zé)將 HTTP 請求中的請求參數(shù)轉(zhuǎn)換為 Java 對象或?qū)?Java 對象轉(zhuǎn)換為 HTTP 響應(yīng)中的內(nèi)容。Spring MVC 中提供了很多HttpMessageConverter 實(shí)現(xiàn)類,可以處理不同的數(shù)據(jù)類型。
HttpMessageConverter 接口定義了兩個(gè)方法:canRead() 和 canWrite(),分別用于判斷當(dāng)前的 HttpMessageConverter 是否可以讀取或?qū)懭胫付ǖ臄?shù)據(jù)類型。HttpMessageConverter 的源碼實(shí)現(xiàn)中,read() 方法用于將 HTTP 請求中的請求參數(shù)轉(zhuǎn)換為 Java 對象,write() 方法用于將 Java 對象轉(zhuǎn)換為 HTTP 響應(yīng)中的內(nèi)容。在具體實(shí)現(xiàn)中,開發(fā)者可以根據(jù)自己的需求自定義 HttpMessageConverter 實(shí)現(xiàn)類。
到此這篇關(guān)于SpringMVC HttpMessageConverter消息轉(zhuǎn)換器的文章就介紹到這了,更多相關(guān)SpringMVC HttpMessageConverter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java通過Socket實(shí)現(xiàn)簡單多人聊天室
這篇文章主要為大家詳細(xì)介紹了Java通過Socket實(shí)現(xiàn)簡單多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04詳解spring batch的使用和定時(shí)器Quart的使用
spring Batch是一個(gè)基于Spring的企業(yè)級批處理框架,它通過配合定時(shí)器Quartz來輕易實(shí)現(xiàn)大批量的數(shù)據(jù)讀取或插入,并且全程自動(dòng)化,無需人員管理2017-08-08一次Spring無法啟動(dòng)的問題排查實(shí)戰(zhàn)之字節(jié)碼篇
最近學(xué)習(xí)了spring相關(guān)知識,公司項(xiàng)目也用到了spring,下面這篇文章主要給大家介紹了一次Spring無法啟動(dòng)的問題排查實(shí)戰(zhàn)之字節(jié)碼篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04SpringBoot詳解如何實(shí)現(xiàn)讀寫分離
當(dāng)響應(yīng)的瓶頸在數(shù)據(jù)庫的時(shí)候,就要考慮數(shù)據(jù)庫的讀寫分離,當(dāng)然還可以分庫分表,那是單表數(shù)據(jù)量特別大,當(dāng)單表數(shù)據(jù)量不是特別大,但是請求量比較大的時(shí)候,就要考慮讀寫分離了.具體的話,還是要看自己的業(yè)務(wù)...如果還是很慢,那就要分庫分表了...我們這篇就簡單講一下讀寫分離2022-05-05