【源码跟踪】动态注册的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