页面的转发与重定向

请求转发导入部分:

生活中常常会遇到这样的例子,例如打电话找某个单位的某个人,一般电话会呼叫到单位的总台,然后总台会根据我们提供的分机号转接到对应的分机最后我们就能进行正常的通话,其实这就又一个电话先到总机,总机再到分机的过程,这个过程我们称之为电话的转接。


请求转发:

其实在互联网中也会遇到类似的情况:浏览器首先发请求发送到ServletA,ServletA进过处理之后把请求传递到ServletB,由ServletB进行继续处理最后输出响应,这个传递的过程称之为请求转发。


请求转发原理:

浏览器首先发请求发送到ServletA进行处理,由于ServletA由于某种原因无法进行处理,也可能是设计的需求,所以交给ServletB继续进行服务这个时候ServletA就会调用forward()将请求转发给ServletB进行处理。

请求转发定义:

将当前的request和response对象交给指定的web组件处理。

说明:

其实在ServletA在调用请求转发的过程中,对于浏览器来说是透明的,浏览器并不知道为其服务的ServletA已经转化为ServletB,对于浏览器来说只是发出了一个请求然后获得一次响应。

注意:

在请求转发的过程中,浏览器的URL地址是不会变的。

转发对象RequestDispatcher:

要做请求转发首先要获取转发对象,然后调用转发对象的forward()
*RequestDispatcher:转发对象,它是由Servlet容器自动创建的,主要封装一个由路径所标识的服务器资源
--forward():请求转发到对应的服务器资源进行请求处理
--include():把请求发送给另外的web组件之后,原有的组件与被转发的组件都可以输出响应信息

获取转发对象RequestDispatcher:

可以通过两种方式获取:
*通过HttpServletRequest获取,也就是说从当前的请求中获取转发对象;
*通过ServletContext获取。

实例:

准备了两个例子,ServletForward与ServletForwarExample,首先请求会发送到ServletForward这个Servlet,然后由ServletForward转发到ServletForwarExample处理
ServletForward:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class ServletForward extends HttpServlet {  
  2.     public void init() throws ServletException {  
  3.         System.out.println("init method");  
  4.     }  
  5.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  6.             throws ServletException, IOException {  
  7.         //1.创建转发对象:获取转发对象,这个转发对象的参数为需要转发到下个Servlet的路径,  
  8.         //可以填mapping元素的url-pattern对应的地址  
  9.         RequestDispatcher rd = req.getRequestDispatcher("/forwardExample");  
  10.           
  11.         //ServletContext对象获取转发对象:1.getNamedDispatche()  
  12.         //getNamedDispatche()参数为对象Servlet的名称,即是mapping元素的Servlet-name的名称  
  13.         rd1 = this.getServletContext().getNamedDispatcher(  
  14.                 "ServletForwardExample");  
  15.       
  16.         //ServletContext对象获取转发对象:1.getRequestDispatcher()  
  17.         //getRequestDispatcher(),参数只能填绝对路径  
  18.         rd2 = this.getServletContext().getRequestDispatcher("/forwardExample");  
  19.   
  20.         //2.进行转发,需要把当前的request对象与response对象转发出去,这样forwardExample才能获取到request与response对象  
  21.         rd.forward(req, resp);  
  22.     }  
  23. }  
  24. ServletForwardExample:  
  25. public class ServletForwardExample extends HttpServlet {  
  26.     public void init() throws ServletException {  
  27.         System.out.println("init method");  
  28.     }  
  29.   
  30.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  31.             throws ServletException, IOException {  
  32.         resp.setContentType("text/html;charset=UTF-8");  
  33.         //获取一个user的参数  
  34.         String user = req.getParameter("user");  
  35.         //把对应的user打印  
  36.         PrintWriter writer = resp.getWriter();  
  37.         writer.println("<html>");  
  38.         writer.println("<head><title>转发示例</title></head>");  
  39.         writer.println("<body>");  
  40.         writer.println("<p>用户名:" + user + "</p>");  
  41.         writer.println("</body>");  
  42.         writer.println("</html>");  
  43.         writer.close();  
  44.     }  
  45. }  
