【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

相關文章
相關標籤/搜索