動態注冊的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了。

