带有网址模式“ / *”的servlet映射中的StackOverflowError

nog*_*bag 5 seo tomcat servlets servlet-filters

我有一组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>
Run Code Online (Sandbox Code Playgroud)

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

我遇到了这里发布的另一个解决方案(易于使用的URL):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>
Run Code Online (Sandbox Code Playgroud)

现在的问题是我不想点击以下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>
Run Code Online (Sandbox Code Playgroud)

但这会导致无限循环:

    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)
Run Code Online (Sandbox Code Playgroud)

我不确定该如何解决。有任何想法吗?

Bal*_*usC 6

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

毕竟,您根本不应该使用/*servlet。它仅在servlet过滤器上有意义。将Servlet映射放回更特定的URL模式,并创建一个过滤器,/*必要时将其转发到所需的servlet。您当然不希望Servlet处理例如images / 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);
}
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • 如果唯一的功能要求是“漂亮的URL”而不是“前端控制器”,那么可以单独使用过滤器,可以。甚至还有第三方库,例如[Tuckey's URLRewriteFilter](http://code.google.com/p/urlrewritefilter/)和[Rewrite](http://ocpsoft.org/rewrite/),它们类似于Apache HTTPD的`mod_rewrite`。但是,如果您实际上需要前端控制器(该前端控制器还将处理HTTP请求预处理和后处理),则最好将其保留在servlet中。 (2认同)