在 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 中的问题

【讨论】:

问题不在于使用根路径。如果我使用根路径,那么我总是使用&lt;url-pattern&gt;/&lt;/url-pattern&gt;@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

是啥导致此 Spring MVC 应用程序中的映射失败?

如何将 Spring MVC 控制器映射到带有和不带有斜杠的 uri?

Google-GSON 的 Spring MVC 映射视图?

Google-GSON 的 Spring MVC 映射视图?