forward()
和 sendRedirect()
之间的概念区别是什么?
请您参考如下方法:
在 Web 开发领域,术语“重定向”是向客户端发送仅包含 Location
的空 HTTP 响应的行为。 header 包含客户端必须向其发送全新 GET 请求的新 URL。所以基本上:
- 客户端向
some.jsp
发送 HTTP 请求. - 服务器发回 HTTP 响应
Location: other.jsp
标题 - 客户端向
other.jsp
发送 HTTP 请求(这会反射(reflect)在浏览器地址栏中!) - 服务器发送回内容为
other.jsp
的 HTTP 响应.
您可以使用网络浏览器的内置/插件开发工具集来跟踪它。在 Chrome/IE9/Firebug 中按 F12 并检查“网络”部分即可看到它。
以上正是由 sendRedirect("other.jsp")
实现的。 RequestDispatcher#forward()
不发送重定向。相反,它使用目标页面的内容作为 HTTP 响应。
- 客户端向
some.jsp
发送 HTTP 请求. - 服务器发送回内容为
other.jsp
的 HTTP 响应.
但是,由于原始 HTTP 请求是 some.jsp
,浏览器地址栏中的URL保持不变。此外,在 some.jsp
后面的 Controller 中设置的任何请求属性将于 other.jsp
提供。在重定向期间不会发生这种情况,因为您基本上是在强制客户端在 other.jsp
上创建新 HTTP 请求。 ,特此放弃 some.jsp
上的原始请求包括它的所有属性。
RequestDispatcher
在 MVC 范例中和/或当您想要隐藏 JSP 以防止直接访问时非常有用。您可以将 JSP 放在 /WEB-INF
中文件夹并使用 Servlet
它控制、预处理和后处理请求。 /WEB-INF
中的 JSP文件夹无法通过 URL 直接访问,但 Servlet
可以使用 RequestDispatcher#forward()
访问它们.
例如,您可以在 /WEB-INF/login.jsp
中拥有一个 JSP 文件。和一个 LoginServlet
映射到 url-pattern
的/login
。当您调用http://example.com/context/login
时,然后是 servlet 的 doGet()
将被调用。您可以在其中进行任何预处理操作,最后转发请求,例如:
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
当您提交表单时,您通常希望使用POST
:
<form action="login" method="post">
这样 servlet 的 doPost()
将被调用,您可以在其中执行任何后处理操作(例如验证、业务逻辑、登录用户等)。
如果有任何错误,那么您通常希望将请求转发回同一页面,并在输入字段旁边显示错误等。您可以使用 RequestDispatcher
为此。
如果 POST
成功后,您通常需要重定向请求,以便当用户刷新请求(例如按 F5 或返回历史记录)时不会重新提交请求。
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login.
} else {
request.setAttribute("error", "Unknown login, please try again."); // Set error.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error.
}
重定向因此指示客户端触发新的 GET
对给定 URL 的请求。刷新请求只会刷新重定向的请求,而不刷新初始请求。这将避免“双重提交”以及困惑和不良的用户体验。这也称为 POST-Redirect-GET
pattern .