前言

这里分享一下我遇到的一个挺有意思的Controller形式,内容涉及@RequestMapping注解的原理。

实际案例

一、基本描述

项目甲中有多个模块,其中就有模块A和B。(这里的模块指的是Maven的多模块子项目),项目乙、丙、丁可以引用模块A来访问独立部署的模块B

模块A  => 关于与模块B通信的协议定义

模块B  => 可以独立部署的项目

其中模块A中定义了一个FeignClient的接口用于访问模块B的服务。

@FeignClient(name = "xx-service", url="http://xx-service:8080")
public interface XXXService {
@PostMapping("/some-url")
public SomeResponse someOperation(@RequestBody SomeParam param);
...
}

我们知道只要打上了@FeignClient注解,我们就可以直接在类中引入这个XXXService,然后调用它的方法。如果我们调用someOperation方法,那它就会根据服务名获取到IP端口信息,然后发HTTP请求到指定服务xx-service。

二、问题出现

按理说,模块B肯定有一个Controller来处理这个“/som-url”的请求。于是我全局搜索了模块B,发现怎么找也找不到“/some-url”。

后来发现模块B中依赖于模块A,且有一个类实现了XXXService这个接口。这个类叫XXXServiceImpl。这个类既不叫xxxController,也不带@Controller注解。

@ResponseBody
@RequestMapping
@Service
public class XXXServiceImpl implements XXXService {
@Override
public SomeResponse someOperation(SomeParam param) {
SomeResponse someResponse = new SomeResponse();
...
return someResponse;
}
...
}

看到@ResponseBody,@RequestMapping,@Service。在我看来这就是一个@RestController了。但是问题来了,还是没有Mapping。

三、我的一个猜想

我想有没有可能实现类继承了接口方法上的注解,于是我看了下@PostMapping的元注解,发现并没有@Inherited的注解。我也尝试打印了XXXServiceImpl类someOperation方法上的注解,发现确实没有。

四、问题解答

XXXServiceImpl确实充当了Controller。关键在于针对@RequestMapping的扫描,会向上扫描类的所有父类和接口。只要在接口或者父类的上方法上发现了@RequestMapping的注解,就认定这个方法是某个请求关联的处理方法。

简化版本

可能有人不是很理解前面的实际案例,这里提供一个简化的版本。

一、新建一个只带Web的Spring Boot项目

二、定义一个接口

这个接口有一个方法,带有@GetMapping注解。

public interface ControllerInterface {
@GetMapping("/hello")
String hello();
}

三、添加实现类

@RequestMapping
@ResponseBody
@Service
public class ControllerInterfaceImpl implements ControllerInterface {
@Override
public String hello() {
return "hello world";
}
}

四、启动并测试

启动项目,访问http://localhost:8080/hello

发现确实可以访问。实际上组合方式还有很多,你可以把注解都写在接口上。

@RequestMapping原理简述

一、搜寻处理类

一个类上如果有@Controller或者@ReqeustMapping注解,会被认定为是请求的Handler。

二、搜寻处理方法

找到处理类后,第二步就是在处理类中查找处理方法,即标注有@RequestMapping(或者其他变种)的方法,注意这里扫描的过程中,会向上扫描父类或者接口是否带有此注解。这个操作由HandlerMethodSelector来完成(Spring 4有这个类,后面的版本可能名称有所变更)

三、整合URL生成RequestMappingInfo

如果处理类上有@RequestMpping注解,且有设置url,则会将类上和方法上的URL拼接起来。最终形成一个RequestMappingInfo。

四、生成映射关系

每个RequestMappingInfo会映射到一个处理方法HandlerMethod。

参考资料

1.@RestMapping原理讲解-1

2.HandlerMethodSelector

最新文章

  1. java并行计算Fork和Join的使用
  2. [译] 给PHP开发者的PHP源码-第一部分-源码结构
  3. Linux 进程间通讯详解五
  4. C#调用WebService获取天气信息
  5. 【Spark】jupyter notebook
  6. Java HexString
  7. 速度之王 — LZ4压缩算法(二)
  8. s21day20 python笔记
  9. linux systemd详解
  10. 2018-2019-1 20189203《Linux内核原理与分析》第八周作业
  11. C++使用: C++中map的基本操作和用法
  12. 关于windows下的文件结束符
  13. .NET Framework 版本和依赖关系[微软官方文档]
  14. Linux ext3/ext4数据恢复
  15. SQL Server 创建索引(index)
  16. 《DSP using MATLAB》Problem 6.4
  17. sas 命令行打开SAS IDE 的代码
  18. codeforce 192 div2解题报告
  19. es6 中的generator函数控制流程
  20. (转)List<T>的各种排序方法

热门文章

  1. react 的进阶
  2. 最短路径问题—Dijkstra算法
  3. 离校登记网页项目个人总结(Alpha阶段)
  4. Linux 系统中的内部与外部命令
  5. python elasticsearch 批量写入数据
  6. unittest各个组件之间的关系
  7. js面向对象自定义MyString()的构造器函数,实现内建String()属性和方法:
  8. go 语言的序列化与反序列化
  9. [Swift]LeetCode277. 寻找名人 $ Find the Celebrity
  10. [Swift]LeetCode632. 最小区间 | Smallest Range