我的编程空间,编程开发者的网络收藏夹
学习永远不晚

RequestMapping要写在Controller类里吗

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

RequestMapping要写在Controller类里吗

本篇内容介绍了“RequestMapping要写在Controller类里吗”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

使用Spring Cloud做项目的同学会使用Feign这个组件进行远程服务的调用,Feign这个组件采用模板的方式,有着优雅的代码书写规范。核心原理对Feign等相关注解进行解析,并提取信息,在Spring Boot工程启动时,通过反射生产Request的bean,并将提取的信息,设置到bean中,最后注入到ioc容器中。

现在有这样的场景,服务A提高RestApi接口,服务B、C、D等服务需要调用服务A提供的RestApi接口,这时最常见的做法是在服务B、C、D分别写一个FeignClient,并需要写RestApi接口的接收参数的实体和接收响应的实体DTo类。这样的做法就是需要不停复制代码。

有没有办法简洁上面的操作呢?有一种最常见的做法是将将服务A进行模块拆分,将FeignClient和常见的model、dto对外输出的类单独写一个模块,可以类似于取名a-service-open_share。这样将服务A服务分为两个模块,即A服务的业务模块和A服务需要被其他服务引用的公共类的模块。服务B、C、D只需要引用服务A的a-service-open_share就具备调用服务A的能力。

笔者在这里遇到一个有趣的其问题。首先看问题:

写一个FeignClient:

