@RestController 源码解读:解决 Web 开发中 REST 服务的疑难杂症

目录

一、@RestContrller注解

1.1 查看底层源码

1.2 @AliasFor注解说明

1.2.1 注解别名

1.2.2 元数据别名

1.3 value() 方法的作用


一、@RestContrller注解

1.1 查看底层源码

首先编写如下内容:

@RestController
public class TestController {

    
}

按住 Ctrl , 鼠标点击 @RestController 进入源码:

  1. @Target注解说明:查看底层源码发现
     

  2. @Documented:标明这个注解会包含在JavaDoc文档中

  3. @Retention:表示这个注解在运行时仍然有效,可以通过反射机制读取。


1.2 @AliasFor注解说明

@AliasFor是Spring框架的一个注解,用于声明注解属性的别名。它有两种不同的应用场景。

  • 注解内的别名

  • 元数据的别名

1.2.1 注解别名

查看@AliasFor注解源码:


 

通过该注解可以知道@AliasFor(value="xxx")和@AliasFor(attribute="xxx")的作用是相同的,接下来我们举例说明:

  1. 首先我需要自定义一个注解

    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface MyInterface1 {
        String value1() default "";
    }

    当我们使用到该注解如 @MyInterface1(value1="number1"),表示 value1 的属性传入了 number1的值。现在如果自定义的注解改变为如下方式,但我希望通过 @MyInterface1(value2="number1") 达到上述相同的效果:

    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface MyInterface1 {
    
        String value1() default "";
    
        String value2() default "";
    }

    就可以添加@Alias()注解为注解内方法(因为@Alias作用域是方法注解)起别名:

    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface MyInterface1 {
    
        @AliasFor(value = "value2")
        String value1() default "";
    
        @AliasFor(value = "value1")
        String value2() default "";
    }

    达到 @MyInterface1(value2="number1") 和 @MyInterface1(value1="number1") 的效果相同。

注意事项:

  1. 组成别名对的每个属性都必须加上注释 @AliasFor,attribute()或value() 属性必须引用该对中另一个属性
  2. 别名属性必须声明相同的返回类型
  3. 别名属性必须声明一个默认值
  4. 别名属性必须声明相同的默认值

