需求: 为了达到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接口待补充。。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