我们在使用HttpServletRequest和HttpServletReonse等工具类的时候,这些工具类走的协议就是http协议,http协议也是我们日常WEB开发通用的协议。因为http协议封装的很好,因此我们往往忽视了它,但是在对性能的极致追求中,这些基础协议,又成为我们继续努力的基础。
响应,在http协议中有非常重要的作用。
可以设置Location响应头,实现请求重定向(可以查看HttpServletRequest相关内容);也可以设置Content-Encoding响应头,告诉浏览器数据的压缩格式;还可以设置content-type响应头,指定回送数据类型;也可以设置content-disposition响应头,让浏览器下载文件((可以查看HttpServletReonse相关内容))…
还可以利用它,做很多很多的事情。
1、WEB数据传输中的压缩(Content-Encoding)的源代码
在带宽不够的时候,压缩是一种解决事情的好方法;现在的带宽是越来越大了,不过文件也越来越大,压缩还是有英雄用武之地的。其中百度等网站也是使用压缩的数据传递方式。
package com.servlet;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
*通过HttpServletResponse实现传输文件的压缩
*
*@author 范芳铭
*/
public class ResponseEncode extendsHttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponseresponse)
throws ServletException,IOException {
String data = "123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890"+
"123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890" +
"123456789012345678901234567890" ;
System.out.println("原始数据的大小为:" + data.getBytes().length);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
//能够把文件进行压缩的对象
GZIPOutputStream gout = new GZIPOutputStream(bout); //buffer
gout.write(data.getBytes());
gout.close();
//得到压缩后的数据
byte g[] = bout.toByteArray();
//告诉浏览器用gzip的方式解压
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Content-Length",String.valueOf(g.length));
System.out.println("压缩后的数据的大小为:" + g.length);
response.getOutputStream().write(g);
}
publicvoid doPost(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
doGet(request,response);
}
}
修改web.xml如下:
<servlet>
<servlet-name>encode</servlet-name>
<servlet-class>com.servlet.ResponseEncode</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>encode</servlet-name>
<url-pattern>/encode</url-pattern>
</servlet-mapping>
2、运行结果
浏览器上显示:123456789012345678901234…
好像没有什么效果。
3、测试压缩方法
在浏览器上的访问URL为:http://localhost:8080/webStudy/encode
所有的数据都很正常,但是好像什么都没有做,和普通的方法是一样的。
利用apache commons的httpClient写一个简单的测试用例。(在Apache commons 系列博客中有详细介绍)
httpClient的测试源代码:
package test.ffm83.commons.httpClient;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
/**
* httpClient 的简单应用
* 基于4.x版本
* @author 范芳铭
*/
public class EasyHttpGetA {
public finalstatic void main(String[] args) throws Exception {
getHttpGetOld("http://www.baidu.com/");
getHttpGetOld("http://localhost:8080/webStudy/encode");
}
private staticvoid getHttpGetOld(String url) throws Exception{
HttpClient httpclient = newDefaultHttpClient(); //老方法,不推荐使用
try {
HttpGet httpget = newHttpGet(url);
System.out.println(StringUtils.center(url, 50,"="));
HttpResponse response =httpclient.execute(httpget); //老方法,不推荐使用
HttpEntity entity =response.getEntity();
System.out.println(response.getStatusLine());
String webContent = "";
if (entity != null) {
webContent= EntityUtils.toString(entity);
System.out.println("ResponsegetContentLength: " + entity.getContentLength());
System.out.println("ResponsetoString() length: " + webContent.length());
}
System.out.println(response.toString()); //显示HTTP请求header
System.out.println("----------------------------------------");
httpget.abort();
}
finally {
httpclient.getConnectionManager().shutdown();
}
}
}
4、最终运行结果
我在这里测试了两个URL地址,一个是百度的,一个是http://localhost:8080/webStudy/encode
运行结果如下:
==============http://www.baidu.com/===============
HTTP/1.1 200 OK
Response getContentLength: -1
Response toString() length: 88174
HTTP/1.1 200 OK [Date: Mon, 02 Feb2015 07:35:35 GMT, Content-Type: text/html; charset=utf-8, Transfer-Encoding:chunked, Connection: Keep-Alive, Vary: Accept-Encoding, Set-Cookie:BAIDUID=79C3549FB148B3FD0457B06C79D0BB4C:FG=1; expires=Thu, 31-Dec-37
23:55:55GMT; max-age=2147483647; path=/; domain=.baidu.com, Set-Cookie:BAIDUPSID=79C3549FB148B3FD0457B06C79D0BB4C; expires=Thu, 31-Dec-37 23:55:55GMT; max-age=2147483647; path=/; domain=.baidu.com, Set-Cookie: BDSVRTM=0;path=/, Set-Cookie: BD_HOME=0; path=/,
Set-Cookie: H_PS_PSSID=11384_6354_1426_11361_11156_10902_11226_11394_11101_11399_11277_11241_11280_11151_11243_11404_10618_10634;path=/; domain=.baidu.com, P3P: CP=" OTI DSP COR IVA OUR IND COM ",Cache-Control: private, Cxy_all: baidu+fefa91c7f05681df2e287f12aec4d30b,
Expires:Mon, 02 Feb 2015 07:35:27 GMT, X-Powered-By: HPHP, Server: BWS/1.1, BDPAGETYPE:1, BDQID: 0xec3eeae200002e8a, BDUSERID: 0][email protected]
----------------------------------------
======http://localhost:8080/webStudy/encode=======
HTTP/1.1 200 OK
Response getContentLength: 35
Response toString() length: 35
HTTP/1.1 200 OK [Server:Apache-Coyote/1.1, Content-Encoding: gzip, Content-Length: 35, Date: Mon, 02Feb 2015 07:37:50 GMT] [email protected]
----------------------------------------
从工具中能够看到:
Response getContentLength: 35
Response toString() length: 35
而从控制台打印出来的内容:
原始数据的大小为:300
压缩后的数据的大小为:35
浏览器具备了自我解压的能力,数据在传输过程中被压缩,降低了带宽的使用。