web.xml:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <servlet>  
  2.     <servlet-name>ServletForward</servlet-name>  
  3.     <servlet-class>类路径.ServletForward</servlet-class>  
  4. </servlet>  
  5.   
  6. <servlet-mapping>  
  7.     <servlet-name>ServletForward</servlet-name>  
  8.     <url-pattern>/forward</url-pattern>  
  9. </servlet-mapping>  
  10.   
  11. <servlet>  
  12.     <servlet-name>ServletForwardExample</servlet-name>  
  13.     <servlet-class>类路径.ServletForwardExample</servlet-class>  
  14. </servlet>  
  15.   
  16. <servlet-mapping>  
  17.     <servlet-name>ServletForwardExample</servlet-name>  
  18.     <url-pattern>/forwardExample</url-pattern>  
  19. </servlet-mapping>  
  20. <h2>  
  21. 请求重定向导入部分:</h2>  

请求重定向导入部分:

用户登录例子:

平时上网的时候访问某些网站都有一个用户登录的流程,其实就是用户发送一个登陆请求,然后服务器端返回一个登陆响应,在登陆验证完成之后,浏览器通常会跳转到另外一个页面,并且浏览器的地址栏也改变了,我们只做了一次请求,会出现另外一个页面。


原因:
在我们登陆完成之后,服务器端向浏览器返回另外一个URL地址的响应信息,浏览器接收到该响应信息之后会自动的请求服务器端返回的URL地址,
最后服务器端返回对应的跳转结果,这样用户就进入了另外的一个页面。

请求重定向:

用户请求用于登陆请求的ServletA,服务器端想在用户登录成功之后直接进入到用户的页面,也就是说服务器端在ServletA处理完之后,ServletB继续为用户进行服务,
此时ServletA用了sendRedirect()将客户端的请求重定向到ServletB,这个过程就是请求重定向的过程。

请求重定向的定义:

*服务器的Servlet通过response对象发送给浏览器一个新URL地址,让其重新请求。
*两次请求,两次响应

实例:

准备了两个Servlet,ServletRedirect与ServletRedirectExample,首先请求会发送到ServletRedirect,然后ServletRedirect会把请求重定向到ServletRedirectExample
做请求重定向需要注意的一点:通过原请求对象的响应对象进行重定向

ServletRedirect:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class ServletRedirect extends HttpServlet {  
  2.     public void init() throws ServletException {  
  3.         System.out.println("init method");  
  4.     }  
  5.   
  6.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  7.             throws ServletException, IOException {  
  8.         //sendRedirect()参数需要注意,请求重定向可以定向到这个站点的其他web资源,使用绝对路径时,  
  9.         //要把当前web资源</span>加入进来,简单起见,使用相对路径(mapping元素下的相对路径)  
  10.         resp.sendRedirect("redirectExample");  
  11.     }  
  12. }  
  13. ServletRedirectExample:  
  14. public class ServletRedirectExample extends HttpServlet {  
  15.     public void init() throws ServletException {  
  16.         System.out.println("init method");  
  17.     }  
  18.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  19.             throws ServletException, IOException {  
  20.         resp.setContentType("text/html;charset=UTF-8");  
  21.         //注意这里与请求转发的区别,请求转发是同一个请求和同一个响应的转发  
  22.         //请求重定向是两次请求,两次转发,这里的请求和响应不是同一个  
  23.         //下面将获取不到user对象的值,即为null  
  24.         String user = req.getParameter("user");  
  25.   
  26.         PrintWriter writer = resp.getWriter();  
  27.         writer.println("<html>");  
  28.         writer.println("<head><title>转发示例</title></head>");  
  29.         writer.println("<body>");  
  30.         writer.println("<p>用户名:" + user + "</p>");  
  31.         writer.println("</body>");  
  32.         writer.println("</html>");  
  33.         writer.close();  
  34.     }  
  35. }  


web.xml:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <servlet>  
  2.     <servlet-name>ServletRedirect</servlet-name>  
  3.     <servlet-class>com.netease.server.example.web.controller.ServletRedirect</servlet-class>  
  4. </servlet>  
  5. <servlet-mapping>  
  6.     <servlet-name>ServletRedirect</servlet-name>  
  7.     <url-pattern>/redirect</url-pattern>  
  8. </servlet-mapping>  
  9.   
  10. <servlet>  
  11.     <servlet-name>ServletRedirectExample</servlet-name>  
  12.     <servlet-class>com.netease.server.example.web.controller.ServletRedirectExample</servlet-class>  
  13. </servlet>  
  14. <servlet-mapping>  
  15.     <servlet-name>ServletRedirectExample</servlet-name>  
  16.     <url-pattern>/redirectExample</url-pattern>  
  17. </servlet-mapping>  

