http的序列化和反序列化是什么鬼吩愧?之前只聽說過對(duì)象的序列化和反序列化啊顾彰。奔著自己很菜的想法去百度了下极阅。下面看一個(gè)簡(jiǎn)單的springmvc的請(qǐng)求:
@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的內(nèi)容轉(zhuǎn)化為Person?對(duì)象筋搏。其實(shí),這就是http序列化和反序列化厕隧。
? ?Http協(xié)議的處理過程拆又,TCP字節(jié)流 <---> HttpRequest/HttpResponse <---> 內(nèi)部對(duì)象儒旬,就涉及這兩種序列化。在springmvc中第一步已經(jīng)由Servlet容器(tomcat等等)幫我們處理了帖族,第二步則主要由框架幫我們處理栈源。http序列化就是第二步的操作。
哈哈竖般,原來我們一直都在跟http序列化打交道啊甚垦,http序列化和反序列化就是請(qǐng)求參數(shù)封裝為對(duì)象和解析對(duì)象的過程啊。之前的項(xiàng)目都是以json的形式實(shí)現(xiàn)序列化和反序列化的涣雕。
將請(qǐng)求的json格式數(shù)據(jù)封裝成了person對(duì)象艰亮,之后返回person對(duì)象,瀏覽器得到了json數(shù)據(jù)挣郭。這個(gè)過程是怎樣完成的呢迄埃?其實(shí)核心是HttpMessageConverter接口;springboot的自動(dòng)化裝配功能將會(huì)初始化WebMvcConfigurationSupport類兑障。這個(gè)類就是初始化HttpMessageConverter的侄非。WebMvcConfigurationSupport的靜態(tài)代碼塊中判斷處理類的jar有沒有引入,比如
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
是json的實(shí)現(xiàn)流译,springboot默認(rèn)引入了這個(gè)包逞怨,所以可以處理json的序列化。如果想添加xml的支持福澡,只需引入xml相關(guān)的jar即可叠赦。
WebMvcConfigurationSupport類的addDefaultHttpMessageConverters方法默認(rèn)添加了一些處理類,
有興趣的可以看下革砸。當(dāng)放入了這些HttpMessageConverter實(shí)現(xiàn)類后除秀,就會(huì)處理請(qǐng)求參數(shù)了,那么問題來了算利,放了這么多的實(shí)現(xiàn)類究竟誰來處理呢鳞仙?他根據(jù)一定的規(guī)則(主要是Content-Type、Accept笔时、controller方法的consumes/produces、Converter.mediaType以及Converter的排列順序這四個(gè)屬性)來選擇到底是使用哪一個(gè)
在http的請(qǐng)求頭中有兩個(gè)參數(shù):Accept:表示瀏覽器可以接收什么樣格式的數(shù)據(jù)application/json等
Content-Type:表示請(qǐng)求的數(shù)據(jù)格式是什么樣的application/json等
controller方法的consumes對(duì)應(yīng)的是匹配 請(qǐng)求Content-Type的格式
produces則對(duì)應(yīng)Accept格式
下面實(shí)現(xiàn)一個(gè)處理自定義類型的HttpMessageConverter
1:創(chuàng)建一個(gè)實(shí)現(xiàn)HttpMessageConverter的類
public class MyMessageConverterextends AbstractHttpMessageConverter {
public MyMessageConverter() {
//設(shè)置支持的類型 這里支持的類型是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 {
//將請(qǐng)求參數(shù)封裝成person對(duì)象 就是請(qǐng)求參數(shù)是properties類型的封裝成person對(duì)象
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對(duì)象封裝成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());
}
}
很簡(jiǎn)單實(shí)現(xiàn)WebMvcConfigurationSupport 類的extendMessageConverters方法就可以了仗岸。
這樣就可以接收properties參數(shù)的請(qǐng)求了允耿。
postman發(fā)送請(qǐng)求
還有個(gè)問題springboot是怎樣自動(dòng)裝配這個(gè)配置的呢?
@SpringBootApplication注解有個(gè)@EnableAutoConfiguration自動(dòng)裝配扒怖,進(jìn)而引入了AutoConfigurationImportSelector.類较锡,此類的作用就是將所有符合條件的@Configuration配置都加載到當(dāng)前SpringBoot創(chuàng)建并使用的IoC容器。在AutoConfigurationImportSelector類中可以看到通過 SpringFactoriesLoader.loadFactoryNames()把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一個(gè)xxxAutoConfiguration文件都加載到容器中其中就包括WebMvcAutoConfiguration引入EnableWebMvcConfiguration.class 進(jìn)而初始化DelegatingWebMvcConfiguration此類就是WebMvcConfigurationSupport的實(shí)現(xiàn)類盗痒。