Fegin 接口去除 @RequestBody ,解决在没有@RequestBody 接收不到参数问题
需求: 为了达到Fegin接口和控制层提供接口一致(因为微服务fegin接口和控制层的接口基本和是一致,避免重复的代码量,规范编码,提高阅读型)例如:fegin接口有控制层就会有其中出现了大量重复的代码且不好阅读。从而想到控制层直接实现fegin接口控制层直接重写方法达到我们的目的调试过程中出现的问题:fegin 传递对象时必须使用@RequstBody 原因...
需求: 为了达到Fegin接口和控制层提供接口一致(因为微服务fegin接口和控制层的接口基本和是一致,避免重复的代码量,规范编码,提高阅读型)
例如:fegin接口有
控制层就会有
其中出现了大量重复的代码且不好阅读。
从而想到控制层直接实现fegin接口
控制层直接重写方法达到我们的目的
调试过程中出现的问题:fegin 传递对象时必须使用@RequstBody 原因就是每个requst只能有一个requestBody,egin 底层会使用post发送请求,将传递的对象设置请求体中带过去。所以有且只能有一个@RequestBody。又因为各种原因不能对rpc接口使用@RequestBody(我们采用的是表单提交,已经大量使用无法更改),所以想出去除fegin 必须对对象使用 @RequestBody才能接收到参数。
原因分析:
SpringMVC中使用RequestResponseBodyMethodProcessor类进行入参、出参的解析。以下方法根据参数是否有@RequestBody注解判断是否进行消息体的转换。
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
}
解决方案:
Srping Mvc 使用RequestResponseBodyMethodProcessor进行参数解析,可以实现一个定制化的Processor,修改supportParameter的判断方法
@Override
public boolean supportsParameter(MethodParameter parameter)
{
//springcloud的接口入参没有写@RequestBody,并且是自定义类型对象 也按JSON解析
if (AnnotatedElementUtils.hasAnnotation(parameter.getContainingClass(), FeignClient.class) && isCustomizedType(parameter.getParameterType())) {
return true;
}
return super.supportsParameter(parameter);
}
内容采自:https://blog.csdn.net/phoebechen_gz/article/details/82500904
具体代码
1.定制化的Processor,修改supportParameter的判断方法
/**
* 覆盖 RequestResponseBodyMethodProcessor supportsParameter 方法使含有FeignClient接口的方法都使用
* RequestResponseBodyMethodProcessor 的方式解析请求 从而接口可以去除@requestBody
* @Author Tang
* @Description
* @Date 11:05 2019/11/21
* @Param
* @return
**/
public class MyRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {
public MyRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {
super(converters);
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
System.out.println("进入自定义============MyRequestResponseBodyMethodProcessor");
if(AnnotatedElementUtils.hasAnnotation(parameter.getContainingClass(), FeignClient.class)){
return true;
}
return super.supportsParameter(parameter);
}
}
2.实现WebMvcConfigurer中的addArgumentResolvers接口
@Configuration
public class MsgMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(5);
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(stringHttpMessageConverter);
messageConverters.add(new SourceHttpMessageConverter<>());
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
messageConverters.add(jackson2HttpMessageConverter);
MyRequestResponseBodyMethodProcessor resolver = new MyRequestResponseBodyMethodProcessor(messageConverters);
argumentResolvers.add(resolver);
}
}
参考文章:
WebMvcConfigurationSupport和WebMvcConfigurer的区别https://blog.csdn.net/kehonghg/article/details/81180731
HttpMessageConverter https://www.jianshu.com/p/0aaeb4144489
2019.11.23补充
突发奇想,内部调用没问题了我又想本地使用formdata在本地调用fegin接口待补充。。
更多推荐
所有评论(0)