HttpMessageConverter

相信使用过Spring的开发人员都用过@RequestBody、@ResponseBody注解,可以直接将输入解析成Json、将输出解析成Json,但HTTP 请求和响应是基于文本的,意味着浏览器和服务器通过交换原始文本进行通信,而这里其实就是HttpMessageConverter发挥着作用。
HttpMessageConverter
Http请求响应报文其实都是字符串,当请求报文到java程序会被封装为一个ServletInputStream流,开发人员再读取报文,响应报文则通过ServletOutputStream流,来输出响应报文。
从流中只能读取到原始的字符串报文,同样输出流也是。那么在报文到达SpringMVC / SpringBoot和从SpringMVC / SpringBoot出去,都存在一个字符串到java对象的转化问题。这一过程,在SpringMVC / SpringBoot中,是通过HttpMessageConverter来解决的。HttpMessageConverter接口源码:

  1. public interface HttpMessageConverter<T> {
  2. boolean canRead(Class<?> var1, @Nullable MediaType var2);
  3. boolean canWrite(Class<?> var1, @Nullable MediaType var2);
  4. List<MediaType> getSupportedMediaTypes();
  5. T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
  6. void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
  7. }

FastJson

代码

  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. @Override
  4. public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  5. converters.add(new ByteArrayHttpMessageConverter());
  6. // @ResponseBody 解决乱码
  7. converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
  8. converters.add(new ResourceHttpMessageConverter());
  9. converters.add(new AllEncompassingFormHttpMessageConverter());
  10. converters.add(fastJsonHttpMessageConverter());
  11. }
  12. @Bean
  13. public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
  14. FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
  15. FastJsonConfig config = new FastJsonConfig();
  16. //Long类型转String类型
  17. SerializeConfig serializeConfig = SerializeConfig.globalInstance;
  18. // ToStringSerializer 是这个包 com.alibaba.fastjson.serializer.ToStringSerializer
  19. serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
  20. serializeConfig.put(Long.class, ToStringSerializer.instance);
  21. serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
  22. config.setSerializeConfig(serializeConfig);
  23. config.setSerializerFeatures(
  24. SerializerFeature.WriteMapNullValue, // 保留map空的字段
  25. SerializerFeature.WriteNullStringAsEmpty, // 将String类型的null转成""
  26. SerializerFeature.WriteNullNumberAsZero, // 将Number类型的null转成0
  27. SerializerFeature.WriteNullListAsEmpty, // 将List类型的null转成[]
  28. SerializerFeature.WriteNullBooleanAsFalse, // 将Boolean类型的null转成false
  29. SerializerFeature.WriteDateUseDateFormat, //日期格式转换
  30. SerializerFeature.DisableCircularReferenceDetect // 避免循环引用
  31. );
  32. config.setSerializeFilters(valueFilter);
  33. converter.setFastJsonConfig(config);
  34. converter.setDefaultCharset(StandardCharsets.UTF_8);
  35. // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
  36. List<MediaType> mediaTypeList = new ArrayList<>();
  37. mediaTypeList.add(MediaType.APPLICATION_JSON);
  38. converter.setSupportedMediaTypes(mediaTypeList);
  39. return converter;
  40. }
  41. }
  42. /**
  43. * FastJson过滤器将null值转换为字符串
  44. * obj 是class
  45. * s 是key值
  46. * o1 是value值
  47. */
  48. public static final ValueFilter valueFilter = (obj, s, v) -> {
  49. if (v == null) {
  50. return "";
  51. }
  52. return v;
  53. };

代码2

  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. /**
  4. * 添加拦截器
  5. */
  6. @Override
  7. public void addInterceptors(InterceptorRegistry registry){
  8. //全局拦截器
  9. registry.addInterceptor(new GlobalInterceptor())
  10. .addPathPatterns("/**")
  11. .excludePathPatterns("/static/**");
  12. //登陆拦截器
  13. registry.addInterceptor(new LoginInterceptor())
  14. .addPathPatterns("/**")
  15. .excludePathPatterns("/static/**");
  16. }
  17. /**
  18. * 利用fastJson替换掉jackson,且解决中文乱码问题
  19. */
  20. @Override
  21. public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
  22. FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
  23. FastJsonConfig fastJsonConfig = new FastJsonConfig();
  24. fastJsonConfig.setSerializerFeatures(
  25. SerializerFeature.DisableCircularReferenceDetect,
  26. SerializerFeature.WriteMapNullValue,
  27. SerializerFeature.WriteNullNumberAsZero,
  28. SerializerFeature.WriteNullStringAsEmpty,
  29. SerializerFeature.WriteNullListAsEmpty,
  30. SerializerFeature.WriteNullBooleanAsFalse,
  31. SerializerFeature.WriteNonStringKeyAsString,
  32. SerializerFeature.BrowserCompatible);
  33. //解决Long转json精度丢失的问题
  34. SerializeConfig serializeConfig = SerializeConfig.globalInstance;
  35. serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
  36. serializeConfig.put(Long.class, ToStringSerializer.instance);
  37. serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
  38. fastJsonConfig.setSerializeConfig(serializeConfig);
  39. //处理中文乱码问题
  40. List<MediaType> fastMediaTypes = new ArrayList<>();
  41. fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
  42. fastConverter.setSupportedMediaTypes(fastMediaTypes);
  43. fastConverter.setFastJsonConfig(fastJsonConfig);
  44. converters.add(fastConverter);
  45. }
  46. }

Jackjson

  1. @EnableWebMvc
  2. @Configuration
  3. public class WebConfig extends WebMvcConfigurerAdapter {
  4. public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  5. MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
  6. SimpleModule simpleModule = new SimpleModule();
  7. simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
  8. simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
  9. ObjectMapper objectMapper = new ObjectMapper();
  10. objectMapper.registerModule(simpleModule);
  11. jacksonConverter.setObjectMapper(objectMapper);
  12. converters.add(jacksonConverter);
  13. }
  14. }
  1. @Component
  2. public class JacksonSerializerConfig {
  3. @Bean
  4. public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
  5. Jackson2ObjectMapperBuilderCustomizer customizer = new
  6. Jackson2ObjectMapperBuilderCustomizer() {
  7. @Override
  8. public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
  9. jacksonObjectMapperBuilder
  10. .serializerByType(Long.class, ToStringSerializer.instance)
  11. .serializerByType(Long.TYPE, ToStringSerializer.instance);
  12. }
  13. };
  14. return customizer;
  15. }
  16. }

参考