gpt4 book ai didi

servlets - 如何将 servlet 映射到/*,它会因无限循环而失败并最终导致 StackOverflowError

转载 作者:行者123 更新时间:2023-12-04 03:02:25 27 4
gpt4 key购买 nike

我想将我的 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() 上被调用并导致无限循环。

这是怎么引起的,我该如何解决?

最佳答案

这是不可能的。 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 转发路径不再匹配 Controller servlet 的 URL 模式。

或者,如果您有自己的默认 servlet 实现,那么您可以将 servlet 映射到 / 并让它在请求不适用于前端 Controller 请求时委托(delegate)给默认 servlet。这就是 Spring MVC 在幕后所做的事情。然而,创建默认 servlet 并非易事,因为它应该能够响应条件请求、缓存请求、流式请求、恢复请求、目录列表请求等等。

另见:

关于servlets - 如何将 servlet 映射到/*,它会因无限循环而失败并最终导致 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13934909/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com