如何将servlet映射到/ *,它以无限循环失败并最终失败StackOverflowError

时间:2012-12-18 14:17:52

标签: servlets mapping infinite-loop

我想将我的servlet映射到/*,但它失败并且无限循环。

<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>my.HelloServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

java代码是:

public class HelloServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response){
        request.getRequestDispatcher("/WEB-INF/jsps/hello.jsp").forward(request, response);
    }

}

如果我映射到/hello,一切正常。

HelloServlet映射到/*时,它也会在RequestDispatcher#forward()上调用并导致无限循环。

这是如何引起的?如何解决?

2 个答案:

答案 0 :(得分:4)

这是不可能的。 JSP实际上应该调用容器的内置JspServlet。但是,由webapp定义的/*映射具有更高的优先级。

您需要将servlet映射到更具体的URL模式,如/pages/*,并创建一个servlet过滤器,将非静态请求转发给该servlet。是的,/*也涵盖了非静态请求(图像/ CSS / JS文件),但它们根本不应由servlet处理。

假设您拥有/resources文件夹中的所有静态资源,则应执行以下操作:

<filter>
    <filter-name>filter</filter-name>
    <filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>controller</servlet-name>
    <servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>controller</servlet-name>
    <url-pattern>/pages/*</url-pattern>
</servlet-mapping>

在过滤器doFilter()中使用以下内容:

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

if (path.startsWith("/resources")) {
    chain.doFilter(request, response); // Goes to container's own default servlet.
} else {
    request.getRequestDispatcher("/pages" + uri).forward(request, response); // Goes to controller servlet.
}

这完全透明地进行,而不对URL中的/pages进行任何更改。 JSP的转发不会触发过滤器或servlet。默认情况下,过滤器不会启动前进,并且JSP前向路径不再与控制器servlet的URL模式匹配。

或者,如果您有自己的默认servlet实现,那么您可以将servlet映射到/,并且如果请求不适用作前端控制器请求,则将其委派给默认servlet。这就是Spring MVC在幕后所做的事情。然而,创建默认servlet并不是一项简单的任务,因为它应该能够响应条件请求,缓存请求,流请求,恢复请求,目录列表请求,等等。

另见:

答案 1 :(得分:-1)

这可能与Servlet Filter going in infinite loop when FORWARD used in mapping in JSF

重复

否则应检查JSP包含的内容,可能是它对css或图像文件的请求可能导致此行为。也建议在没有通配符的情况下尝试。