使用HttpMessageConverters解决精度损失问题导致Feign不能通信
原因:
以下代码
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
SerializeConfig config = new SerializeConfig();
config.put(Long.class, new LongObjectSerializer());
fastJsonConfig.setSerializeConfig(config);
fastConverter.setFastJsonConfig(fastJsonConfig);
return new HttpMessageConverters(fastConverter);
}
public class LongObjectSerializer implements ObjectDeserializer, ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object,
Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter out = serializer.out;
if (object == null) {
out.append("");
return;
}
String strVal = object.toString();
out.writeString(strVal);
}
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type,
Object fieldName) {
return null;
}
@Override
public int getFastMatchToken() {
// TODO Auto-generated method stub
return 0;
}
}
修改了http请求序列化的方法,long转为string。
由于fegin使用的是http请求,实体类的请求是http请求(伪RPC),当然long类型的参数也会被转换成string,导致这个错:
JSONException: default constructor not found. class xxx
解决方法将feginClient类的请求的long类型参数转为string类型的
但是又报了以下错误:
EncodeException: 'Content-Type' cannot contain wildcard type '*'
百度搜了一下,是alibaba.fastjson新版本不支持Content-Type为“*”的问题,配置:
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
supportedMediaTypes.add(MediaType.APPLICATION_PDF);
supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XML);
supportedMediaTypes.add(MediaType.IMAGE_GIF);
supportedMediaTypes.add(MediaType.IMAGE_JPEG);
supportedMediaTypes.add(MediaType.IMAGE_PNG);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
supportedMediaTypes.add(MediaType.TEXT_HTML);
supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
supportedMediaTypes.add(MediaType.TEXT_XML);
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
fastConverter.setSupportedMediaTypes(supportedMediaTypes);
return new HttpMessageConverters(fastConverter);
}
然后接着运行,发现了
HttpRequestMethodNotSupportedException: Request method 'POST' not supported
异常,但是feginClient里面的接口我定义的是@GetMapping,百度查了一下,fegin会将有参数的请求强制转成了POST方式,然后如果传的参数不是实体类的话需要在方法参数里面加上@RequestParam()
可能还会遇到下面这个异常
although at least one Creator exists
这个是feginclient返回实体类中使用了lombok表达式的@Builder注释造成的,取消掉就好了