Fegin 接口去除 @RequestBody ,解決在沒有@RequestBody 接收不到參數問題

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章