注意:

如果想重定向到当前的web资源则填写相对路径,如果想重定向到其他web资源就填写绝对路径。




servlet和servlet之间可以实现相互跳转,servlet的跳转可以将一个项目的模块进行划分,这样更加方便了开发人员的操作,servlet之间的跳转分为两种,一种是转发,英文名称Forward,另一种是重定向,英文名称Redirect。转发,指转移发放,指的是文件的批转发送;重定向,就是通过)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。下面重点详细介绍一下转发和重定向,希望对有需要的小伙伴有帮助,还请大牛们多多指教。
转发(Forward)
转发市通过RequestDispatcher对象的Forward(HttpServletRequest request,HttpServletResponse response)来实现的,语法格式如下所示:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet/LifeCycleServlet");   
  2. dispatcher.forward(request, response);</span>  
      servlet页面跳转的路径是相对路径,转发方式只能跳转到本web应用中的页面上,跳转后浏览器地址栏不会改变,转发市最常用的方式,在struts等MVC框架中,都是用servlet来处理用户请求,把结果通过request.setAttribut()放到request中,然后转发到jsp中进行显示,当执行转发方法时,不能有任何输出到达客户端,否则会抛出异常,也就是说,在转发之前,不要使用out.println()语句向客户端输出。代码如下所示:
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">public void doGet(HttpServletRequest request, HttpServletResponse response)  
  2.         throws ServletException, IOException {  
  3.     String destination = request.getParameter("destination");  
  4.        
  5.     if("file".equals(destination)){  
  6.         RequestDispatcher d = request.getRequestDispatcher("/WEB-INF/web.xml");  
  7.         d.forward(request, response);  
  8.     }else if("jsp".equals(destination)){  
  9.         request.setAttribute("date"new Date());  //attributes are reset between requests.  
  10.         RequestDispatcher dispatcher = request.getRequestDispatcher("/forward.jsp");  
  11.         dispatcher.forward(request, response);  
  12.     }else if("servlet".equals(destination)){  
  13.         RequestDispatcher disp = request.getRequestDispatcher("/servlet/LifeCycleServlet");  
  14.         disp.forward(request, response);  
  15.     }else{  
  16.         response.setCharacterEncoding("UTF-8");  
  17.         response.getWriter().println("缺少参数。用法:"+request.getRequestURI()+"?destination=jsp或者file或者servlet");  
  18.     }  
  19. }</span>  
