动态注册的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了。

