HttpMessageConverter
相信使用过Spring的开发人员都用过@RequestBody、@ResponseBody注解,可以直接将输入解析成Json、将输出解析成Json,但HTTP 请求和响应是基于文本的,意味着浏览器和服务器通过交换原始文本进行通信,而这里其实就是HttpMessageConverter发挥着作用。
HttpMessageConverter
Http请求响应报文其实都是字符串,当请求报文到java程序会被封装为一个ServletInputStream流,开发人员再读取报文,响应报文则通过ServletOutputStream流,来输出响应报文。
从流中只能读取到原始的字符串报文,同样输出流也是。那么在报文到达SpringMVC / SpringBoot和从SpringMVC / SpringBoot出去,都存在一个字符串到java对象的转化问题。这一过程,在SpringMVC / SpringBoot中,是通过HttpMessageConverter来解决的。HttpMessageConverter接口源码:
public interface HttpMessageConverter<T> {boolean canRead(Class<?> var1, @Nullable MediaType var2);boolean canWrite(Class<?> var1, @Nullable MediaType var2);List<MediaType> getSupportedMediaTypes();T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;}
FastJson
代码
@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new ByteArrayHttpMessageConverter());// @ResponseBody 解决乱码converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));converters.add(new ResourceHttpMessageConverter());converters.add(new AllEncompassingFormHttpMessageConverter());converters.add(fastJsonHttpMessageConverter());}@Beanpublic FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();FastJsonConfig config = new FastJsonConfig();//Long类型转String类型SerializeConfig serializeConfig = SerializeConfig.globalInstance;// ToStringSerializer 是这个包 com.alibaba.fastjson.serializer.ToStringSerializerserializeConfig.put(BigInteger.class, ToStringSerializer.instance);serializeConfig.put(Long.class, ToStringSerializer.instance);serializeConfig.put(Long.TYPE, ToStringSerializer.instance);config.setSerializeConfig(serializeConfig);config.setSerializerFeatures(SerializerFeature.WriteMapNullValue, // 保留map空的字段SerializerFeature.WriteNullStringAsEmpty, // 将String类型的null转成""SerializerFeature.WriteNullNumberAsZero, // 将Number类型的null转成0SerializerFeature.WriteNullListAsEmpty, // 将List类型的null转成[]SerializerFeature.WriteNullBooleanAsFalse, // 将Boolean类型的null转成falseSerializerFeature.WriteDateUseDateFormat, //日期格式转换SerializerFeature.DisableCircularReferenceDetect // 避免循环引用);config.setSerializeFilters(valueFilter);converter.setFastJsonConfig(config);converter.setDefaultCharset(StandardCharsets.UTF_8);// 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"List<MediaType> mediaTypeList = new ArrayList<>();mediaTypeList.add(MediaType.APPLICATION_JSON);converter.setSupportedMediaTypes(mediaTypeList);return converter;}}/*** FastJson过滤器将null值转换为字符串* obj 是class* s 是key值* o1 是value值*/public static final ValueFilter valueFilter = (obj, s, v) -> {if (v == null) {return "";}return v;};
代码2
@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {/*** 添加拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry){//全局拦截器registry.addInterceptor(new GlobalInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");//登陆拦截器registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");}/*** 利用fastJson替换掉jackson,且解决中文乱码问题*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters){FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullNumberAsZero,SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.WriteNullListAsEmpty,SerializerFeature.WriteNullBooleanAsFalse,SerializerFeature.WriteNonStringKeyAsString,SerializerFeature.BrowserCompatible);//解决Long转json精度丢失的问题SerializeConfig serializeConfig = SerializeConfig.globalInstance;serializeConfig.put(BigInteger.class, ToStringSerializer.instance);serializeConfig.put(Long.class, ToStringSerializer.instance);serializeConfig.put(Long.TYPE, ToStringSerializer.instance);fastJsonConfig.setSerializeConfig(serializeConfig);//处理中文乱码问题List<MediaType> fastMediaTypes = new ArrayList<>();fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);fastConverter.setSupportedMediaTypes(fastMediaTypes);fastConverter.setFastJsonConfig(fastJsonConfig);converters.add(fastConverter);}}
Jackjson
@EnableWebMvc@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter {public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();SimpleModule simpleModule = new SimpleModule();simpleModule.addSerializer(Long.class, ToStringSerializer.instance);simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);ObjectMapper objectMapper = new ObjectMapper();objectMapper.registerModule(simpleModule);jacksonConverter.setObjectMapper(objectMapper);converters.add(jacksonConverter);}}
@Componentpublic class JacksonSerializerConfig {@Beanpublic Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {Jackson2ObjectMapperBuilderCustomizer customizer = newJackson2ObjectMapperBuilderCustomizer() {@Overridepublic void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance).serializerByType(Long.TYPE, ToStringSerializer.instance);}};return customizer;}}
