我正在尝试将 servlet 响应转发到同一页面(又名:前一页,或“servlet”调用者)。
我已经看到很多答案(比如 这个 和 这个)但仍然无法正常工作。
我通常执行以下操作将 servlet 的响应重定向到另一个页面:
request.getRequestDispatcher("MyNewPage").forward(request, response);
但是我尝试将“MyNewPage”更改为我认为是解决方案的其他选项:
request.getRequestDispatcher((String)request.getAttribute("javax.servlet.forward.request_uri")).forward(request, response);
request.getRequestDispatcher(request.getHeader("referer")).forward(request, response);
和其他选项,无法使其工作。
我究竟做错了什么?
原文由 Christian Vielma 发布,翻译遵循 CC BY-SA 4.0 许可协议
首先
request.getHeader("referer")
返回一个完整的 URL,但你必须剥离http://server[:port]/
因为你传递给 request.getRequestDispatcher() 的内容被添加到应用程序上下文中,如下所示:这不是您想要的,因为您只需要将以下内容传递给调度程序方法:
如果我们从头开始,第一个请求从这个 URL 开始:
转发有效,但第二次向 Servlet 发出请求时,Servlet 将转发给自己。因此,您将进入一个 Servlet 调用自身的循环。为什么会这样?由于你是从表单中调用Servlet的,这就意味着你的浏览器地址栏中的URL地址会在第一次请求后变为你的Servlet的URL地址。
Servlet 会将请求转发回 JSP 页面,浏览器将仅显示该页面,但浏览器地址框中的 URL 仍将是包含 Servlet 的网址,而不是 JSP 页面:
因此,下次您点击提交时,Servlet 将尝试将请求转发给自己。如果我是你,我会使用重定向。它似乎更适合您的目的:
这将始终更改浏览器地址框中的 URL 并防止您的 Servlet 循环。这将对请求参数产生影响,但您始终可以将它们添加到重定向 URL(如果它不是敏感信息)或将它们存储在会话中,直到您在重定向将发出的下一个第一个请求中检索它们。
像 JSF 这样的框架可以使您免于这些问题。
允许您使用 forward 的最简单的解决方案是在表单中保留调用 Servlet 的 JSP(viewid) 而不是使用 request.getHeader(“referer”) 的隐藏参数。不过,您将需要检查循环,因为有人可能故意更改该值以强制您的 Servlet 容器循环并最终使 VM 崩溃。但是你可以只使用一个请求属性来记录链中的前一个请求,如果它是相同的,你会回应一个错误。因此,在 servlet 中,您将使用隐藏字段值来决定转发到的位置:
在你的 JSP 中:
我认为这可以满足您的要求。