项目场景:
项目采用的是webflux框架,对于传入json格式的请求数据用fastjson来解析
问题描述:
假设实体是下面的结构:
@Data
public class Student {
//姓名
@JSONField(name = "Name")
private String name;
//性别
@JSONField(name = "Gender")
private String sex;
//年龄
@JSONField(name = "Age")
private Integer age;
}
按照要求如果传入json请求数据格式如下:
{“Name”:“张三”,“Gender”:“male”,“Age”:“25”}
上面的实体按照fastJson对字段进行配置,但是实体并未映射到,后台结果如下
原因分析:
目前springboot webflux内置的消息解析器,还不支持fastJson,即使容器中配置fastJson也不行。
解决方案:
修改内置解析jackson的解析方式,让部分数据按照fastJson来解析,配置代码如下。
package com.zhoule.webflux.webflux_demo.config;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.AbstractJackson2Decoder;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.MimeType;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* @author zhoule
* @Description: config
* @date 2022/1/7 14:39
*/
@Configuration
public class WebFluxConfig implements WebFluxConfigurer {
private static FastJsonHttpMessageConverter fastJsonHttpMessageConverter;
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
fastJsonHttpMessageConverter.setFastJsonConfig(config);
HttpMessageConverter<?> converter = fastJsonHttpMessageConverter;
return new HttpMessageConverters(converter);
}
private ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
//自定义解码器
configurer.defaultCodecs().jackson2JsonDecoder(new CustomJsonDecoder(objectMapper));
//自定义编码器 编码器的道理和解码器基本类似,可以自行尝试
//configurer.defaultCodecs().jackson2JsonEncoder(null);
}
static class CustomJsonDecoder extends AbstractJackson2Decoder {
public CustomJsonDecoder(ObjectMapper mapper, MimeType... mimeTypes) {
super(mapper, mimeTypes);
}
@Override
public Object decode(DataBuffer dataBuffer, ResolvableType targetType, MimeType mimeType, Map<String, Object> hints) throws DecodingException {
Object read = null;
boolean flag = false;
try {
//如果是json格式 以及是否是自己的业务包
if (mimeType.toString().contains(MediaType.APPLICATION_JSON_VALUE) &&
targetType.getType().getTypeName().startsWith("com.zhoule")) {
read = fastJsonHttpMessageConverter.read(targetType.getType(), null, new CustomHttpInputMessage(dataBuffer.asInputStream()));
} else {
//不是想转换的数据直接返回父类调用
return super.decode(dataBuffer, targetType, mimeType, hints);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (flag) {
DataBufferUtils.release(dataBuffer);
}
}
return read;
}
}
//定义一个fastJson相关的HttpInputMessage
static class CustomHttpInputMessage implements HttpInputMessage {
private InputStream inputStream;
public CustomHttpInputMessage(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public InputStream getBody() throws IOException {
return inputStream;
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);
return httpHeaders;
}
}
}
改完后的效果如下: