Servlet实战(3)
在Servlet(1)和Servlet(2)中自己收获了很多,每一篇笔记都是自己的亲身实践,在Servlet(3)中我会继续探索一些让我迷惑的东西。在Servlet学习结束后,我将开始深入的探索struts框架,一步步走下去。
请求转发----------getRequestDispatcher()
页面重定向、请求转发
我记得我刚开始接触java时,那时候跟傻子一样,学什么东西都是狼吞虎咽,现在回想起来,当初的知识十有七八都忘了,脑海里只留下一点影,遇到问题知道百度哪些。现在再来细细学习当初让自己迷惑的东西。
推荐好文:https://www.cnblogs.com/understander/p/5689900.html
说实在的,看了上面推荐的好文之后,我就不想写这个重定向和转发了,因为感觉他里面讲的很好,很透彻。自己就把原文抄一遍,加深印象吧【转载】。
重定向----------sendRedirect()
介绍
Servlet相应请求有两种方式,一个是重定向,返回一个页面给客户端,另一种是直接向客户端传递数据。
使用重定向是让浏览器重新发送请求,它可以请求是当前站点下的一个Servlet,也可以是当前站点下的其他静态文件,如果是其他站点下的记得写全地址栏信息(加http)。
使用方式
response.sendRedirect("/ServletProject/DemoServlet")
官网说明
【使用指定的重定向位置URL向客户端发送临时重定向响应并清除缓冲区。缓冲区将被此方法设置的数据替换。调用此方法将状态代码设置为sc_found 302(found)。此方法可以接受相对URL;servlet容器必须在将响应发送到客户端之前将相对URL转换为绝对URL。如果位置是相对的,而没有前导“/”,则容器将其解释为相对于当前请求URI。如果位置与前导“/”相关,则容器将其解释为相对于servlet容器根。如果已提交响应,则此方法将引发IllegalStateException。使用此方法后,应将响应视为已提交,而不应写入。】
例子
来看一个例子:
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/RedirectServlet") public class RedirectServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); // 地址栏变成:http://localhost:8080/Servlet/www.taobao.com // resp.sendRedirect("www.taobao.com"); // 地址栏变成:http://localhost:8080/www.taobao.com // resp.sendRedirect("/www.taobao.com"); // 地址栏变成:https://www.taobao.com/ // resp.sendRedirect("http://www.taobao.com"); // 重定向到其他站点要使用绝对URL // 将请求重定向到index.jsp // resp.sendRedirect("index.jsp"); req.setAttribute("name", "毛毛"); // 将请求重定向到Servlet resp.sendRedirect("Redirect_DispatcherServlet"); } }
从地址栏的变化中我们可以看出,重定向可以重定向到当前站点下某一个项目里的其他Servlet,也可以重定向到另一个项目里的其他Servlet,或者是其他站点的项目。
@WebServlet("/Redirect_DispatcherServlet") public class Redirect_DispatcherServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("name:"+req.getAttribute("name")); } }
请求转发----------getRequestDispatcher()
介绍
将客户端的请求转发到另一个Servlet或者JSP页面。
使用方式
request.getRequestDispatcher("/").forward(request, response);
官网说明
【返回一个RequestDispatcher对象,该对象用作位于给定路径的资源的包装器。RequestDispatcher对象可用于将请求转发到资源或在响应中包含资源。资源可以是动态的或静态的。指定的路径名可能是相对的,尽管它不能扩展到当前servlet上下文之外。如果路径以“/”开头,则被解释为相对于当前上下文根目录。如果servlet容器无法返回requestDispatcher,则此方法返回空值。此方法与servletContext getRequestDispatcher的区别在于,此方法可以采用相对路径。】
例子
来看一个例子:
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/DispatcherServlet") public class DispatcherServlet extends HttpServlet{ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 请求到首页 // req.getRequestDispatcher("/index.jsp").forward(req, resp); // 也能请求到首页 // req.getRequestDispatcher("index.jsp").forward(req, resp); req.setAttribute("name", "毛毛"); req.getRequestDispatcher("/Redirect_DispatcherServlet").forward(req, resp); } }
两者之间的区别
区别
(1) RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL(带有http)重定向到其他站点的资源。如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
(2) 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
(3) HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的 访问请求。RequestDispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
重定向发两次请求,地址栏改变了,两次是不同的request请求。
转发只发一次请求,地址栏不变,转发方和接收方共享req和resp对象,所以能拿到name
(4) RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。
(5) 无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。
总结
转发-----你找我借钱,我没钱,但是我可以帮你去找别人借钱。(再“借钱”这个动作由我去执行)
重定向-----你找我借钱,我没钱,但是我让你去找别人借钱。(再“借钱”这个动作由你自己去执行)
接下来要读的是
JSP的基本构成