在我们日常的web开发过程中肯定都用过@RequestBody、@ResponseBody注解,其作用就是将输入输出参数解析成Json,但是Http请求和响应都是基于报文的,意味着浏览器与服务器之间的交互时通过原始文本进行数据同i性能的,这里其实就是HttpMessageConverter在起作用。
首先来看下HttpMessageConvertersAutoConfiguration配置类的源码
HttpMessageConvertersAutoConfiguration源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| @Configuration(proxyBeanMethods = false) @ConditionalOnClass(HttpMessageConverter.class) @Conditional(NotReactiveWebApplicationCondition.class) @AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class }) @Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class, JsonbHttpMessageConvertersConfiguration.class }) public class HttpMessageConvertersAutoConfiguration {
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
@Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); }
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(StringHttpMessageConverter.class) @EnableConfigurationProperties(HttpProperties.class) protected static class StringHttpMessageConverterConfiguration {
@Bean @ConditionalOnMissingBean public StringHttpMessageConverter stringHttpMessageConverter(HttpProperties httpProperties) { StringHttpMessageConverter converter = new StringHttpMessageConverter( httpProperties.getEncoding().getCharset()); converter.setWriteAcceptCharset(false); return converter; }
}
static class NotReactiveWebApplicationCondition extends NoneNestedConditions {
NotReactiveWebApplicationCondition() { super(ConfigurationPhase.PARSE_CONFIGURATION); }
@ConditionalOnWebApplication(type = Type.REACTIVE) private static class ReactiveWebApplication {
}
}
}
|
从源码中我们可以看到此配置类给Ioc容器中添加了messageConverters和stringHttpMessageConverter这两个bean
HttpMessageConvertersAutoConfiguration
首先先看这一段代码
1 2 3 4 5 6
| @Bean @ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) { return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList())); }
|
执行完毕后会查询到这些converter

其中我们可以看到StringHttpMessageConverter,这是为了处理不同编码。

StringHttpMessageConverter源码
我们可以看到如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Override protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException { HttpHeaders headers = outputMessage.getHeaders(); if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) { headers.setAcceptCharset(getAcceptedCharsets()); } Charset charset = getContentTypeCharset(headers.getContentType()); StreamUtils.copy(str, charset, outputMessage.getBody()); }
public static void copy(String in, Charset charset, OutputStream out) throws IOException { Assert.notNull(in, "No input String specified"); Assert.notNull(charset, "No charset specified"); Assert.notNull(out, "No OutputStream specified");
Writer writer = new OutputStreamWriter(out, charset); writer.write(in); writer.flush(); }
|
当我们请求一个地址的时候,方法上加了@ResponseBody或者使用的是@RestControlelr,并且返回值是一个字符串,此converter就会生效


之后就用到StreamUtils的copy方法了,将我们返回的数据写入输出流,返回给浏览器。