接着昨天的来复习,昨天复习到了请求转发和请求重定向。
我们先来讲请求转发:
什么叫请求转发呢,你可以这样理解:一个人想去柜台2办事,但是他必须先经过柜台一拿到章才可以(拿柜台2要用的数据),经过柜台1拿到章后再
"问路"到柜台2,拿到想要的东西,再返回。这整个过程就叫做请求转发。
我们在web.xml配置好路径后在servlet程序中这样配置:
public class Servlet1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求的参数查看 String username = req.getParameter("username"); System.out.println("在Servlet1查看参数; " + username); //使用域数据,传递到Servlet2 req.setAttribute("key","柜台1的章"); //问路 : Servlet2怎么走 /** * 请求转发必须要以/开头 斜杠表示地址 映射到idea代码的web目录 后面就是资源的路径 */ RequestDispatcher requestDispatcher = req.getRequestDispatcher("/serv2"); //走向Servlet2 requestDispatcher.forward(req,resp); } }
其中要注意:
/** * 请求转发 * setAttribute(key,value) : 设置域数据 * getAttribute(key) : 获取域数据 * getRequestDispatcher() : 获取请求转发对象 */
我们在serv2中这样设置:
public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); System.out.println("在Servlet2中查看参数:" + username); //查看柜台1是否盖章 String key = (String) req.getAttribute("key"); System.out.println("柜台1是否有章:" + key); //处理自己的业务 System.out.println("Servlet2处理自己的业务"); } }
在浏览器中输入如下地址并跳转:
http://localhost:8080/demo/serv1?username=123
控制台会这样输出:
在Servlet1查看参数; 123 在Servlet2中查看参数:123 柜台1是否有章:柜台1的章 Servlet2处理自己的业务
我们可以根据代码观察到我们确实在serv1中设置的域数据被serv2获取到了,并且确实跳转到了serv2。
请求转发的特点:
/** * 请求转发 * 特点: * 1、浏览器地址栏没有变化 * 2、他们是一次请求 * 3、他们共享Request域中的数据 * 4、可以转发到 WEB-INF 目录下 */
但是请求转发可能会遇到问题:
比如我们在web中这样设置网页:
路径是 webapp/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> 这是web下的index.html <br/> <a href="a/b/c.html">a/b/c.html</a> <a href="http://localhost:8080/demo/forwardC">请求转发 : a/b/c.html</a> </body> </html>
路径是 webapp/a/b/c.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 这是a下的b下的c.html页面<br/> <a href="../../index.html">跳回首页</a> </body> </html>
web.xml配置好路径/forwardC后这样配置servlet程序:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("经过了ForwardC程序"); req.getRequestDispatcher("/a/b/c.html").forward(req,resp); } }
我们点击第一个a标签后出现这样的页面:
点击跳回首页确实可以跳转到刚刚那个页面,但是如果我们点击请求转发:a/b/c.html再点击跳回首页却出现了网页404。
这是为什么呢?
这是因为我们使用请求转发的时候页面地址是
http://localhost:8080/demo/forwardC
如果这个时候我们再点击页面内的a链接它是这样跳转的:
<a href="../../index.html">跳回首页</a>
就跳转到了:
http://localhost:8080/index.html
这显然是一个错误的资源路径,所以才会出现404问题。
那我们该如何解决这样的问题呢,很简单,只要在webapp/a/b/c.html页面内加一行这样的代码:
<base href="http://localhost:8080/demo/a/b/">
这样你页面的任何跳转都是参照这个地址来进行跳转,这样就可以实现请求转发的顺利跳转了。
请求重定向:
/**
* 请求重定向
* 请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说,我给你一些地址,你去新地址访问,就是请求重定向
* (因为之前的地址可能已经废弃了)
*
* 特点:
* 1、浏览器地址栏会发生变化
* 2、两次请求
* 3、不共享request域中的数据
* 4、不能访问WEB-INF下的资源
* 5、可以访问当前工程以外的资源
*/
如图:
代码示例:
我们在web.xml中配置好/response1和/response2后
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("曾经到此一游 Response1"); req.setAttribute("key","陈柏宇"); //设置响应状态码302 //resp.setStatus(302); //设置响应头,说明新的地址在哪里 //resp.setHeader("Location","http://localhost:8080/demo/WEB-INF/a.html"); resp.sendRedirect("http://localhost:8080/demo/response2"); }
response2:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("response2‘s result"); System.out.println(req.getAttribute("key")); }
我们在浏览器输入如下网址:
http://localhost:8080/demo/response1
最终我们跳转到了
http://localhost:8080/demo/response2
这里说明一点,请求重定向是无法访问WEB-INF目录下的内容的
控制台输出:
曾经到此一游 Response1
null
这说明我们在response1中设置的requset域数据根本就没有被response2获取到。
总结一下请求转发和请求重定向的区别:
1.请求的转发:地址栏是初次发出请求的地址。
请求的重定向:地址栏不是初次发出请求的地址,为最后响应的地址。
2.请求转发:在最终的Servlet中,request和中转的那个request是同一个对象。
请求的重定向:在最终的Servlet中,request和中转的那个request不是同一个对象。
3.请求转发:只能转发给当前web应用的资源。
请求的重定向:可以重定向到任何资源(除了WEB-INF目录下的资源)。
4.请求的转发:/代表的是当前web应用的根目录。
请求的重定向:/代表的是当前web站点的根目录。