转发和重定向-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

转发和重定向

简介: servlet和servlet之间可以实现相互跳转,servlet的跳转可以将一个项目的模块进行划分,这样更加方便了开发人员的操作,servlet之间的跳转分为两种,一种是转发,英文名称Forward,另一种是重定向,英文名称Redirect。
servlet和servlet之间可以实现相互跳转,servlet的跳转可以将一个项目的模块进行划分,这样更加方便了开发人员的操作,servlet之间的跳转分为两种,一种是转发,英文名称Forward,另一种是重定向,英文名称Redirect。转发,指转移发放,指的是文件的批转发送;重定向,就是通过)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。下面重点详细介绍一下转发和重定向,希望对有需要的小伙伴有帮助,还请大牛们多多指教。
转发(Forward)
转发市通过RequestDispatcher对象的Forward(HttpServletRequest request,HttpServletResponse response)来实现的,语法格式如下所示:
RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet/LifeCycleServlet"); 
dispatcher.forward(request, response);
      servlet页面跳转的路径是相对路径,转发方式只能跳转到本web应用中的页面上,跳转后浏览器地址栏不会改变,转发市最常用的方式,在struts等MVC框架中,都是用servlet来处理用户请求,把结果通过request.setAttribut()放到request中,然后转发到jsp中进行显示,当执行转发方法时,不能有任何输出到达客户端,否则会抛出异常,也就是说,在转发之前,不要使用out.println()语句向客户端输出。代码如下所示:
public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String destination = request.getParameter("destination");
     
    if("file".equals(destination)){
        RequestDispatcher d = request.getRequestDispatcher("/WEB-INF/web.xml");
        d.forward(request, response);
    }else if("jsp".equals(destination)){
        request.setAttribute("date", new Date());  //attributes are reset between requests.
        RequestDispatcher dispatcher = request.getRequestDispatcher("/forward.jsp");
        dispatcher.forward(request, response);
    }else if("servlet".equals(destination)){
        RequestDispatcher disp = request.getRequestDispatcher("/servlet/LifeCycleServlet");
        disp.forward(request, response);
    }else{
        response.setCharacterEncoding("UTF-8");
        response.getWriter().println("缺少参数。用法:"+request.getRequestURI()+"?destination=jsp或者file或者servlet");
    }
}
重定向(Redirect)
        重定向是通过服务器端返回状态码来实现的,a和b都表示重定向,区别是a表示永久性重定向,b表示临时性重定向,通过sendRedirect(String location)就可以实现重定向,如下面的demo。本例子主要实现了Servlet来实现文件下载并统计下载次数。要下载的文件以及下载次数都保存在一个Map中。主要思路是:首先加载页面表单,当用户点击下载链接时,客户端发起请求,运行doGet里的if判断,实现重定向。 重定向和跳转的区别:跳转是在服务器端实现的,客户端浏览器并不知道该浏览动作,而使用Redict跳转时,跳转是在客户端实现的,也就是说客户端浏览器实际上请求了两次次服务器。
public class RedictServlet extends HttpServlet {
 
    Map<String,Integer> map = new HashMap<String,Integer>(); //new一个Map
 
    public void init() throws ServletException {  //放在init中,加载servlet时运行此方法,把文件内容放到map中去
        map.put("/download/setup.exe", 0);
        map.put("/download/application.zip", 0);
        map.put("/download/01.mp3", 0);
    }
 
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String filename = request.getParameter("filename");
         
        if(filename!=null){
            int hit = map.get(filename);  //取下载次数
            map.put(filename, ++hit);  //下载次数加1后保存
            response.sendRedirect(request.getContextPath()+filename);  //重定向到文件
             
        }else{
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            response.setContentType("text/html");
            out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
            out.println("<HTML>");
            out.println("  <HEAD><TITLE>文件下载</TITLE></HEAD>");
            out.println("   <link rel='stylesheet' type='text/css' href='../css/style.css'>");
            out.println("  <BODY><br/>");
 
            out.println("<fieldset align=center style=width:90%><legend>文件下载</legend>");  //绘制页面表单
            out.println("<table width=100%>");
            out.println("   <tr>");
            out.println("       <td><b>文件名"+"</b></td>");
            out.println("       <td><b>下载次数</b></td>");
            out.println("       <td><b>下载</b></td>");
            out.println("   </tr>");
             
            for(Entry<String,Integer> entry: map.entrySet()){  //遍历map的方法
                out.println("<tr>");
                out.println("   <td>"+entry.getKey()+"</td>");
                out.println("   <td>"+entry.getValue()+"</td>");
                out.println("   <td><a href = '"+request.getRequestURI()+"?filename="+entry.getKey()+"'target = '_blank' onclick ='location = location;'>下载</a></td>");  //target='_blank'目标地址在无标题的新页面中打开。onclick ='location = location;'页面刷新
                out.println("</tr>");
            }
            out.println("</table>");
            out.println("   </legend>");
            out.println("  </BODY>");
            out.println("</HTML>");
            out.flush();
            out.close();
        }
         
    }
 
    public void destroy() {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
        map = null;
    }
}

转发和重定向的区别
使用转发跳转时,跳转是在服务器端实现的,客户端浏览器并不知道该浏览的动作,而使用重定向跳转的社会化,跳转实在客户端实现的,也就是说客户端浏览器实际上请求了两次服务器,语法格式如下:
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范围内共享数据。

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章