6

我正在尝试将 servlet 响应转发到它来自时的同一页面(又名:上一页,或“servlet”调用者)。

我已经看到了很多答案(例如thisthis),但仍然无法使其发挥作用。

我通常执行以下操作来将 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);

和其他选项,不能让它工作。

我究竟做错了什么?

4

2 回答 2

17

首先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">

我认为这将满足您的要求。

于 2012-08-17T22:56:35.840 回答
1

更好的策略是在请求中添加调用者属性。这样在处理完被调用者 servlet 后,它就可以将其请求转发回调用者。

就像是,

呼叫者

request.setAttribute("caller", "/page/Foo.jsp");

被调用者

String uri = (String)request.getAttribute("caller");
getServletContext().getRequestDispatcher(uri).forward(request, response);

或者您可以尝试在会话中添加呼叫者并在转发后将其删除。

于 2014-06-21T09:36:26.720 回答