重定向(Redirect)
        重定向是通过服务器端返回状态码来实现的,a和b都表示重定向,区别是a表示永久性重定向,b表示临时性重定向,通过sendRedirect(String location)就可以实现重定向,如下面的demo。本例子主要实现了Servlet来实现文件下载并统计下载次数。要下载的文件以及下载次数都保存在一个Map中。主要思路是:首先加载页面表单,当用户点击下载链接时,客户端发起请求,运行doGet里的if判断,实现重定向。 重定向和跳转的区别:跳转是在服务器端实现的,客户端浏览器并不知道该浏览动作,而使用Redict跳转时,跳转是在客户端实现的,也就是说客户端浏览器实际上请求了两次次服务器。
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">public class RedictServlet extends HttpServlet {  
  2.    
  3.     Map<String,Integer> map = new HashMap<String,Integer>(); //new一个Map  
  4.    
  5.     public void init() throws ServletException {  //放在init中,加载servlet时运行此方法,把文件内容放到map中去  
  6.         map.put("/download/setup.exe"0);  
  7.         map.put("/download/application.zip"0);  
  8.         map.put("/download/01.mp3"0);  
  9.     }  
  10.    
  11.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  12.             throws ServletException, IOException {  
  13.         String filename = request.getParameter("filename");  
  14.            
  15.         if(filename!=null){  
  16.             int hit = map.get(filename);  //取下载次数  
  17.             map.put(filename, ++hit);  //下载次数加1后保存  
  18.             response.sendRedirect(request.getContextPath()+filename);  //重定向到文件  
  19.                
  20.         }else{  
  21.             response.setCharacterEncoding("UTF-8");  
  22.             PrintWriter out = response.getWriter();  
  23.             response.setContentType("text/html");  
  24.             out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");  
  25.             out.println("<HTML>");  
  26.             out.println("  <HEAD><TITLE>文件下载</TITLE></HEAD>");  
  27.             out.println("   <link rel='stylesheet' type='text/css' href='../css/style.css'>");  
  28.             out.println("  <BODY><br/>");  
  29.    
  30.             out.println("<fieldset align=center style=width:90%><legend>文件下载</legend>");  //绘制页面表单  
  31.             out.println("<table width=100%>");  
  32.             out.println("   <tr>");  
  33.             out.println("       <td><b>文件名"+"</b></td>");  
  34.             out.println("       <td><b>下载次数</b></td>");  
  35.             out.println("       <td><b>下载</b></td>");  
  36.             out.println("   </tr>");  
  37.                
  38.             for(Entry<String,Integer> entry: map.entrySet()){  //遍历map的方法  
  39.                 out.println("<tr>");  
  40.                 out.println("   <td>"+entry.getKey()+"</td>");  
  41.                 out.println("   <td>"+entry.getValue()+"</td>");  
  42.                 out.println("   <td><a href = '"+request.getRequestURI()+"?filename="+entry.getKey()+"'target = '_blank' onclick ='location = location;'>下载</a></td>");  //target='_blank'目标地址在无标题的新页面中打开。onclick ='location = location;'页面刷新  
  43.                 out.println("</tr>");  
  44.             }  
  45.             out.println("</table>");  
  46.             out.println("   </legend>");  
  47.             out.println("  </BODY>");  
  48.             out.println("</HTML>");  
  49.             out.flush();  
  50.             out.close();  
  51.         }  
  52.            
  53.     }  
  54.    
  55.     public void destroy() {  
  56.         super.destroy(); // Just puts "destroy" string in log  
  57.         // Put your code here  
  58.         map = null;  
  59.     }  
  60. }</span>  

转发和重定向的区别
使用转发跳转时,跳转是在服务器端实现的,客户端浏览器并不知道该浏览的动作,而使用重定向跳转的社会化,跳转实在客户端实现的,也就是说客户端浏览器实际上请求了两次服务器,语法格式如下:
response.sendRedirect("/a.jsp");
页面的路径是相对路径,sendRedirect可以将页面跳转到任何页面,不一定局限于本web应用中,例如:
response.sendRedirect("URL");
跳转后浏览器地址栏发生变化,这种方式要传值出去的话,只能在url中带parameter或者是放在seesion中,无法使用request.setAttribute来传递。接着小编以画图的形式来解释一下转发和重定向的区别:
转发
a、转发不会改变浏览器的地址栏
b、转发共享同一个request
c、转发只能在同一个web应用中使用
如下图:

接着,我们来看重定向:
a、重定向会改变浏览器的地址栏
b、重定向不共享request
c、可以重定向到任意URL
如下图:

        一句话概括来说就是,转发是服务器行为,重定向是客户端行为,从请求次数和请求的资源地址两个方面来理解一下她们之间的区别,首先从请求次数来说,重定向行为是做了两次请求,以及产生了两个request对象,重定向会导致request对象信息丢失。转发是做了一次请求,浏览器地址栏一直是第一次请求的地址,转发是服务器内部request/response控制权的移交。

        从请求资源的角度来看,重定向是weib自荐可以将请求重定向到任意一个url,而不仅仅是同一个应用,重定向的源组件与目标组件不公用同一个HttpServletRequest对象,因此不能在request范围内共享数据。转发的源组件与目标组件必须在同一个应用总,两者可以在request范围内共享数据。

       小编寄语:小编主要简单介绍了转发和重定向的相关知识,小编简单的举一个例子来帮助小伙伴们理解一下转发和重定向,假设我们需要去办理一个银行业务,假设我们先去了建行,建行的工作人员看了以后,发现这个业务应该工行的工作人员来进行处理,但是建行的工作人员没有跟我们说,让我们去工行,而是让我们坐下来,喝杯茶,建行的工作人员自己和工行的工作人员取得联系,让他们把业务办理好,给我们送了过来,这就是转发;那么什么是重定向呢?我们先去了建行,建行的工作人员说,这个事情不归我们管理,你们需要去工行办理,然后,我们从建行撤了回来,我们自己乘车去了工行,这就是重定向。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值