首先request.getHeader("referer")
返回一个完整的 URL,但你必须去掉它,http://server[:port]/
因为你传递给 request.getRequestDispatcher() 的内容被添加到应用程序上下文中,如下所示:
/NameOfApp/http:/localhost:8084/NameOfApp/test.jsp
这不是您想要的,因为您只需要将以下内容传递给调度程序方法:
test.jsp
如果我们从头开始,第一个请求就从这个 URL 开始:
http://localhost:8084/RequestDispatcher/test.jsp
转发有效,但是当您第二次向 Servlet 发出请求时,Servlet 将转发给自己。因此,您将进入一个循环,其中 Servlet 调用自身。为什么会发生这种情况?由于您从表单中调用 Servlet,这意味着您的浏览器地址框中的 URL 地址将在第一次请求后更改为您的 Servlet 的地址。
http://localhost:8084/RequestDispatcher/NewServlet
Servlet 会将请求转发回 JSP 页面,浏览器将仅显示该请求,但浏览器地址框中的 URL 仍将是包含 Servlet 而不是 JSP 页面的 URL:
http://localhost:8084/RequestDispatcher/NewServlet
因此,下次您点击提交时,Servlet 将尝试将请求转发给它自己。如果我是你,我会使用重定向。它似乎更适合您的目的:
response.sendRedirect(request.getHeader("referer"));
这将始终更改浏览器地址框中的 URL 并防止 Servlet 循环。这将对请求参数产生影响,但您始终可以将它们添加到重定向 URL(如果它不是敏感信息)或将它们存储在会话中,直到您在重定向将发出的下一个第一个请求中检索它们。
像 JSF 这样的框架可以帮助您避免这些问题。
允许您使用 forward 的最简单的解决方案是保留调用 Servlet 的 JSP(viewid) 的表单中的隐藏参数,而不是使用 request.getHeader("referer")。不过,您需要检查循环,因为有人可能会故意更改该值以强制您的 Servlet 容器循环并最终使 VM 崩溃。但是您可以只使用请求属性来记录链中的前一个请求,如果相同,则以错误响应。因此,在 servlet 中,您将使用隐藏字段值来决定转发到的位置:
request.getRequestDispatcher(request.getParameter("viewid")).forward(request, response);
在您的 JSP 中:
<input type="hidden" name="viewid" value="test.jsp">
我认为这将满足您的要求。