[轉]使用自訂HttpMessageConverter對返回內容進行加密

來源:互聯網
上載者:User

標籤:api   stream   val   figure   oct   convert   介面   註解   一個   

今天上午技術群裡的一個人問” 如何在 Spring MVC 中統一對返回的 Json 進行加密?”。

大部分人的第一反應是通過 Spring 攔截器(Interceptor)中的postHandler方法處理。實際這是行不通的,因為當程式運行到該方法,是在返回資料之後,渲染頁面之前,所以這時候 Response 中的輸出資料流已經關閉了,自然無法在對返回資料進行處理。

其實這個問題用幾行代碼就可以搞定,因為 Spring 提供了非常豐富的擴充支援,無論是之前提到的InterceptorMethodArgumentResolver,還是接下來要提到的HttpMessageConverter

在 Spring MVC 的 Controller 層經常會用到@RequestBody@ResponseBody,通過這兩個註解,可以在 Controller 中直接使用 Java 對象作為請求參數和返回內容,而完成這之間轉換作用的便是HttpMessageConverter

HttpMessageConverter介面提供了 5 個方法:

  • canRead:判斷該轉換器是否能將請求內容轉換成 Java 對象
  • canWrite:判斷該轉換器是否可以將 Java 對象轉換成返回內容
  • getSupportedMediaTypes:獲得該轉換器支援的 MediaType 類型
  • read:讀取請求內容並轉換成 Java 對象
  • write:將 Java 對象轉換後寫入返回內容

    其中readwrite方法的參數分別有有HttpInputMessageHttpOutputMessage對象,這兩個對象分別代表著一次 Http 通訊中的請求和響應部分,可以通過getBody方法獲得對應的輸入資料流和輸出資料流。

    這裡通過實現該介面自訂一個 Json 轉換器作為樣本:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 class CustomJsonHttpMessageConverter implements HttpMessageConverter { //Jackson 的 Json 映射類private ObjectMapper mapper = new ObjectMapper (); // 該轉換器的支援類型:application/jsonprivate List supportedMediaTypes = Arrays.asList (MediaType.APPLICATION_JSON); /*** 判斷轉換器是否可以將輸入內容轉換成 Java 類型* @param clazz 需要轉換的 Java 類型* @param mediaType 該請求的 MediaType* @return*/@Overridepublic boolean canRead (Class clazz, MediaType mediaType) {if (mediaType == null) {return true;}for (MediaType supportedMediaType : getSupportedMediaTypes ()) {if (supportedMediaType.includes (mediaType)) {return true;}}return false;} /*** 判斷轉換器是否可以將 Java 類型轉換成指定輸出內容* @param clazz 需要轉換的 Java 類型* @param mediaType 該請求的 MediaType* @return*/@Overridepublic boolean canWrite (Class clazz, MediaType mediaType) {if (mediaType == null || MediaType.ALL.equals (mediaType)) {return true;}for (MediaType supportedMediaType : getSupportedMediaTypes ()) {if (supportedMediaType.includes (mediaType)) {return true;}}return false;} /*** 獲得該轉換器支援的 MediaType* @return*/@Overridepublic List getSupportedMediaTypes () {return supportedMediaTypes;} /*** 讀取請求內容,將其中的 Json 轉換成 Java 對象* @param clazz 需要轉換的 Java 類型* @param inputMessage 請求對象* @return* @throws IOException* @throws HttpMessageNotReadableException*/@Overridepublic Object read (Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {return mapper.readValue (inputMessage.getBody (), clazz);} /*** 將 Java 對象轉換成 Json 返回內容* @param o 需要轉換的對象* @param contentType 傳回型別* @param outputMessage 回執對象* @throws IOException* @throws HttpMessageNotWritableException*/@Overridepublic void write (Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {mapper.writeValue (outputMessage.getBody (), o);}}

當前 Spring 中已經預設提供了相當多的轉換器,分別有:

名稱 作用 讀支援 MediaType 寫支援 MediaType
ByteArrayHttpMessageConverter 資料與位元組數組的相互轉換 \/\ application/octet-stream
StringHttpMessageConverter 資料與 String 類型的相互轉換 text/\* text/plain
FormHttpMessageConverter 表單與 MultiValueMap的相互轉換 application/x-www-form-urlencoded application/x-www-form-urlencoded
SourceHttpMessageConverter 資料與 javax.xml.transform.Source 的相互轉換 text/xml 和 application/xml text/xml 和 application/xml
MarshallingHttpMessageConverter 使用 Spring 的 Marshaller/Unmarshaller 轉換 XML 資料 text/xml 和 application/xml text/xml 和 application/xml
MappingJackson2HttpMessageConverter 使用 Jackson 的 ObjectMapper 轉換 Json 資料 application/json application/json
MappingJackson2XmlHttpMessageConverter 使用 Jackson 的 XmlMapper 轉換 XML 資料 application/xml application/xml
BufferedImageHttpMessageConverter 資料與 java.awt.image.BufferedImage 的相互轉換 Java I/O API 支援的所有類型 Java I/O API 支援的所有類型

回到最開始所提的需求,既然要對返回的 Json 內容進行加密,肯定是對MappingJackson2HttpMessageConverter進行改造,並且只需要重寫write方法。

MappingJackson2HttpMessageConverter的父類AbstractHttpMessageConverter中的write方法可以看出,該方法通過writeInternal方法向返回結果的輸出資料流中寫入資料,所以只需要重寫該方法即可:

1234567891011121314151617181920 @Beanpublic MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter () {return new MappingJackson2HttpMessageConverter () {// 重寫 writeInternal 方法,在返回內容前首先進行加密@Overrideprotected void writeInternal (Object object,HttpOutputMessage outputMessage) throws IOException,HttpMessageNotWritableException {// 使用 Jackson 的 ObjectMapper 將 Java 對象轉換成 Json StringObjectMapper mapper = new ObjectMapper ();String json = mapper.writeValueAsString (object);LOGGER.error (json);// 加密String result = json + "加密了!";LOGGER.error (result);// 輸出outputMessage.getBody ().write (result.getBytes ());}};}

在這之後還需要將這個自訂的轉換器配置到 Spring 中,這裡通過重寫WebMvcConfigurer中的configureMessageConverters方法添加自訂轉換器:

123456 // 添加自訂轉換器@Overridepublic void configureMessageConverters (List> converters) {converters.add (mappingJackson2HttpMessageConverter ());super.configureMessageConverters (converters);}

測試一下:

如此便簡單的完成了對返回內容進行加密的功能。

 

(原文地址:http://www.scienjus.com/custom-http-message-converter/)

[轉]使用自訂HttpMessageConverter對返回內容進行加密

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.