赞
踩
MappingJackson2HttpMessageConverter
没有默认编码的问题在Spring Boot 3.3.1 自定配置创建的MappingJackson2HttpMessageConverter
默认是没有指定字符串编码,因此在实际的使用中会自动使用ISO8859-1
的编码。
StringHttpMessageConverter
默认编码为ISO8859-1
,这个也需要修改。
com.fasterxml.jackson.databind.Module
bean 不生效的问题由于Spring 自动配置的MappingJackson2HttpMessageConverter
创建时并不会使用配置的com.fasterxml.jackson.databind.Module
,因此会导致原型2.0版本通过该方式配置的JSON自定义序列化和反序列化无效。
增加一个配置类实现WebMvcConfigurer
接口,并实现configureMessageConverters
或者extendMessageConverters
方法。这个两个方法都会将当前的系统中的所有MessageConverters
传入。区别在于extendMessageConverters
是做后置加工的,也就是到执行它的时候,系统内的MessageConverters
已经是被前置处理过的(前置操作包括合并、排序等),而configureMessageConverters
是没有被前置处理,甚至是部分的MessageConverters
。
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.nio.charset.StandardCharsets; import java.util.List; /** * 自定义的Mvc配置,用于配置转换器 */ @Configuration public class CustomWebMvcConverterConfigurer implements WebMvcConfigurer { @Autowired private com.fasterxml.jackson.databind.Module customJackSonModule; /** * 扩展消息转换器列表,以支持自定义的字符集和Jackson模块。 * 此方法遍历给定的消息转换器列表,并对特定类型的转换器应用自定义配置。 * 具体来说,它将字符串转换器的默认字符集设置为UTF-8,并为Jackson转换器注册一个自定义的Jackson模块。 * * @param converters 消息转换器的列表,这里我们将遍历这个列表并对特定的转换器进行配置。 */ @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // 遍历给定的消息转换器列表 for(HttpMessageConverter<?> converter : converters) { // 如果当前转换器是字符串转换器,则将其默认字符集设置为UTF-8 if(converter instanceof StringHttpMessageConverter stringHttpMessageConverter) { stringHttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8); continue; } // 如果当前转换器是Jackson 2转换器,则将其默认字符集设置为UTF-8,并注册自定义的Jackson模块 if(converter instanceof MappingJackson2HttpMessageConverter jackson2HttpMessageConverter) { jackson2HttpMessageConverter.setDefaultCharset(StandardCharsets.UTF_8); ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper(); // 注册自定义的Jackson模块,以支持额外的序列化和反序列化需求 objectMapper.registerModule(customJackSonModule); } } } }
直接在创建一个MappingJackson2HttpMessageConverter
Bean。
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import java.nio.charset.StandardCharsets; @Configuration public class JacksonConfiguration { @Autowired private com.fasterxml.jackson.databind.Module customJackSonModule; @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); // 注册自定义Module objectMapper.registerModule(customJackSonModule); converter.setObjectMapper(objectMapper); //默认字符集设置为UTF-8 converter.setDefaultCharset(StandardCharsets.UTF_8); return converter; } } } }
自定义Jackson2ObjectMapperBuilderCustomizer
,用于配置Jackson2ObjectMapperBuilder
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; /** * 配置Jackson2ObjectMapperBuilderCustomizer */ @Configuration public class JacksonConfiguration { @Autowired private com.fasterxml.jackson.databind.Module customJackSonModule; @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperBuilderCustomizer() { return new Jackson2ObjectMapperBuilderCustomizer() { @Override public void customize(Jackson2ObjectMapperBuilder builder) { // 注册自定义的 Module builder.modulesToInstall(customJackSonModule); } }; } }
该方案不可行的原因是Spring Boot自动配置的MappingJackson2HttpMessageConverter
使用的ObjectMapper
就没使用Jackson2ObjectMapperBuilder
的Bean去创建的,而是每次都重新创建一个Jackson2ObjectMapperBuilder
的创建的。 这个应该是给未来版本来解决的,详情可以看org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
这个类。
MappingJackson2HttpMessageConverter
转换器构造流程几个构造流程:
1、org.springframework.boot.autoconfigure.BackgroundPreinitializer
的org.springframework.boot.autoconfigure.BackgroundPreinitializer.MessageConverterInitializer
初始化AllEncompassingFormHttpMessageConverter
消息转换器。在这个消息转换器中默认会初始化一堆消息转换器,其中就包含MappingJackson2HttpMessageConverter
的无参构造方法。
2、org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration#formContentFilter
方法中创建了一个OrderedFormContentFilter
的Filter,这个Filter中默认会创建一个AllEncompassingFormHttpMessageConverter
消息转换器。在这个消息转换器中默认会初始化一堆消息转换器,其中就包含MappingJackson2HttpMessageConverter
的无参构造方法。
AllEncompassingFormHttpMessageConverter
只处理Form 表单请求(请求头为application/x-www-form-urlencoded
)的转换。
3、org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration#mappingJackson2HttpMessageConverter
,使用指定的ObjectMapper
创建了一个MappingJackson2HttpMessageConverter
4、org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerAdapter
-> org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getMessageConverters
->
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addDefaultHttpMessageConverters
使用默认的Jackson2ObjectMapperBuilder
的配置创建一个MappingJackson2HttpMessageConverter
5、org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration#messageConverters
默认的Jackson2ObjectMapperBuilderCustomizer
的实现
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.Jackson2ObjectMapperBuilderCustomizerConfiguration.StandardJackson2ObjectMapperBuilderCustomizer
HttpMessageConverter
的write
方法调用点
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters(T, org.springframework.core.MethodParameter, org.springframework.http.server.ServletServerHttpRequest, org.springframework.http.server.ServletServerHttpResponse)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。