转发 Forward
Api 详解
- 转发
Forward
是通过RequestDispatcher
对象的forward()
方法实现。RequestDispatcher 可以通过以下两种方式获取:
- HttpServletRequest 的
getRequestDispatcher()
方法获得 - ServletContext 的
getRequestDispatcher()
方法获取
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/downloadServlet");
RequestDispatcher dispatcher = req.getRequestDispatcher("/downloadServlet");
-
getRequestDispatcher()
方法的参数必须为以/
开始,/
表示本 Web 应用程序的根路径。如果要跳转到Servlet为 http://IP:PORT/servlet/RequestServlet。则参数应该为/servlet/RequestServlet
。 -
跳转在服务器,地址栏不变。当使用 Forward 形式跳转 Servlet 时,地址栏会显示跳转前的 Servlet 访问地址。因为该跳转是在服务器端实现,客户端浏览器并不知道该跳转动作,也就是说 Forward 跳转对客户端浏览器是透明的
-
Forward是最常用的方式。在struts等框架中,都是用Servlet来处理用户请求,把结果通过 request.setAttribute() 放到 request 中,然后 Forward 到JSP显示
-
当执行 Forward 动作的时候不能有任何输出到达客户端,否则会抛出
illegalStateException
。
java.lang.IllegalStateException: Cannot forward after response has been committed
-
转发:同一个HttpServletRequest, 这时web 数据的共享要使用 Request 域即可
-
代码
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("在 Forward 之前不能向客户端输出结果");
writer.flush();
// 跳转到文件下载的 Servlet
// RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/downloadServlet")
RequestDispatcher dispatcher = req.getRequestDispatcher("/downloadServlet");
dispatcher.forward(req, resp);
}
}
重定向 Redirect
原理
- 重定向是利用服务器返回的状态来实现的。
- 客户端浏览器请求服务器的时候,服务器端会返回一个状态码。服务器端通过 HttpServletResponse 的
setStatus()
方式设置状态码。 - 如果服务器返回
301 或者 302
,则浏览器会到新的网址重新请求该资源。
- 状态码简单列表如下如下
状态码 | 解释 |
---|---|
100 ~ 199 | 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 |
200 ~ 299 | 表示成功接收请求,已经完成整个过程。如200 |
300 ~ 399 | 为完成请求,客户端需要进一步细化请求。例如,请求的资源已经移动到一个新的地址。常用 301、302、307、304 |
400 ~ 499 | 客户端的请求有错误。常用404 |
500 ~ 599 | 服务器端出现错误。常用500 |
- 301 、302都表示重定向,区别是 301是永久性重定向,302是临时性重定向。下面的代码将访问该Servlet的请求重定向到另一个网址
response.setStates(301);//设置状态码为301
response.setHeader("Location","http://www.baidu.com") //新网址
实现
-
HttpServletResponse 类中把重用的状态码封装成了静态常量。并且把
setStates()
与setHeader()
方法封装成另一个方法sendRedirect(String location)
,只需要调用sendRedirect()
方法就能实现重定向 -
与转发不同,重定向(Redirect)的跳转是在客户端实现的。实际上客户端浏览器请求了 2 次服务器,第1 次获取重定向的状态码与重定向的网址,第 2 次访问真实地址(类似CORS实现的跨域请求,也是请求两次)
-
重定向:是不同的 HttpServletRequest 对象,每一次访问都会new 一个 HttpServletRequest 对象。这时web数据的共享要使用 session 域 和 context 域
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向到文件下载页面
resp.setStatus(301);
resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
resp.setHeader("Location", "/requestServlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/requestServlet");
}
}
自动刷新(Refresh)
- 自动刷新不仅可以实现一段时间之后自动跳转到另一个页面,还可以实现一段时间之后刷新本页面。Servlet中通过设置HttpServletResponse 对象的Header属性实现自动刷新效果
- 其中 1000 为时间,单位为毫秒
- URL参数指定的网址就是1 秒之后跳转的页面。当URL设置的路径为Servlet自己的路径时,就会每隔1秒钟自动访问页面一次
response.setHeader("Refresh","1000; url=http://www.baidu.com")
- 自动刷新与重定向原理是差不多。如果时间设为 0,把URL设为另一个网址,效果就是重定向
response.setHeader("Refresh","0; url=http://www.baidu.com") // 重定向