需求: 爲了達到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接口待補充。。