spring学习笔记(七)HttpMessageConverter
spring学习笔记(七)HttpMessageConverter
1. HttpMessageConverter的加载
首先我们找到WebMvcAutoConfiguration这个类
在其中我们可以看到这么一段代码
@Configuration
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
@Order(0) //表示最先加载
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
private final ResourceProperties resourceProperties;
private final WebMvcProperties mvcProperties;
private final ListableBeanFactory beanFactory;
private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
private ResourceLoader resourceLoader; public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
this.resourceProperties = resourceProperties;
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
} public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
} public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.messageConvertersProvider.ifAvailable((customConverters) -> {
// 添加自定义的converter
converters.addAll(customConverters.getConverters());
});
}
// 省略一部分不重要的代码
.....
上面我们要分析的核心代码就是configureMessageConverters(List<HttpMessageConverter<?>> converters)这个方法,首先我要知道这个方法的入参是什么,在哪里初始化的。
我们可以看到在这个类上有一个@import注解
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})我们可以跟一下这个类----》EnableWebMvcConfiguration
我们可以发现这个类继承了WebMvcConfigurationSupport,核心的关于messageConverter的代码如下:
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(stringHttpMessageConverter);
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter()); try {
messageConverters.add(new SourceHttpMessageConverter());
} catch (Throwable var4) {
} messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
messageConverters.add(new AtomFeedHttpMessageConverter());
messageConverters.add(new RssChannelHttpMessageConverter());
} Jackson2ObjectMapperBuilder builder;
if (jackson2XmlPresent) {
builder = Jackson2ObjectMapperBuilder.xml();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
} messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
} else if (jaxb2Present) {
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
} if (jackson2Present) {
builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
} messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
} else if (gsonPresent) {
messageConverters.add(new GsonHttpMessageConverter());
} else if (jsonbPresent) {
messageConverters.add(new JsonbHttpMessageConverter());
} if (jackson2SmilePresent) {
builder = Jackson2ObjectMapperBuilder.smile();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
} messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
} if (jackson2CborPresent) {
builder = Jackson2ObjectMapperBuilder.cbor();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
} messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
} }
从这段代码中我们可以知道
- spring中默认添加了几个消息转换器,比如ByteArrayHttpMessageConverter,stringHttpMessageConverter,ResourceHttpMessageConverter等等
- 会根据Jackson,Gson等添加对应的小心转换器
2. 从StringMessageConverter探究消息转换器的原理
public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
// 默认字符集
public static final Charset DEFAULT_CHARSET;
@Nullable
private volatile List<Charset> availableCharsets;
private boolean writeAcceptCharset;
public StringHttpMessageConverter() {
this(DEFAULT_CHARSET);
}
public StringHttpMessageConverter(Charset defaultCharset) {
super(defaultCharset, new MediaType[]{MediaType.TEXT_PLAIN, MediaType.ALL});
this.writeAcceptCharset = true;
}
public void setWriteAcceptCharset(boolean writeAcceptCharset) {
this.writeAcceptCharset = writeAcceptCharset;
}
public boolean supports(Class<?> clazz) {
return String.class == clazz;
}
protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
return StreamUtils.copyToString(inputMessage.getBody(), charset);
}
protected Long getContentLength(String str, @Nullable MediaType contentType) {
Charset charset = this.getContentTypeCharset(contentType);
return (long)str.getBytes(charset).length;
}
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
if (this.writeAcceptCharset) {
outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
}
Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
StreamUtils.copy(str, charset, outputMessage.getBody());
}
protected List<Charset> getAcceptedCharsets() {
List<Charset> charsets = this.availableCharsets;
if (charsets == null) {
charsets = new ArrayList(Charset.availableCharsets().values());
this.availableCharsets = (List)charsets;
}
return (List)charsets;
}
private Charset getContentTypeCharset(@Nullable MediaType contentType) {
if (contentType != null && contentType.getCharset() != null) {
return contentType.getCharset();
} else if (contentType != null && contentType.isCompatibleWith(MediaType.APPLICATION_JSON)) {
return StandardCharsets.UTF_8;
} else {
Charset charset = this.getDefaultCharset();
Assert.state(charset != null, "No default charset");
return charset;
}
}
static {
// 默认字符集为ISO-8859-1
DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
}
}
上面代码的核心就在两个读写的方法上,分别是将字符串转换为httpMessage,跟将httpMessage转换为字符串
// 读方法
protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
Charset charset =
// 根据请求头中的信息,得到编码类型并转换
this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
return StreamUtils.copyToString(inputMessage.getBody(), charset);
}
// 写方法
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
if (this.writeAcceptCharset) {
outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
}
Charset charset =
// 根据响应头中的编码类型,将字符串转换为httpMessage消息
this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
StreamUtils.copy(str, charset, outputMessage.getBody());
}
spring学习笔记(七)HttpMessageConverter的更多相关文章
- Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入
模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...
- 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- 1.《Spring学习笔记-MVC》系列文章,讲解返回json数据的文章共有3篇,分别为:
转自:https://www.cnblogs.com/ssslinppp/p/4528892.html [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://w ...
- 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- (转)Qt Model/View 学习笔记 (七)——Delegate类
Qt Model/View 学习笔记 (七) Delegate 类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...
- Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)
在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...
- Typescript 学习笔记七:泛型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
随机推荐
- CVE-2019-0232 远程代码执行漏洞-复现
0x00 漏洞介绍 该漏洞是由于Tomcat CGI将命令行参数传递给Windows程序的方式存在错误,使得CGIServlet被命令注入影响. 该漏洞只影响Windows平台,要求启用了CGISer ...
- Fiddler实战之拟2G、3G、4G网络进行弱网测试
至于fidder网络代理设置就不多说了 模拟网速: 1.启动Fiddler,打开菜单栏Rules---Performances---Simulate Modem Speeds这里打开了模拟调节速度 2 ...
- Restlet Client发送GET、POST等请求
插件下载 百度云盘 链接:https://pan.baidu.com/s/13R4s1UR5TONl2JnwTgtIYw 密码:rt02 插件安装 解压后,直接拖进浏览器中. 功能演示
- Java成长记录第二集--基础重点
第一篇写的博客给自己的学习路线立了个flag后,感觉现在学习的积极性大增,这也离不开那几位老铁们的互相鼓励.废话不多说,现在给出自己总结的Java基础部分所要重点注意的内容,对以后的开发工作也是很常用 ...
- 【Tool】IDEA 连接数据库
窗口 View - DataBase 右侧的窗口弹出,点加号选择数据库 没有装载驱动包,提示下载 可以选择老版本的驱动,或者新版的 老版本驱动只需要填入数据库,账户和密码即可测试链接,显示连接成功 新 ...
- Docker+Cmd+Cli+Git之前端工程化纪要(二)自定义类package.json文件管理模块包
全新升级后的FE工作流为:使用FE命令包进行项目的初始化,其中包括项目初始化.拉取脚手架.私库拉取模块包或后期扩展的CI/CD等与本公司工作流相关的操作. 出现的问题如下: 脚手架工具的包依赖信息存放 ...
- 一些SpringBoot的初步理解
SpringBoot SpringBoot作为近几年很火的微服务框架,只需要简单的几个依赖,少量的配置,就可以使用它快速搭建一个轻量级的微服务,优点是简单.快速.大道至简,缺点是真的太单一,不适于项目 ...
- 泛微ecology OA系统在数据库配置信息泄露
漏洞描述 攻击者可通过该漏洞页面直接获取到数据库配置信息,攻击者可通过访问存在漏洞的页面并解密从而获取数据库配置信息,如攻击者可直接访问数据库,则可直接获取用户数据,由于泛微e-cology默认数据库 ...
- redis: 事务管理(九)
redis的事务 不保证原子性 三个步骤:开启事务.命令入队.执行事务 开启事务:multi 执行事务:exec 127.0.0.1:6379> multi #开启事务 OK 127.0.0.1 ...
- AIX详细的VG,LV扩容步骤
需求 1.归档日志刷得太快,经常把空间挤爆. 2.Oracle数据库表空间需要扩容 解决方案 1.先做重要数据备份 2.进行文件系统扩容 步骤 1. df -g 查找出/u01 对应的VG卷 VOLU ...