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

前言

这里分享一下我遇到的一个挺有意思的Controller形式,内容涉及@RequestMapping注解的原理。html

实际案例

1、基本描述java

项目甲中有多个模块,其中就有模块A和B。(这里的模块指的是Maven的多模块子项目),项目乙、丙、丁能够引用模块A来访问独立部署的模块Bspring

模块A  => 关于与模块B通讯的协议定义api

模块B  => 能够独立部署的项目app

其中模块A中定义了一个FeignClient的接口用于访问模块B的服务。ide

@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。测试

2、问题出现url

按理说,模块B确定有一个Controller来处理这个“/som-url”的请求。因而我全局搜索了模块B,发现怎么找也找不到“/some-url”。spa

后来发现模块B中依赖于模块A,且有一个类实现了XXXService这个接口。这个类叫XXXServiceImpl。这个类既不叫xxxController,也不带@Controller注解。.net

@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。

3、个人一个猜测

我想有没有可能实现类继承了接口方法上的注解,因而我看了下@PostMapping的元注解,发现并无@Inherited的注解。我也尝试打印了XXXServiceImpl类someOperation方法上的注解,发现确实没有。

4、问题解答

XXXServiceImpl确实充当了Controller。关键在于针对@RequestMapping的扫描,会向上扫描类的全部父类和接口。只要在接口或者父类的上方法上发现了@RequestMapping的注解,就认定这个方法是某个请求关联的处理方法。

简化版本

可能有人不是很理解前面的实际案例,这里提供一个简化的版本。

1、新建一个只带Web的Spring Boot项目

 

2、定义一个接口

这个接口有一个方法,带有@GetMapping注解。

public interface ControllerInterface {
    @GetMapping("/hello") String hello(); }

3、添加实现类

@RequestMapping
@ResponseBody
@Service
public class ControllerInterfaceImpl implements ControllerInterface { @Override public String hello() { return "hello world"; } }

4、启动并测试

启动项目,访问http://localhost:8080/hello

发现确实能够访问。实际上组合方式还有不少,你能够把注解都写在接口上。

 

@RequestMapping原理简述

1、搜寻处理类

一个类上若是有@Controller或者@ReqeustMapping注解,会被认定为是请求的Handler。

2、搜寻处理方法

找处处理类后,第二步就是在处理类中查找处理方法,即标注有@RequestMapping(或者其余变种)的方法,注意这里扫描的过程当中,会向上扫描父类或者接口是否带有此注解。这个操做由HandlerMethodSelector来完成(Spring 4有这个类,后面的版本可能名称有所变动)

3、整合URL生成RequestMappingInfo

若是处理类上有@RequestMpping注解,且有设置url,则会将类上和方法上的URL拼接起来。最终造成一个RequestMappingInfo。

4、生成映射关系

每一个RequestMappingInfo会映射到一个处理方法HandlerMethod。

参考资料

1.@RestMapping原理讲解-1

2.HandlerMethodSelector

相关文章
相关标签/搜索