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就会使用它。

猜你喜欢

转载自www.cnblogs.com/deityjian/p/10952038.html