SpringBoot自定義HttpMessageConverter


Spring就是一個大大的插線板,上面插着各種各樣的Bean。
SpringBoot大大簡化了Spring的配置,將原來放在XML中的配置大量的在代碼中使用注解實現。這么做有利有弊,總體上利大於弊。

使用注解的方式在Spring中注冊Bean,有四種方式:

  • Component
  • Service
  • Controller,RestController
  • Repository

上面這四個注解真是SpringBoot的核心。因為要想使用

  • @Value屬性注入
  • @Resource,@Autowired自動注入

就必須讓Spring能夠看見使用這些注解的類,也就是說必須在Spring中注冊Bean,Spring才會統一幫你管理。

上面“Component”等注解都是用來注解類,注解接口要使用@Bean注解。當讓Spring注入接口時,如果接口有多個實例類,需要用@Resource("myUserDaoImpl")這種方式注明實例類的名稱;如果接口只有一個實例類,Spring會自動檢測合適的類型進行注入。

沒有Spring的時候,各個Bean形成的依賴關系是一個錯綜復雜的圖狀結構。有了Spring,各個Bean之間松耦合,各個Bean只跟Spring容器有聯系,這就形成了總線型的依賴,大大簡化了類與類之間的依賴關系。

下面進入正題,我編寫了一個Controller,返回User類型的數據,Spring會把User轉化成JSON字符串,現在我想對這個字符串進行一些處理再返回。要求不能更改Controller部分的代碼,因為我要對全部的返回的JSON都進行這種處理,如果改Controller的話需要更改好多地方。

@RestController
class MyController {
@RequestMapping("user")
User getUser() {
   return new User("weidiao", 25);
}
}

雖然這個函數返回的User類型,實際上Spring會把這個對象轉換成JSON。跟@ResponseBody@RequestBody兩個注解密切相關的一個接口是:HttpMessageConverter。

消息轉換器的目標是:HTTP輸入請求格式向Java對象的轉換;Java對象向HTTP輸出請求的轉換。有的消息轉換器只支持多個數據類型,有的只支持多個輸出格式,還有的兩者兼備。

HttpMessageConverter 接口提供了5個方法:

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

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

Spring已經默認包含了常用的消息轉換器:

名稱 作用 讀支持MediaType 寫支持MediaType
ByteArrayHttpMessageConverter 數據與字節數組的相互轉換 / application/octet-stream
StringHttpMessageConverter 數據與String類型的相互轉換 text/* text/plain
FormHttpMessageConverter 表單與MultiValueMap<string, string=””>的相互轉換 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支持的所有類型

請看實現

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

@Component
public class MyHttpMessageConverter implements HttpMessageConverter<Object> {
@Override
public boolean canRead(Class<?> aClass, MediaType mediaType) {
   return false;
}

@Override
public boolean canWrite(Class<?> aClass, MediaType mediaType) {
   return true;
}

@Override
public List<MediaType> getSupportedMediaTypes() {
   return Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8);
}

@Override
public Object read(Class<?> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
   return null;
}

@Override
public void write(Object o, MediaType mediaType, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
   PrintWriter cout = new PrintWriter(httpOutputMessage.getBody());
   JSONObject ans = new JSONObject();
   ans.put("object", o);
   ans.put("successful", o != null);
   cout.write(JSON.toJSONString(ans, true));
   cout.close();
}
}

使用@Component注解這個類就能夠讓Spring知道:這里有一個消息轉換器。這樣Spring就會使用它。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM