• 【API知识】一种你可能没见过的Controller形式


    前言

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

  • 相关阅读:
    2019软工实践_作业4_1(结对编程实现博客)
    2019软工实践_作业3_2(团队介绍博客)
    跨域资源共享CORS
    解决IntelliJ无法导入maven包的问题
    IntelliJ IDEA中各种小图标的含义
    IntelliJ 发布Maven项目时所需的Jar没有打包的问题
    IntelliJ跳转到抽象方法的实现
    IntelliJ IDEA利用Maven下载所需的JAR包到项目中
    Java编程思想代码环境配置
    查看window用户登录日志
  • 原文地址:https://www.cnblogs.com/longfurcat/p/10741369.html
Copyright © 2020-2023  润新知