1.2.2 元数据别名

  1. 自定义第一个注解:

    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    public @interface MyInterface1 {
        String value() default "";
    }

  2. 自定义第二个注解:

    @Retention(value = RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    @MyInterface1
    public @interface MyInterface2 {
    
        @AliasFor(annotation = MyInterface1.class,value = "value")
        String value() default "";
    }

    此时@MyInterface1 (“number”)就和@MyInterface2(“number”)等价。这里可以理解成,注解MyInterface2的value属性重写了注解MyInterface1的value属性,但重新的属性的返回类型必须相同。

    此时再来查看@RestController 的@Alias:

        @RestController(value="xxxx")和@Controller(value="xxx")等价。

类似的使用包括:

可以看出对于value这个属性来说,@Configuration注解中的值会重写@Component的value属性值,这有点像类之间的继承,子类可以重父类的方法。我们也可以将@Configuration注解看成@Component的子注解


1.3 value() 方法的作用

@RestController的定义中,value()方法使用@AliasFor注解将其与@Controllervalue属性关联起来。这意味着当在@RestController上使用value属性时,它实际上等同于在@Controller上使用value属性,用于指定控制器的基本路径等相关信息,例如@RestController("myControllerPath")这种用法

也就是说value属性用于指定控制器的基本路径,那么我们进行接下来的测试:

  1. 首先编写Controller类代码:运行项目

    @RestController(value = "user")
    public class TestController {
        
        @RequestMapping("/test")
        public String test(){
            return "测试成功!";
        }
        
    }

    结果程序并没有识别到,发生404错误:

  2. 接下来测试/test路径:发现可以访问成功

  3. 所以如果是要填写路径的话,还是需要使用 @RequestMapping("/user/test")才是正确的,代码修改后测试:
    @RestController(value = "user")
    @RequestMapping("/user")
    public class TestController {
    
        @RequestMapping("/test")
        public String test(){
            return "测试成功!";
        }
    
    }

    此时就可以访问成功了:

  4. 一般情况下,我们修改为如下的规范:

    @RestController
    @RequestMapping("/user")
    public class TestController {
    
        @RequestMapping("/test")
        public String test(){
            return "测试成功!";
        }
    
    }

        所以value()方法的解释仅仅是 “建议”。

JDK 17 引入 records 新特性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/913334.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Android】轮播图——Banner

引言 Banner轮播图是一种在网页和移动应用界面设计中常见的元素,主要用于在一个固定的区域内自动或手动切换一系列图片,以展示不同的内容或信息。这个控件在软件当中经常看到,商品促销、热门歌单、头像新闻等等。它不同于ViewPgaer在于无需手…

游戏引擎学习第一天

视频参考: https://www.bilibili.com/video/BV1zGDCYHErA/ 创建一个保存项目的路径 VS的安装略过,个人自行百度 1. vs 创建第一个CMAKE的窗口项目 game.cpp 修改如下的代码 到https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain 去…

ArcGIS软件之“计算面积几何”地图制作

目录 一、消防站的泰森多边形ex12二、人口调查的泰森多边形三、人口调查的泰森多边形属性设置四、计算面积几何,用于求密度五、求密度六、给“现有中学”属性 R1赋值七、“现有中学”设置多环缓存区 并为它赋值八、“土地使用”为不同的功能区赋值九、三个图层相交十…

Rust @绑定(Rust@绑定)(在模式匹配的同时将值绑定到变量)

文章目录 Rust中的绑定基础概念示例:基本模式匹配 绑定的使用示例:范围匹配并绑定变量 深入探索绑定的好处示例:复杂数据结构中的应用 总结 附加 Rust中的绑定 Rust 语言以其强类型系统和内存安全的特性著称。在进行模式匹配时,R…

使用EasyExcel实现导出excel文件时生成多级下拉选

前言 公司有个需求本来只涉及到两个下拉选项&#xff0c;后面就想能不能实现多个下拉选&#xff0c;当然我这里说的多个下拉选是联动的&#xff0c;比如省、地市、区县这种。 实现步骤 1、添加EasyExcel的Maven依赖 <dependency><groupId>com.alibaba</group…

海量小文件挑战下的CephFS:优化策略与实践探索

文章目录 1.背景2.基本概念2.1 CephFS IO流程2.2 Ceph-FUSE 3. 问题3.1 问题源起3.2 理论分析3.3 原因排查3.3.1 Ceph-FUSE日志分析3.3.2 提出猜想3.3.3 代码验证3.3.3.1 MDS端3.3.3.2 Ceph-FUSE端 3.4 小结 1.背景 随着大数据、人工智能技术的蓬勃发展&#xff0c;人类对于算…

编写一个脚本实现参数的远程主机网络探测python test_ip.py 192.168.0.10~192.168.0.100(sys模块)

""" 编写一个脚本实现参数的远程主机网络探测python test_ip.py 192.168.0.10~192.168.0.100 """ #导入模块 #读取起始IP&#xff0c;结束IP import sys start_ip sys.argv[1] end_ip sys.argv[2] # print(start_ip,end_ip)##########组装数据…

lvgl: 示例入门

目录 1. A very simple hello world label 2. A button with a label and react on click event 3. Create styles from scratch for buttons 4. Create a slider and write its value on a label 1. A very simple hello world label void _lv_example_get_started_1(void) …

Redis2:Redis数据结构介绍、通用命令、String类型、Key的层级格式

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

云计算基础

声明 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 目录 一、云架构介绍 二、云服务 三、云分类 四、共享责任模型 五、云架构 六、云架构设计 七、集…

【超级详细】基于Zynq FPGA对雷龙SD NAND的测试

目录 一、SD NAND特征1.1 SD卡简介1.2 SD卡Block图 二、SD卡样片三、Zynq测试平台搭建3.1 测试流程3.2 SOC搭建 一、SD NAND特征 1.1 SD卡简介 雷龙的SD NAND有很多型号&#xff0c;在测试中使用的是CSNP4GCR01-AMW与CSNP32GCR01-AOW。芯片是基于NAND FLASH和 SD控制器实现的…

python中常见的8种数据结构之一列表

列表是Python中最常见的数据结构之一。它是一种有序的集合&#xff0c;可以包含不同类型的数据。 以下是列表的一些特点和常见操作&#xff1a; 1. 定义列表&#xff1a;可以使用方括号&#xff08;[]&#xff09;来定义一个空列表&#xff0c;也可以在方括号中添加元素来初始…

Python 在PDF中绘制形状(线条、矩形、椭圆形等)

在PDF中绘制图形可以增强文档的视觉效果。通过添加不同类型的形状&#xff0c;如实线、虚线、矩形、圆形等&#xff0c;可以使文档更加生动有趣&#xff0c;提高读者的阅读兴趣。这对于制作报告、演示文稿或是教材特别有用。本文将通过以下几个示例介绍如何使用Python 在PDF中绘…

AndroidStudio-滚动视图ScrollView

滚动视图 滚动视图有两种: 1.ScrollView&#xff0c;它是垂直方向的滚动视图;垂直方向滚动时&#xff0c;layout_width属性值设置为match_parent&#xff0c;layout_height属性值设置为wrap_content。 例如&#xff1a; &#xff08;1&#xff09;XML文件中: <?xml ve…

【后端速成Vue】computed计算属性

前言&#xff1a; 本期将会介绍 Vue 中的计算属性&#xff0c;他和 methods 方法又会有什么区别呢&#xff1f;在这里都会给你一一讲解。 篮球哥找工作专属IT岗位内部推荐&#xff1a; 专属内推链接&#xff1a;内推通道 1、computed计算属性 概念&#xff1a; 基于现有的数据…

mysql 配置文件 my.cnf 增加 lower_case_table_names = 1 服务启动不了的原因

原因&#xff1a;在MySQL8.0之后的版本&#xff0c;只允许在数据库初始化时指定&#xff0c;之后不允许修改了 mysql 配置文件 my.cnf 增加 lower_case_table_names 1 服务启动不了 报错信息&#xff1a;Job for mysqld.service failed because the control process exited …

优化时钟网络之时钟偏移

Note&#xff1a;文章内容以Xilinx 7系列FPGA进行讲解 1、基本介绍 所谓时钟偏移&#xff08;Clock Skew&#xff09;&#xff0c;是指在同步时序电路中&#xff0c;同一个时钟信号到达各个寄存器时钟端口的时间不一致的现象。如下图所示&#xff1a; 时钟从源端到达寄存器FF1的…

npm镜像的常用操作

查看当前配置的 npm 镜像 npm config get registry切换官方镜像 npm config set registry https://registry.npmjs.org/切换淘宝镜像(推荐) npm config set registry https://registry.npmmirror.com/切换腾讯云镜像 npm config set registry http://mirrors.cloud.tencent…

Notepad++ 最新官网中文版在线下载 附文本编辑器安装与基础使用教程

Notepad &#xff08;记事本&#xff09;是一个简单的文本编辑器&#xff0c;预装在所有版本的 Microsoft Windows 操作系统中。它的主要功能是创建、编辑和存储纯文本文件&#xff0c;通常以 .txt 格式保存。Notepad 的设计旨在提供一个轻量级的文本处理工具&#xff0c;适合快…

Deprecated Gradle features were used in this build

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 今天我使用gradle搭建springboot项目使用&#xff0c;报警告Deprecated Gradle features were used in this build, making it inco…