转发的一些小细节

重定向区别于转发,是客户端请求服务器,服务器的两种操作方式:

1.重定向 :通俗的说-客户端向服务器发出一次请求,服务器作出响应告诉客户端去请求另外一个地址,客户端请求了两次,得到响应两次。

2,转发:也是通俗的说-客户端向服务器发出一次请求,服务器去请求另外一个地址,然后作出响应,客户端请求了一次,得到响应一次。


我们这里就从Servlet说说转发:(javaweb的一些框架都是基于servlet开发的)

我们要转发,就得先得到Dispatrue对象,然后调用它的forword(request,response);方法,进行请求转发。

得到Dispatrue对象有两种方式:

1,|--得到ServletContext(),然后通过它的getRequestDispatrue()方法得到;

|--得到ServletContext对象有两种方式:

1.1.|--通过ServletConfig对象的getServletContext()方法获取;

1.1.1|--得到ServletConfig对象,通过httpServlet自带的方法getServletConfig()方法获取。

1.2.|--则是通过HttpServlet自带的方法getServletContext()方法获取。

2,|--通过Request对象的getRequestDispatrue()方法得到。

我们对下面的代码进行分析,更加深刻的理什么是转发:

ServletContext context=getServletContext();
		OutputStream os=response.getOutputStream();
		os.write("ss".getBytes());
		//os.flush();//flush将缓冲区的数据强制性的写到客户端后response就返回给客户端信息导致本次响应结束,,后面的不执行,如果不flush那么
					//在执行转发前 缓冲区的数据就会被清空
		System.out.println("执行了");
		context.getRequestDispatcher("/ResponseGzipTest").forward(request, response);
		response.getOutputStream().write("vbb".getBytes());//这个不执行,以为转发后目的地的response已经向客户端写信息了
												//那么这个response就无效了,和前面的情况是一样的

上面程序中的:

ResponseGzipTest   是一个Servlet 具体代码如下:

		response.setContentType("text/html;charset=utf-8");
		response.setHeader("Content-Encoding", "gzip");
		String s="hello  niha";
		System.out.println(s.getBytes().length);
		ByteOutputStream out=new ByteOutputStream();
		GZIPOutputStream gos=new GZIPOutputStream(out);
		gos.write(s.getBytes());//将数据压缩读出来放入到out字节输出流中
		gos.close();
		
		byte []buf=out.toByteArray();
		OutputStream ous=response.getOutputStream();
		System.out.println(buf.length); 
		ous.write(buf);
		
		ous.close();
		

上面的代码是将"hello  niha"通过gzip压缩后传输到客户端显示出来。


分析:当客户端一个请求到通过get或者post方式到达后台时,程序进行的时候,执行到了红色部分的代码,那么后台服务器就得进行转发这个请求,通过forword代码将这次请求的request对象和response对象传递过去(因为一次请求进行转发,只有一个request和response),

这是这个程序的运行结果:



我们可以看到在地址栏我们请求的是ServletContextTest2然后转发到ResponseGzipTest这个servlet,这里地址栏的url没有发生变化(这是转发的一个特点),

但是我们在图上面的第一段代码的时候,在转发前存在这么一段代码:

OutputStream os=response.getOutputStream();
		os.write("ss".getBytes());
		//os.flush();//flush将缓冲区的数据强制性的写到客户端后response就返回给客户端信息导致本次响应结束,,后面的不执行,如果不flush那么
					//在执行转发前 缓冲区的数据就会被清空
		System.out.println("执行了");

为什么os.write("ss".getBytes())这句话没有起作用,也就是说为什么页面上没有打印出来“ss”这个字符串?

原因是这样的:

os.write("ss".getBytes())是将“ss”写进了缓存,每当服务器进行转发的时候,都会清除缓存中的数据所有不会有输出结果。

但是如果我们将注释掉的“os.flush()“释放掉,会出现怎样的结果呢?



这个是执行结果,也就是说这次将ss输出到了页面;但是控制台出现了异常:


说的是响应已经提交,也就是说转发的时候不存在没有提交的response,为什么会出现这种情况呢?

原因是:我们调用os.flush()方法,强制的将缓存中的数据通过response的响应写到客户端,那么就意味着这次请求就结束了。


我们还注意到在第一段代码的转发后存在这么一段代码:

response.getOutputStream().write("vbb".getBytes());//这个不执行,以为转发后目			//的地的response已经向客户端写信息了

这句换在上面的几种情况下都没有执行,为什么呢?

原因是:第一种情况是转发执行了,在ResponseGizpTest这个servlet类里面已经通过response对客户端做出了响应,那么其后执行的所有response就失效了。

第二种情况,是强制flush缓存中的数据,通过response响应想客户端写数据, 其后的response当然也就失效了。。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值