当使用多个 Controller 类和 DefaultAnnotationHandlerMapping 时,我们在使用 Spring Portlet MVC 3.1 时遇到了问题。
背景
- 我们正在使用带有渲染和操作阶段注释的 Spring Portlet MVC 3.1
- 我们正在使用 JBoss EPP 5.1.1
问题
- 对于带有参数的 Portlet 渲染请求,Portlet 中渲染的页面不正确
原因
- Spring Portlet MVC 对 @RenderMapping 使用的方法与具有正确注释的预期方法不同
技术分析
我们所有的 Controller 都包含 @RenderMapping 和 @ActionMapping 注释,并且都具有“params”参数,以确保根据 portlet URL 中设置的参数调用预期的方法。对于默认渲染,我们有一个带有 @RenderMapping 注释且不带“params”参数的方法,当请求不包含参数时,我们使用该方法渲染空白 JSP。
根据对书中第 7 章和第 8 章的阅读,我们了解到 Dispatcher Portlet 尝试为传入请求获取适当的处理程序映射,并将其发送到配置的 Controller bean 中的适当方法。我们的假设是,只有在检查 Controller 中没有其他方法具有与特定请求参数匹配的注释后,才会调用默认的 @RenderMapping 注释(不带参数)。
但是,我们经过调试发现这个假设是不正确的。 DefaultAnnotationHandlerMapping 似乎以某种预定义的顺序遍历 Controller bean 中的可用注释列表。这意味着,如果具有默认 @RenderMapping 注释(不带参数)的 Controller bean 出现在列表之前,则将调用具有默认 @RenderMapping 注释(不带参数)的方法,而不是调用列表下方的正确方法.
明显错误
我们正在Windows环境中开发并部署到Linux环境。在 Windows 中,我们看到处理程序按字母顺序循环遍历 Controller bean,因此我们最初通过在 Controller 中添加 @RenderMapping 注解的方法来解决我们的问题,该方法在 Controller 中没有参数,并且 bean 名称最接近“Z”。
然而,在 Linux 中, Controller Bean 的检测顺序似乎不同。我在下面附上了 Spring 日志来强调这个问题。无参数 @RenderMapping 注释位于 YourDetailsController 中,正如您在 Windows 日志中看到的那样,它出现在列表的最后,而在 Linux 中则不然。这意味着,如果我们尝试访问列表中 YourDetailsController 之后出现的 Controller 之一,我们最终总是会遇到 YourDetailsController 中的 no params 注释。
问题
- 我们的假设是否正确?
- 我们的诊断是否反射(reflect)了预期的行为?或者是 Spring Portlet MVC 的一个错误?
- 是否有不同的方法来扫描注释以形成处理程序映射 bean 列表?
- 使用 xml 配置(而不是注释)可以解决我们的问题吗?
- 我们是否能够定义多个处理程序映射和顺序,以便默认处理程序映射成为调度程序 portlet 使用的最后一个处理程序映射?
如果您对此问题有任何想法或建议,我们将不胜感激。
最佳答案
迈克.我遇到了完全相同的问题。我正在使用 JDK 7、Spring 3.1.1.RELEASE 和 Hibernate 4.1.3.Final。我正在 Linux (Fedora) 上进行开发并在 Linux(Fedora 和 SL)上进行部署。
我被困住了,因为我确信各个部分( Controller )一次只能工作一个,但对渲染请求的调用一起被随机忽略。有时更改某些内容会使渲染请求再次正常工作,但它们从未一起工作。
正如 Walter 所建议的,当我在自己的包中隔离仅包含默认渲染请求的 Controller 时,仅在其中保留默认渲染请求(在我有删除/查看请求之前),并在 portlet 的中分离 Controller 的扫描在其他两个之后扫描默认 Controller 的 XML 配置,突然间一切都变得很神奇。
看看这个错误是否存在于 Spring 跟踪器中会很有趣......
关于spring-mvc - Spring portlet MVC 3.1 如何确定使用多个 Controller 呈现哪个带注释的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10432321/