带有 url 模式“/ *”的 servlet 映射中的 ***Error

Posted

技术标签:

【中文标题】带有 url 模式“/ *”的 servlet 映射中的 ***Error【英文标题】:***Error in servlet mapping with url-pattern "/*" 【发布时间】:2012-05-11 06:01:17 【问题描述】:

我有一组 JSP 页面,我想隐藏 .jsp 扩展名(经过一番研究,这似乎对 SEO 有好处)。

我遇到的一个解决方案如下:

<servlet>
    <servlet-name>mypage</servlet-name>
    <jsp-file>/some-page.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>mypage</servlet-name>
    <url-pattern>/some-page</url-pattern>
</servlet-mapping>

虽然这可行,但我相信我必须为我网站上的每个 jsp 页面设置此映射。

我在这里发现了另一个解决方案(简单友好的 URL):Hidden features of JSP/Servlet

... 它使用一个简单的 servlet 来转发请求。在我的 web.xml 中,我有以下内容并且工作正常:

<servlet>
    <servlet-name>MyServletName</servlet-name>
    <servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServletName</servlet-name>
    <url-pattern>/myservlet/*</url-pattern>
</servlet-mapping>

现在的问题是我不想点击 URL:www.mydomain.com/myservlet/some-page

我想使用网址:www.mydomain.com/some-page

所以我把 url-pattern 改成了“/*”

<servlet>
    <servlet-name>MyServletName</servlet-name>
    <servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServletName</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

但这会导致无限循环:

    Exception in thread "http-bio-8080-exec-1" java.lang.***Error
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:219)
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            .
            .
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
            at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
            at myservlets.PrettyUrlServlet.doGet(PrettyUrlServlet.java:22)

我不确定如何解决。有什么想法吗?

【问题讨论】:

【参考方案1】:

映射到/* 的servlet 也将在RequestDispatcher#forward() 调用上运行。因此,如果您在该 servlet 中执行转发,它每次都会在无限循环中调用自己。这解释了***Error

毕竟,您根本不应该将/* 用于servlet。它只对 servlet 过滤器有意义。将 servlet 映射放回更具体的 URL 模式,并在 /* 上创建一个过滤器,在必要时转发到所需的 servlet。您当然不想让 servlet 来处理例如图像/CSS/JS 文件。假设它们都放在/resources 文件夹中,并且你的前端控制器映射到/myservlet/*,那么在doFilter() 中执行以下工作:

HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/resources/")) 
    // Just let container's default servlet do its job.
    chain.doFilter(request, response);

else 
    // Delegate to your front controller.
    request.getRequestDispatcher("/myservlet" + path).forward(request, response);

另见:

URL mapping in Tomcat to FrontController servlet

【讨论】:

愚蠢的问题。我什至首先需要 servlet 吗?过滤器可以直接转发到jsp页面吗? 如果唯一的功能需求是“漂亮的 URL”而不是“前端控制器”,那么您可以单独使用过滤器,是的。甚至还有 3rd 方库,例如 Tuckey's URLRewriteFilter 和 Rewrite,它们类似于 Apache HTTPD 的 mod_rewrite。但是如果你真的需要一个前端控制器(它也会处理 HTTP 请求的预处理和后处理),最好把它放在 servlet 中。【参考方案2】:

你应该使用UrlRewriteFilter

你可以在你的配置文件(urlrewrite.xml)上使用这样的一些:

<rule>
    <from>/products/([a-zA-Z0-9._%]+)</from>
    <to>/products.jsp?id=$1</to>
</rule>

UrlRewriteFilter 在评论中,但我认为它应该是一个独立的答案。

【讨论】:

以上是关于带有 url 模式“/ *”的 servlet 映射中的 ***Error的主要内容,如果未能解决你的问题,请参考以下文章

Servlet 映射:带有斜杠的 URL 的 url-pattern

简单映射器模式 C# 代码生成模板

带有 RESTFul Urls 的 Servlet 应用程序

此 URL 不支持带有简单 servlet 的 HTTP 方法 GET

Servlet映射的过程

servlet 映射 url 模式中 / 和 /* 之间的区别