前言

这里分享一下我遇到的一个挺有意思的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

【API知识】一种你可能没见过的Controller形式的更多相关文章

  1. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  2. 这是你没见过的不一样的redis

    转: 这是你没见过的不一样的redis 提到Redis,大家一定会想到的几个点是什么呢? 高并发,KV存储,内存数据库,丰富的数据结构,单线程(6版本之前) 那么,接下来,上面提到的这些,都会一一给大 ...

  3. 超赞!12套你没见过的社交媒体 & 社交网站图标

    如今,社交网络成为我们信息获取和传播的重要途径,很多网站都有把内容分享到社交媒体的功能.社交媒体图标作为向用户传递信息的重要媒介,不管是在网页还是 Web 应用程序中都非常需要.今天这篇文章和大家分享 ...

  4. struts2的action访问servlet API的三种方法

    学IT技术,就是要学习... 今天无聊看看struts2,发现struts2的action访问servlet API的三种方法: 1.Struts2提供的ActionContext类 Object g ...

  5. Action访问Servlet API的三种方法

    一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...

  6. 【.Net】调用Web API的几种方式

    引言 记录一下调用Web API的几种方式,以调用百度API为例. HttpWebRequest HttpWebRequest位于System.Net命名空间,是常用的调用Web API类库. str ...

  7. Vue.js 2.x API 知识梳理(一) 全局配置

    Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...

  8. 在C#中使用RESTful API的几种好方法

    什么是Restful API REST 即Representational State Transfer的缩写.直接翻译的意思是"表现层状态转化". 它是一种互联网应用程序的API ...

  9. Queue API的几种实现详解

    目录 Queue API的几种方法的使用 ArrayBlockingQueue原理及源码解析 ArrayBlockingQueue的成员变量 ArrayBlockingQueue的offer和put方 ...

随机推荐

  1. [jzoj]3468.【NOIP2013模拟联考7】OSU!(osu)

    Link https://jzoj.net/senior/#main/show/3468 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: ...

  2. Html开发中document.getElementByTagName无法找到所有DOM元素的问题解决方法

    let eleList = document.querySelectorAll('li') for (let i = 0; i < eleList.length; i++) { // 遍历操作 ...

  3. Qt5+MSVC2015环境将VS2015编写的控制台程序转化为GUI程序

    如题所述,如何将VS2015编写的控制台程序转化为Qt5+MSVC2015环境编译的GUI程序? 最近想到这个操作,类似于Linux下使用的命令行操作转到Windows下使用GUI操作,看了控制台的命 ...

  4. Hadoop集群搭建-HA高可用(手动切换模式)(四)

    步骤和集群规划 1)保存完全分布式模式配置 2)在full配置的基础上修改为高可用HA 3)第一次启动HA 4)常规启动HA 5)运行wordcount 集群规划: centos虚拟机:node-00 ...

  5. 28 ArcMap 运行特别慢怎么办

    小编电脑配置如下: , 虽然不是太好吧,但还是满足ArcMap运行的要求的,但不知道为什么,就是很慢,终于在无意中,发现了一个位置,取消勾选以后,ArcMap变的快很多,亲测有效 取消后台处理后,Ar ...

  6. Lua学习----零碎知识点

    Jit(just in time) 动态即时编译,边运行时边编译---->lua (主要是面向进程) Aot(ahead of time) 静态提前编译,运行前编译---->C#(主要是面 ...

  7. CSS Media媒体查询使用大全,完整媒体查询总结

    前面的话 一说到响应式设计,肯定离不开媒体查询media.一般认为媒体查询是CSS3的新增内容,实际上CSS2已经存在了,CSS3新增了媒体属性和使用场景(IE8-浏览器不支持).本文将详细介绍媒体查 ...

  8. Android OpenGL ES 开发(四): OpenGL ES 绘制形状

    在上文中,我们使用OpenGL定义了能够被绘制出来的形状了,现在我们想绘制出来它们.使用OpenGLES 2.0来绘制形状会比你想象的需要更多的代码.因为OpenGL的API提供了大量的对渲染管线的控 ...

  9. Javascript高级编程学习笔记(84)—— Canvas(1)基本用法

    Canvas绘图 Canvas自HTML5引入后,由于其炫酷的效果成为HTML5新增功能中最受欢迎的部分 Canvas元素通过在页面中设定一个区域,然后就可以使用JS在其中绘制图形 <canva ...

  10. Python爬虫7-Cookie & Session

    GitHub代码练习地址:1.手动利用cookie访问网页:https://github.com/Neo-ML/PythonPractice/blob/master/SpiderPrac10_cook ...