StackOverflowError in servlet mapping with url-pattern "/*"



我有一组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):JSP/Servlet的隐藏功能

。它使用一个简单的 servlet 来转发请求。 在我的网络中.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>

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

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

所以我将网址模式更改为"/*"

<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.StackOverflowError
            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)

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

映射

/*上的 servlet 也将在RequestDispatcher#forward()调用上运行。因此,如果你在该 servlet 中执行前向,它每次都会在无限循环中调用自己。这就解释了StackOverflowError.

毕竟,您根本不应该将/*用于 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);
}

另请参阅:

  • Tomcat 中的 URL 映射到 FrontController servlet

你应该使用 UrlRewriteFilter

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

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

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

最新更新