我在 Servlet 环境中使用 Spring MVC 开发已经有一段时间了,主要是在 Spring 3.1.x 和 3.2.x 上,但最近将工作转移到了一家使用 Spring 3.0.6 混合使用 Portlet 和 Servlet 的公司。
首先,DefaultAnnotationHandlerMapping 似乎有两个版本,一个用于Portlets,一个用于Servlets。我对 Portlets 的有限了解让我相信它们只是 Servlet 的扩展,所以我可以模糊地理解需要有两个单独的 HandlerMapping,一个用于处理通用 Servlet,另一个用于处理 Portlest 的细节。让我感到震惊的是,他们每个人在处理 @RequestMapping 注释的方式以及我的新雇主如何选择设置方面似乎表现不同。
过去,我为整个应用程序使用了一个 DispatchHandler。我知道您可以拥有多个 DispatchHandler,但我从未看到过隔离子上下文 XML 的好处。无论如何,在过去我会将 DispatchHandler 映射到“/”,然后每个 Controller 使用 @RequestMapping("/someUrl") 在顶部设置一个映射,然后在每个处理程序方法上设置另一个 @RequestMapping,进一步扩展 URL 映射。所以,从浏览器我会得到类似的东西:
其中第一个“/myWar”映射到 WAR 部署,下一个“/”映射到 DispatchServlet,“/myController”是控制器的映射,之后的任何内容都使用 URL 签名、请求的组合匹配到某个方法方法、参数等
现在让我们评估一下我在新公司看到的情况。首先,每个控制器都有自己的 DispatchServlet,因此定义了大约 20-30 个 DispatchServlet,它们都映射了不同的基本 URI,一些具有相同的基本应用程序上下文 XML,一些具有不同的,都使用来自 ContextLoaderListener 的相同应用程序上下文。随后的每个 DispatchServlet 的路径都与其“映射”控制器上的 @RequestMapping 相同,因此在上面的示例中,DispatchServlet 将具有路径“/myController”,而控制器将具有 @RequestMapping(“/myController”)。最重要的是,在控制器的方法级别,@RequestMapping 上指定的值似乎完全忽略了应用于它的任何附加路径。
因此,例如,如果我有一个带有 @RequestMapping("/myController") 的控制器,然后是带有 @RequestMapping("/edit") 的方法,点击 URL http://somehost.com/myWar/myContoller/edit给我一个 404。但是,如果我将方法级别的 @RequestMapping 更改为 @RequestMapping(parameter="actionMethod=edit"),并将 URL 更改为http://somehost.com/myWar/myController?actionMethod=edit,它地图很好,我得到了我的页面。此外,如果我将我的方法级别 @RequestMapping 更改为 @RequestMapping(value="/edit",params="actionMethod=view") 既不是http://somehost.com/myWar/myController?actionMethod=edit也不是http:/ /somehost.com/myWar/myController/edit?actionMethod=edit工作。问题是,现在要在方法级别获得除默认映射之外的任何内容,需要我使用“?actionMethod=edit”,而不是简单地使用添加的路径扩展 URI。此外,它使我无法使用 RESTful 方法,因为现在我无法定义 @RequestMapping("/somePath/{id}") 之类的东西。
我脑子里有很多困惑,比如为什么 web.xml 中的 DispatchServlet 映射与控制器 @RequestMapping 重叠,以及当我将 value 属性设置为有效的 URI 映射时,为什么控制器方法级别的 @RequestMapping 不起作用,但是当我设置一些参数映射时工作正常吗?
哦,很抱歉发布了这么长的帖子。我只是想更好地了解这里发生的事情,以便我可以用智能的方法来处理它,或者回到我的新团队并说“这应该改变,这就是原因”。如果有帮助,我可以用一些简化的代码示例来扩展这个冗长的问题。