在 Spring MVC 的 servlet 映射中,如何映射 url 模式目录的根目录?
Posted
技术标签:
【中文标题】在 Spring MVC 的 servlet 映射中,如何映射 url 模式目录的根目录?【英文标题】:In a servlet mapping in Spring MVC how do I map the root of a url pattern directory? 【发布时间】:2012-11-04 13:05:35 【问题描述】:<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
如果我点击 /test/page,以上将起作用。但是,点击 /test 或 /test/ 将不起作用。我用的是Spring MVC,我的请求映射如下:
@RequestMapping(value = "","/")
编辑:
我正在使用独立项目进行验证,但这似乎是 Spring 的 UrlPathHelper 的错误。当同时存在上下文和 servlet 路径时,以下方法返回不正确的路径,并且您在没有尾部斜杠的情况下点击了 servlet。
public String getPathWithinApplication(HttpServletRequest request)
String contextPath = getContextPath(request);
String requestUri = getRequestUri(request);
if (StringUtils.startsWithIgnoreCase(requestUri, contextPath))
// Normal case: URI contains context path.
String path = requestUri.substring(contextPath.length());
return (StringUtils.hasText(path) ? path : "/");
else
// Special case: rather unusual.
return requestUri;
例如,假设我有一个“admin”上下文和以下 servlet 映射:
<servlet-mapping>
<servlet-name>usersServlet</servlet-name>
<url-pattern>/users/*</url-pattern>
</servlet-mapping>
现在我的一个控制器中有一个请求映射,如下所示:
@RequestMapping(value = "","/")
如果我点击 /admin/users 它将不起作用。但是,如果我点击 /admin/users/ 它将起作用。现在,如果我将请求映射更改为以下内容,那么它们都可以工作:
@RequestMapping(value = "/users","/")
但是,现在 URL /admin/users/users 也可以使用(这不是我想要的)。
【问题讨论】:
【参考方案1】:首先,将 dispatcher servlet 映射到“/”和“/*”之间的区别。 有区别!
当映射到“/*”时,所有 URL 请求(包括类似“/WEB-INF/jsp/.../index.jsp”的东西)都映射到调度器 servlet。
其次,当使用 Spring + Tiles 并在您的 tile 定义中返回一些 JSP 时,它被视为内部转发请求,并由与原始请求相同的 servlet 处理。 在我的示例中,我调用根 URL“/”,它被 home() 方法正确捕获,然后由 Tiles 转发到“index.jsp”,再次由 Dispatcher Servlet 处理。 显然,dispatcher servlet 无法处理“index.jsp”,因为它没有控制器。
是的,它很丑,但看起来它就是这样工作的。
所以,到目前为止,我找到的唯一解决方案是:将 web.xml 中的“/*”改回“/”。我猜想,Tomcat 的 jsp servlet 会正确呈现 JSP,而不是调度程序 servlet。 不幸的是,这个修复会破坏 Spring 的 ROOT URL 调度,所以你需要暂时放弃使用 ROOT URL + Tiles 的想法。
请注意,当使用“/*”时,在 web.xml 中添加显式 servlet 映射“.jsp -> Tomcat jsp 没有帮助,而且很糟糕。
问题还是没有解决。
这也是 Spring MVC 3.0 中的问题
【讨论】:
问题不在于使用根路径。如果我使用根路径,那么我总是使用<url-pattern>/</url-pattern>
和@RequestMapping(value = "","/")
。我从来没有遇到过这个问题,我使用的是 Tiles 2 和 Spring MVC 3。问题在于首先指定一个 servlet 路径。每当您指定 servlet 路径信息时,Spring 的请求映射就是之后的一切。所以从技术上讲,相同的请求映射应该可以工作,因为它是 servlet 路径的根。然而,情况似乎并非如此。【参考方案2】:
我的设置通常如下所示:
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
控制器,我假设您想平等地处理 /test
和 /test/
:
@Controller
public class MyController
@RequestMapping("/test")
public String test()
return "redirect:/welcome";
@RequestMapping("/test/")
public String test()
return "redirect:/welcome";
@RequestMapping("/welcome")
public void test(ModelMap model)
// do your stuff
这样的设置会导致DispatcherServlet
处理对*.css
和*.js
文件的请求,这在大多数情况下是不需要的。我认为这是 Bhavik 描述的问题。对于这些资源,您可以像这样使用 ResourceController:
<mvc:resources mapping="/css/**" location="/resources/css/" />
<mvc:resources mapping="/js/**" location="/resources/js/" />
来自/resources/css
和/resources/js
的文件将被提供,而不会强迫您编写额外的控制器。
【讨论】:
问题是关于根控制器的,更多参考请阅读我下面的答案 感谢您对服务资源的评论。 Here are the offical Spring docs.【参考方案3】:Yevgeniy 是正确的,但是如果您的 DispatcherServlet 正在接管默认 servlet,您必须将其添加到您的 web.xml:
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
【讨论】:
【参考方案4】:一种不接触 web.xml 文件的方法是将地图设置为默认的欢迎文件路径。
@RequestMapping("/index.html")
【讨论】:
【参考方案5】:在我的例子中,每个 url 都在工作除了根“/”url。
问题是我没有删除我项目的 webapp 根文件夹中的 index.htm
文件。
【讨论】:
以上是关于在 Spring MVC 的 servlet 映射中,如何映射 url 模式目录的根目录?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring MVC 中将请求映射到 HTML 文件?
如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?