@FeignClient(name = "user-service")public interface UserClient {    @GetMapping("/users")    List<User> getUsers();

写一个实现类:

@RestControllerpublic class UserController implements UserClient {    @Autowired    UserService      userService;    @OverRide    List<User> getUsers(){       return userService.getUsers();    }

启动工程,浏览器访问接口localhost:8008/users,竟然能正确访问?!明明我在UserController类的getUsers方法没有加RequestMapping这样的注解。为何能正确的映射?!

带着这样的疑问,我进行了一番的分析和探索!

首先就是自己写了一个demo,首先创建一个接口类:

public interface ITest {    @GetMapping("/test/hi")    public String hi();}

写一个Controller类TestController

@RestControllerpublic class TestController implements ITest {    @Override    public String hi() {        return "hi you !";    }

启动工程,浏览器访问:http://localhost:8762/test/hi,浏览器显示:

hi you !

我去,TestController类的方法 hi()能够得到ITest的方法hi()的   @GetMapping(“/test/hi”)注解吗? 答案肯定是获取不到的。

特意编译了TestController字节码文件:
javap -c TestController

 public class com.example.demo.web.TestController implements com.example.demo.web.ITest {  public com.example.demo.web.TestController();    Code:       0: aload_0       1: invokespecial #1                  // Method java/lang/Object."<init>":()V       4: return  public java.lang.String hi();    Code:       0: ldc           #2                  // String hi you !       2: areturn}

上面的字节码没有任何关于@GetMapping(“/test/hi”)的信息,可见TestController直接获取不到@GetMapping(“/test/hi”)的信息。

那应该是Spring MVC在启动时在向容器注入Controller的Bean(HandlerAdapter)时做了处理。初步判断应该是通过反射获取到这些信息,并组装到Controller的Bean中。首先看通过反射能不能获取ITest的注解信息:

 public static void main(String[] args) throws ClassNotFoundException {    Class c = Class.forName("com.example.demo.web.TestController");    Class[] i=c.getInterfaces();    System.out.println("start interfaces.."  );    for(Class clz:i){        System.out.println(clz.getSimpleName());        Method[] methods = clz.getMethods();        for (Method method : methods) {            if (method.isAnnotationPresent(GetMapping.class)) {                GetMapping w = method.getAnnotation(GetMapping.class);                System.out.println("value:" + w.value()[0]  );            }        }    }    System.out.println("end interfaces.."  );    Method[] methods = c.getMethods();    for (Method method : methods) {        if (method.isAnnotationPresent(GetMapping.class)) {            GetMapping w = method.getAnnotation(GetMapping.class);            System.out.println("value:" + w.value());        }    }}

允运行上面的代码:

start interfaces..

ITest

value:/test/hi

end interfaces..

可见通过反射是TestController类是可以获取其实现的接口的注解信息的。为了验证Spring Mvc 在注入Controller的bean时通过反射获取了其实现的接口的注解信息,并作为urlMapping进行了映射。于是查看了Spring Mvc 的源码,经过一系列的跟踪在RequestMappingHandlerMapping.java类找到了以下的方法:

protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {   RequestMappingInfo info = createRequestMappingInfo(method);   if (info != null) {      RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);      if (typeInfo != null) {         info = typeInfo.combine(info);      }   }   return info;}

继续跟踪源码在AnnotatedElementUtils 类的searchWithFindSemantics()方法中发现了如下代码片段:

// Search on methods in interfaces declared locallyClass<?>[] ifcs = method.getDeclaringClass().getInterfaces();result = searchOnInterfaces(method, annotationType, annotationName, containerType, processor,      visited, metaDepth, ifcs);if (result != null) {   return result;}

这就是我要寻找的代码片段,验证了我的猜测。

“RequestMapping要写在Controller类里吗”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

RequestMapping要写在Controller类里吗

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

RequestMapping要写在Controller类里吗

本篇内容介绍了“RequestMapping要写在Controller类里吗”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用Spring
2023-06-19

vue中为何方法要写在methods的里面

这篇文章主要介绍了vue中为何方法要写在methods的里面,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-13

SAP ABAP里存在Java List集合工具类吗

这篇文章主要讲解了“SAP ABAP里存在Java List集合工具类吗”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SAP ABAP里存在Java List集合工具类吗”吧!在开发过程中发
2023-06-03

阿里云域名备案必须要在阿里云服务器吗

是的,如果您的网站或其他服务器托管在阿里云服务器上,您需要在备案时提供相关信息给阿里云客服,以获取阿里云服务器的相关政策和流程要求。在备案完成后,您可以通过阿里云的客服来获取更多有关网站备案的信息。备案的相关要求可能因国家和地区的不同而略有差异,以下是一些可能被提及的问题:备案需要提交哪些材料?我需要提供哪些信息?我需要多长时间才能完成备案?在了解所有备案相关信息和流程后,您可以按
2023-10-26

阿里云域名备案必须要在阿里云服务器备案吗安全吗

是的,阿里云的域名备案需要在阿里云服务器上进行备案。在域名备案过程中,您需要将域名的注册人或所有人等信息通过互联网发送到国家工业信息安全发展研究中心进行备案审核。通过审核后,您将获得一个电子验证码,用于访问您的域名信息。然而,在实际情况中,由于某些原因,域名备案的实际操作可能会受到限制。因此,建议您在备案过程中注意以下几点:选择正规的域名注册机构(如阿里云等)进行备案。在域名备案过程中,
2023-10-26

阿里云域名备案必须要在阿里云服务器备案吗

是的,阿里云的域名备案需要在阿里云服务器上进行备案。如果您是在阿里云的服务器上进行备案,可能需要提供您的信息、选择的服务器等,才能完成备案流程。如果您是在云服务器上备案,则无需在阿里云服务器上进行备案。备案过程通常是由阿里云管理员在您的系统中完成的。无论您在云服务器上如何操作,备案都会自动完成。需要注意的是,阿里云的域名备案政策可能会有所不同,具体备案要求可能会因为当地的备案规定而有所差异。
2023-10-26

阿里云域名备案必须要在阿里云服务器备案吗为什么

阿里云域名备案并不是强制要求的,备案可以在阿里云的官方网站上进行,但具体要求和流程可能因各地政策和法律法规不同而有所不同。您可以登录阿里云的官方网站,查看您所在地区关于域名备案的相关政策和要求,并根据相关要求进行操作。需要注意的是,不同地域对于域名备案的要求可能有不同,您可能需要查看您当地的政策或咨询当地的阿里云客服人员,以了解具体的备案要求和流程。
2023-10-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录