美文网首页
springboot学习之HttpMessageConverte

springboot学习之HttpMessageConverte

作者: 刘杰生 | 来源:发表于2019-05-03 16:55 被阅读0次

http的序列化和反序列化是什么鬼?之前只听说过对象的序列化和反序列化啊。奔着自己很菜的想法去百度了下。下面看一个简单的springmvc的请求:

@RestController

public class PersonController {

@GetMapping("getPerson")

public Person getPerson(@RequestBody Person person) {

System.err.println("create an person: " + person);

return person;

}

}

  @RestController中有@ResponseBody,可以帮我们把Person 序列化到resp.body中。@RequestBody可以帮我们把req.body的内容转化为Person 对象。其实,这就是http序列化和反序列化。

   Http协议的处理过程,TCP字节流 <---> HttpRequest/HttpResponse <---> 内部对象,就涉及这两种序列化。在springmvc中第一步已经由Servlet容器(tomcat等等)帮我们处理了,第二步则主要由框架帮我们处理。http序列化就是第二步的操作。

哈哈,原来我们一直都在跟http序列化打交道啊,http序列化和反序列化就是请求参数封装为对象和解析对象的过程啊。之前的项目都是以json的形式实现序列化和反序列化的。

将请求的json格式数据封装成了person对象,之后返回person对象,浏览器得到了json数据。这个过程是怎样完成的呢?其实核心是HttpMessageConverter接口;springboot的自动化装配功能将会初始化WebMvcConfigurationSupport类。这个类就是初始化HttpMessageConverter的。WebMvcConfigurationSupport的静态代码块中判断处理类的jar有没有引入,比如

jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&

ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);

是json的实现,springboot默认引入了这个包,所以可以处理json的序列化。如果想添加xml的支持,只需引入xml相关的jar即可。

WebMvcConfigurationSupport类的addDefaultHttpMessageConverters方法默认添加了一些处理类,

有兴趣的可以看下。当放入了这些HttpMessageConverter实现类后,就会处理请求参数了,那么问题来了,放了这么多的实现类究竟谁来处理呢?他根据一定的规则(主要是Content-Type、Accept、controller方法的consumes/produces、Converter.mediaType以及Converter的排列顺序这四个属性)来选择到底是使用哪一个

在http的请求头中有两个参数:Accept:表示浏览器可以接收什么样格式的数据application/json等

Content-Type:表示请求的数据格式是什么样的application/json等

controller方法的consumes对应的是匹配 请求Content-Type的格式

produces则对应Accept格式

下面实现一个处理自定义类型的HttpMessageConverter

1:创建一个实现HttpMessageConverter的类

public class MyMessageConverterextends AbstractHttpMessageConverter {

public MyMessageConverter() {

//设置支持的类型 这里支持的类型是application/x-properties;charset=UTF-8

super(new MediaType("application","x-properties", Charset.forName("UTF-8")));

}

@Override

    protected Person readInternal(Class clazz, HttpInputMessage inputMessage)throws IOException, HttpMessageNotReadableException {

//将请求参数封装成person对象 就是请求参数是properties类型的封装成person对象

InputStream inputStream = inputMessage.getBody();

Properties properties =new Properties();

properties.load(new InputStreamReader(inputStream));

String name = properties.getProperty("name");

String phone = properties.getProperty("phone");

Person person =new Person();

person.setName(name);

person.setPhone(phone);

return person;

}

@Override

    protected void writeInternal(Person person, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException {

//此方法就是将person对象封装成properties返回给浏览器

Properties properties =new Properties();

properties.setProperty("name", person.getName());

properties.setProperty("phone", person.getPhone());

OutputStream body = outputMessage.getBody();

properties.store(body,"UTF-8");

}

@Override

    protected boolean supports(Class clazz) {

return ClassUtils.isAssignable(Person.class,clazz);

}

}

2 将此处理类添加到配置类中

@Configuration

public class MyWebMvcConfigurationSextends WebMvcConfigurationSupport {

@Override

    protected void extendMessageConverters(List> converters) {

super.extendMessageConverters(converters);

converters.add(new MyMessageConverter());

}

}

很简单实现WebMvcConfigurationSupport 类的extendMessageConverters方法就可以了。

这样就可以接收properties参数的请求了。

postman发送请求

还有个问题springboot是怎样自动装配这个配置的呢?

@SpringBootApplication注解有个@EnableAutoConfiguration自动装配,进而引入了AutoConfigurationImportSelector.类,此类的作用就是将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中其中就包括WebMvcAutoConfiguration引入EnableWebMvcConfiguration.class 进而初始化DelegatingWebMvcConfiguration此类就是WebMvcConfigurationSupport的实现类。


相关文章

网友评论

      本文标题:springboot学习之HttpMessageConverte

      本文链接:https://www.haomeiwen.com/subject/hnfznqtx.html