博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud 中使用Feign解决参数注解无法继承的问题
阅读量:6366 次
发布时间:2019-06-23

本文共 4191 字,大约阅读时间需要 13 分钟。

Spring Cloud 中使用Feign解决参数注解无法继承的问题

在使用Feign的时候,通常先写一个接口类,然后再写实现类,根据官网的例子接下来编写一个简单的Feign的请求例子

@FeignClient("spring-cloud-eureka")public interface FeignDemoApi {        @RequestMapping("/testFeign")    public String testSpringMvc(@RequestBody User user);}复制代码

然后实现类如下

@RestControllerpublic class FeignDemoApiImpl implements FeignDemoApi{    @Override    public String testSpringMvc(User user) {        return user.getName();    }}复制代码

然后测试类编写如下

@RequestMapping("/testSpringmvc")    public void test6(){        User user =new User();        user.setName("test");        user.setAge(18);        feignDemoApi.testSpringMvc(user);    }复制代码

发现在客户端进行接收的时候发现接收到的User为null

然后从网上查资料才知道需要在实现类的入参中也加入@RequestBody注解,这样才能接收到参数。但是不禁有个疑问,我们查看@RequestMapping@RequestBody这两个注解的代码中都没有@Inherited这个可支持继承的注解,那么@RequestMapping为什么能发挥作用?而@RequestBody却不能发挥作用呢?

@RequestMapping 注解

然后经过查资料了解到,SpringMvc在初始化时候会将带有@Controller初始化进Spring容器中,其实例化的类型为RequestMappingInfo类,此时在SpringMvc中会加载@Controller类注解下的所有带有@ RequestMapping的方法,将其@RequestMapping中的属性值也加载进来,如果在本类方法上找不到@RequestMapping注解信息的话,那么就会寻找父类相同方法名的@RequestMapping的注解。具体在AnnotatedElementUtils类中的searchWithFindSemantics方法中有下面的一段。表示在父类中寻找注解。

// Search on interfacesfor (Class
ifc : clazz.getInterfaces()) { T result = searchWithFindSemantics(ifc, annotationType, annotationName, containerType, processor, visited, metaDepth); if (result != null) { return result; }}复制代码

此时就能知道为什么在子类中没有加@RequestMapping注解,但是却享有父类@RequestMapping注解的效果了。

@RequestBody 注解

在上面的注解中我们了解到虽然@RequestMapping不支持继承,但是子类享有同样效果的原因就是在判断的时候如果子类没有就去父类找,但是在测试中我们发现@RequestBody是没有享受此效果的,所以我猜测在判断是否有注解的时候只是判断本类有没有此注解而没有判断父类。

经过查询资料,发现在SpringMvc中使用RequestResponseBodyMethodProcessor来进行入参和出参的解析,其中使用supportsParameter来判断是否有@RequestBody的注解

@Override	public boolean supportsParameter(MethodParameter parameter) {		return parameter.hasParameterAnnotation(RequestBody.class);	}复制代码

我们发现事实如我们猜测的一样。

解决方案

我们也可以像@RequestMapping注解一样进行判断如果本类没有的话,那么就对其父类进行判断。创建一个配置类然后将自定义的ArgumentResolvers放入到RequestMappingHandlerAdapter

@Configurationpublic class MyWebMvcConfigu implements BeanFactoryAware {    private ConfigurableBeanFactory beanFactory;    @Autowired    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;	//判断其父类是否有注解    public static  MethodParameter interfaceMethodParameter(MethodParameter parameter,            Class annotationType) {        if (!parameter.hasParameterAnnotation(annotationType)) {            for (Class
itf : parameter.getDeclaringClass().getInterfaces()) { try { Method method = itf.getMethod(parameter.getMethod().getName(), parameter.getMethod().getParameterTypes()); MethodParameter itfParameter = new MethodParameter(method, parameter.getParameterIndex()); if (itfParameter.hasParameterAnnotation(annotationType)) { return itfParameter; } } catch (NoSuchMethodException e) { continue; } } } return parameter; } @PostConstruct public void modifyArgumentResolvers() { List
list = new ArrayList<>(requestMappingHandlerAdapter.getArgumentResolvers()); // RequestBody 支持接口注解 list.add(0, new RequestResponseBodyMethodProcessor(requestMappingHandlerAdapter.getMessageConverters()) { @Override public boolean supportsParameter(MethodParameter parameter) { return super.supportsParameter(interfaceMethodParameter(parameter, RequestBody.class)); } @Override // 支持@Valid验证 protected void validateIfApplicable(WebDataBinder binder, MethodParameter methodParam) { super.validateIfApplicable(binder, interfaceMethodParameter(methodParam, Valid.class)); } }); // 修改ArgumentResolvers, 支持接口注解 requestMappingHandlerAdapter.setArgumentResolvers(list); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = (ConfigurableBeanFactory) beanFactory; }}复制代码

然后我们就可以发现再重新调用以后子类没有加入@RequestBody注解也能够接收到实体类了

参考文章

转载地址:http://ljrma.baihongyu.com/

你可能感兴趣的文章
jdbc url
查看>>
刷leetcode第704题-二分查找
查看>>
debug_backtrace() 函数生成一个 backtrace(追踪)
查看>>
第七天,还是盒子
查看>>
XAMPP软件包下载
查看>>
XXL-JOB初体验-ORACLE版
查看>>
沉思录:别人的棺材
查看>>
jersey + spring + mybatis + redis项目搭建
查看>>
PAT 1006 部分正确_另一种解法
查看>>
在Keil环境下使用JLink实现printf输出重定向至debug窗口
查看>>
postgres的\d命令不显示全部的用户表
查看>>
poj 3468 A Simple Problem with Integers
查看>>
OOA/OOD/OOP细讲
查看>>
Tomcat 系统架构与设计模式_ 设计模式分析
查看>>
本地串口TCP/IP 映射到远端串口
查看>>
锁机制探究
查看>>
硬盘直接引导启动Manjaro Linux iso
查看>>
CodeSmith代码生成工具介绍
查看>>
几个常用且免费的接口
查看>>
jQuery文件上传插件 Uploadify更改错误提示的弹出框
查看>>