当前位置: 首页 > article >正文

@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 新特性


http://www.kler.cn/a/391621.html

相关文章:

  • JSON-RPC-CXX深度解析:C++中的远程调用利器
  • C/C++精品项目之图床共享云存储(3):网络缓冲区类和main
  • 类别变量分析——卡方独立性检验卡方拟合优度检验
  • 【教程】华南理工大学国际校区宿舍门锁声音设置
  • 【设计模式】关联关系与依赖关系
  • Java基础-组件及事件处理(下)
  • Hbase入门
  • 树莓派安装FreeSWITCH
  • v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
  • 23. 管理架构债务
  • 0基础跟德姆(dom)一起学AI 深度学习02-Pytorch基本使用
  • 力扣 LeetCode 142. 环形链表II(Day2:链表)
  • 负载均衡式在线oj项目开发文档2(个人项目)
  • Linux之进程
  • java:多态练习
  • filerchain是什么类
  • MongoDB增删改查,复杂查询案例分析
  • 精准监测,高效防护:特力康输电线路防山火新方案
  • Vue2+ElementUI:用计算属性实现搜索框功能
  • Python网络爬虫简介
  • 信令服务器设计之websocket
  • Spring Boot基础教学:Spring Boot 简介
  • 元器件封装
  • Linux系统编程学习 NO.11——进程的概念(2)
  • IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发
  • php中ajax怎么使用【小白专用24.11.12】