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。

695653-20170516135626791-1426896158.png

消息转换器的目标是: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-urlencodedapplication/x-www-form-urlencoded
SourceHttpMessageConverter数据与javax.xml.transform.Source的相互转换text/xml和application/xmltext/xml和application/xml
MarshallingHttpMessageConverter使用Spring的Marshaller/Unmarshaller转换XML数据text/xml和application/xmltext/xml和application/xml
MappingJackson2HttpMessageConverter使用Jackson的ObjectMapper转换Json数据application/jsonapplication/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就会使用它。

转载于:https://www.cnblogs.com/weiyinfu/p/6861074.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值