【源碼跟蹤】動態注冊的Controller的@RequestMapping的方法 能訪問,但返回404


動態注冊的Controller的@RequestMapping的方法 能訪問(已經執行進了controller的那些方法),但前端收不到結果,返回404。

 

調試跟蹤源碼發現:

1、controller的那些方法返回結果,

在 org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite 的 selectHandler 會找一個合適的handle對返回結果進行處理。

 我們可以看到 會循環15個 handles,通過 下面語句去找 哪個handle處理更合適:

handler.supportsReturnType(returnType)

我們期望 由 RequestResponseBodyMethodProcessor 這個handle 來處理我們的返回結果,它會把返回結果轉成 字符串 返回給前端。

然后此處最終選擇的是 ModelAttributeMethodProcessor 這 handle。

我們返回的是一個vo,ModelAttributeMethodProcessor  無法處理,報錯 404。

 

2、為什么 handle 為 RequestResponseBodyMethodProcessor 時,

handler.supportsReturnType(returnType) 為false呢?

進入RequestResponseBodyMethodProcessor 的 supportsReturnType 方法,繼續研究:

public boolean supportsReturnType(MethodParameter returnType) {
        return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||   //這句是看看該Controller的Class是否有@ResponseBody
                returnType.hasMethodAnnotation(ResponseBody.class));                                          //這句是看看該方法上是否有@ResponseBody
    }

Controller的class上我們不可能定義@ResponseBody(該注解不能直接定義在Class上),

我們的方法上一般也不會寫上@ResponseBody(有@RestController,默認就是@ResponseBody,所以不會額外加 ),

這樣handler.supportsReturnType(returnType) 自然不會為true,也就不會使用 RequestResponseBodyMethodProcessor 來處理返回結果。

 

解決:

在動態注冊的Controller的@RequestMapping的方法上加上 @ResponseBody, OK,問題解決。

 

擴展:

那些非動態注冊的Controller在class我們一般會定義 @RestController,

默認就是@ResponseBody方式返回結果,

所以方法上也不會加上@ResponseBody。

那為什么這些方法會被 RequestResponseBodyMethodProcessor 正常處理呢?

 

這就是回頭看 RequestResponseBodyMethodProcessor 的 supportsReturnType 方法了。

該方法第一句是判斷 Class是否有@ResponseBody。

@RestController 包含了 @ResponseBody,所以這里會為 true,所以 supportsReturnType 自然就會返回true了。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM