前言

这里分享一下我遇到的一个挺有意思的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. elasticsearch简单操作

    现在,启动一个节点和kibana,接下来的一切操作都在kibana中Dev Tools下的Console里完成 创建一篇文档 将小黑的小姨妈的个人信息录入elasticsearch.我们只要输入 PU ...

  2. Docker安装ngnix使用ping报错

    最近在学习docker时,由于docker维护的dockerHub远程仓库的镜像文件比普通的文件小得多,所以经常碰到的情况是,一般常用的命令,会出现no command的情况.今天安装ping的时候就 ...

  3. tyflow雨滴在物体上滑落测试

    http://docs.tyflow.com/download/

  4. GYM 101617 F

    说到这题还要提到周日下午训练赛,都进去了hmc说他这场单切过准备换一场. 很不幸的是我当时已经开了这个几何题, 开场就开几何是什么鬼啊!!! 给你n个圆,找一点在所有园内并且离原点最远.(保证有解) ...

  5. A_B_Good Bye 2018_cf

    A. New Year and the Christmas Ornament time limit per test 1 second memory limit per test 256 megaby ...

  6. java中int和integer

  7. 多选ui实现单选效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. Hadoop 数据去重

    数据去重这个实例主要是为了读者掌握并利用并行化思想对数据进行有意义的筛选.统计大数据集上的数据种类个数.从网站日志中计算访问等这些看似庞杂的任务都会涉及数据去重.下面就进入这个实例的MapReduce ...

  9. [Swift]LeetCode33. 搜索旋转排序数组 | Search in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  10. [Swift]LeetCode981. 基于时间的键值存储 | Time Based Key-Value Store

    Create a timebased key-value store class TimeMap, that supports two operations. 1. set(string key, s ...