请求转发和重定向的区别

一 、重定向

1.重定向过程

客户端发送一个请求到服务器端,对应的Servlet处理完之后调用了sendRedirect()这个方法,然后立即向客户端返回响应,告诉客户端你必须再给谁谁重新发送一个请求,紧接着客户端收到这个请求后,立刻发出一个新的请求。在这两个请求互不干扰、相互独立。
浏览器发送了两次请求,浏览器的地址栏也发生了变化,请求过程中产生了两个request和两个response请求,两个servlet不共享一个request和response,重定向是通过sendRedirect()实现.
在这里插入图片描述

2.代码

下面举了一个生活中的例子来解释重定向过程。

A手头略紧,找舍友B借钱,然而舍友B最近零花钱也所剩无几,没有答应B,让A去找舍友C问问,舍友C恰好这个月比较富裕,答应了A的请求。这个过程里A完成了两次请求,请求对象不同。

【AServlet】
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class AServlet
 */
@WebServlet("/AServlet")
public class AServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public AServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		
        String id=request.getParameter("stuid");
		System.out.println("---开始第一次请求:A不想上课去找B---");
		System.out.println("A对B说:我不去上课,帮我签个到,学号是"+id);
		System.out.println("B对A说:我也没打算去上课,你问问C去不去");
		System.out.println("---开始第二次请求:A要去找C---");
		response.sendRedirect("CServlet");

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

【CServlet】
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class BServlet
 */
@WebServlet("/CServlet")
public class CServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public CServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//设置浏览器解析的格式,否则浏览器会出现乱码
        response.setContentType("text/html;charset=utf-8");
        //获取请求携带的id
        String id = request.getParameter("id");
        System.out.println("A对C说:老师点名帮我签个到,学号是:"+id);
        System.out.println("C:木的问题,那我帮你答到");
        //获取输出流
        PrintWriter writer = response.getWriter();
        //将信息返回给浏览器
        writer.println("C:木的问题,那我帮你答到");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}
}
3.运行结果

启动服务器,在浏览器中输入网址
在这里插入图片描述
浏览器中响应,结果如下:
在这里插入图片描述
Console打印信息如下:
在这里插入图片描述
发送第二次请求的时候,可以发现money显示null

二、 请求转发

1.请求转发过程

客户端首先发送一个请求到服务器,服务器匹配Servlet,并指定执行。当这个Servlet执行完后,它要调用getRequestDispacther()方法,把请求转发给指定的Servlet_list.jsp,整个流程都是在服务端完成的,而且是在同一个请求里面完成的,因此Servlet和jsp共享同一个request,在Servlet里面放的所有东西,在student_list.jsp中都能取出来。因此,student_list.jsp能把结果getAttribute()出来,getAttribute()出来后执行完把结果返回给客户端,整个过程是一个请求,一个响应。
浏览器只发送1次请求,地址栏地址没有改变,请求过程中只产生一个response和requests对象,涉及到的几个servlet共享一个request和response对象,请求转发用getRequestDispatcher实现。
在这里插入图片描述

2.代码

下面举了一个生活中的例子来解释请求转发的过程。

A手头略紧,找舍友B借钱,然而舍友B最近零花钱也所剩无几,但是碍于面子他没有直接拒绝A而是去找C帮忙然后借钱再给A。这个过程里A完成了1次请求,请求对象始终是B。

【AAServle.java】
import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class AAServlet
 */
@WebServlet("/AAServlet")
public class AAServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public AAServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		// 获取请求携带的id
        String money = request.getParameter("money");
        System.out.println("----A这个月提前月光,为了艰难度日打算去找舍友B借钱----");
		System.out.println("A对B说:最近手头有点紧,能先借我"+money+"RMB不");
        System.out.println("B对A说:好的");
        System.out.println("----虽然B没有钱,但是B为了帮助A偷偷去找C借钱了----");
        //---后面B直接在服务器将请求转发给C---
        //获取转发对象,后面括号指定了转发的路径
        RequestDispatcher dispatcher = request.getRequestDispatcher("CCServlet");
        //执行转发功能,并将请求和响应一并转发过去
        dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

在上面的代码中用到了forward()方法,使用forward()可以实现传值,例如在登陆注册时,设置好的用户名由servlet传递给jsp时,如果用重定向,jsp就不能获取该用户的信息,但是利用forward()时,就可以传送该用户的信息。这也可以解释为什么后面Console打印信息时重定向第二次请求的参数为null。

【CCServlet.java】
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class CCServlet
 */
@WebServlet("/CCServlet")
public class CCServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public CCServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        // 获取请求携带的值
        String money = request.getParameter("money");
        System.out.println("B对C说:帮忙借给A" + money+"RMB吧");
        System.out.println("A借到钱了");
        // 获取输出流
        PrintWriter writer = response.getWriter();
        // 将信息返回给浏览器
        writer.println("A借到钱了");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
3.运行结果

启动服务器,在浏览器中输入网址
在这里插入图片描述浏览器中响应,结果如下:
在这里插入图片描述
Console打印信息如下:
在这里插入图片描述
在请求转发中,money的值不同于重定向,money不为空,而且网址也没有变化,而重定向可以发现Servlet更改了。

三、转发和重定向的区别

  1. request.getRequestDispatcher()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;服务器内部转发,整个过程处于同一个请求当中。
    ​ response.sendRedirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。不在同一个请求。重定向,实际上客户端会向服务器端发送两个请求
    ​ 所以转发中数据的存取可以用request作用域:request.setAttribute(), request.getAttribute(),重定向是取不到request中的数据的,只能用session
  2. RequestDispatcher是通过调用HttpServletRequest对象的getRequestDispatcher()方法得到的,是属于请求对象的方法。
    ​ sendRedirect()是HttpServletResponse对象的方法,即响应对象的方法,既然调用了响应对象的方法,那就表明整个请求过程已经结束了,服务器开始向客户端返回执行的结果。
  3. 重定向可以跨域访问就是可以访问本服务器外的资源,而转发是在web服务器内部进行的,只能访问当前服务器下的资源。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值