Http协议
对于一个浏览器,如果它要访问web资源,那就要通过HTTP协议来访问。
一个高级程序员,那么他肯定对于Http相应有很深的理解,可以这么说“如果你不理解HTTP协议,那你就不用学web程序了;如果你非常了解HTTP协议,那你也不用学web了,因为什么,因为web程序就那么点东西”,下面开始介绍HTTP协议。
HTTP协议总体来说一共分为两大类,1.请求头 2.响应头,
一.先说请求头:
请求行:GET是以get方式请求,请求的资源是/lav/1.html,HTTP的版号是1.1,http协议一共有两个版本号,分别是http1.0和http1.1,
消息头:
1.Accept:用来告诉服务器,客户端支持的数据类型,这里是全支持,举个例子:text/html,images
2.Accept-Charset:用于告诉服务器,客户端采用的编码方式,例如:ISO-8859-1
3.Accept-Encoding:用于告诉服务器,客户机支持的数据压缩格式,这里是gzip格式
4.If-Modified-Since:用于告诉服务器,这是最后一次的缓存时间,一般的情况下,浏览器第一次在访问页面的时候会本地缓存,这个字段可根据服务最后一次更新的时间来比对,是否重新加载。
5.Accept-Lanaguage:客户机的语言环境,可用作本地化。
6.Host:客户机通过这个头告诉服务器,想访问那台主机。
7.Referer:客户机通过这个头告诉服务,它是从那个资源来访问服务器的(用这个referer可以做“防盗链”),防盗链是什么,比如从别人的网站点击我的网站资源,在这种情况下可以避免直接的打开或者下载,一般情况下应用这个防盗链调回我网站的首页。
8.User-Agent:客户机通过这个来告诉服务器,客户机的软件环境。
9.Cookie:客户机通过这个头向服务器带给一些信息。
10.Connection:客户机通过这个头来确定我这次请求完成,连接是否关闭。(close/Keep-Alive).
以上就是消息头主要常用的几个头,还有很多,我们只说常用的。
二.在说响应头:
状态行:http协议的版本号,200状态码,原因叙述
状态码
100-199——————表示成功接受请求,要求客户端继续提交下一次请求才能完成整个的处理过程
200-299——————表示成功接受请求,并已完成整个的处理过程
300-399——————未完成请求,客户需要进一步细化请求,例如请求的资源已经移动一个新的地址,302(你请求,我要你去找别人),304和307要客户机去拿缓存。
400-499——————客户端请求有错误,
500-599——————服务器端出现错误
多个响应头:
Location:这个头配合302状态码使用,用于告诉客户机去找谁
Server:服务器通过这个头告诉浏览器服务器的类型
Content-Encoding:服务器通过这个头告诉浏览器,我要的数据压缩格式
Content-Length:服务器通过这个头,告诉浏览器回送数据压缩的长度
Content-Type:服务器通过这个头告诉浏览器回送数据的类型
Last-Modified:用来告诉浏览器缓存时间。
Transfer-Encoding:告诉浏览器数据的传送方式
refresh:控制浏览器多长时间刷新一次(股票,聊天室)
content-disposition:服务器通过这个头告诉浏览器数据以下载方式打开数据
Etag: 和缓存相关的头,这个能保证"实时更新",用在对实时更新要求比较高的网站
Expires:服务器通过这个头告,诉浏览器回送的资源缓存多上时间,-1,0代表不缓存,date
cache-control: no cache 和 Pragma: no cache :服务器通过这个两个头告,诉浏览器不要缓存数据
如果你想市面上的所有的浏览器不缓存你的数据,Expires,cache-control,Pragma都写上就可以了。
未完待续---21:33
下面代码演示,看一看响应头有什么作用,这里面我把测试代码都放在了方法里,如果你想测试别的,复制,或者引用都行,
1 package com.du.servlet; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.File; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.OutputStream; 9 import java.io.PrintWriter; 10 import java.util.zip.GZIPOutputStream; 11 12 import javax.servlet.ServletException; 13 import javax.servlet.http.HttpServlet; 14 import javax.servlet.http.HttpServletRequest; 15 import javax.servlet.http.HttpServletResponse; 16 17 public class ServletDemo1 extends HttpServlet { 18 19 public void destroy() { 20 super.destroy(); 21 22 } 23 24 25 public void doGet(HttpServletRequest request, HttpServletResponse response) 26 throws ServletException, IOException { 27 //把想测试的响应头代码放在doGet方法里 28 } 29 30 31 /** 32 * 让浏览器以什么方式打开数据,content-disposition 33 * @param response 34 * @throws IOException 35 */ 36 private void test5(HttpServletResponse response) throws IOException { 37 response.setHeader("content-disposition", "attachment;filename=duwenlei.png"); 38 39 InputStream in = this.getServletContext().getResourceAsStream("1.png"); 40 int len; 41 byte[] buffer = new byte[1024]; 42 OutputStream out = response.getOutputStream(); 43 while((len = in.read(buffer)) > 0){ 44 out.write(buffer, 0, len); 45 } 46 } 47 48 49 /** 50 * 通过refresh头,来控制浏览器多长时间刷新一次 51 * @param response 52 * @throws IOException 53 */ 54 private void test4(HttpServletResponse response) throws IOException { 55 String data = "bbbbbbbbbbbbbbb"; 56 response.setHeader("refresh", "3");//3秒刷新一次 57 // response.setHeader("refresh", "3;url='http://www.baidu.com'"); 三秒后跳转到百度,用于注册成功跳转首页效果 58 response.getOutputStream().write(data.getBytes()); 59 } 60 61 62 /** 63 * 向网页写一张图片,通过Content-type告诉浏览器返回的数据类型 64 * @param response 65 * @throws IOException 66 */ 67 private void test3(HttpServletResponse response) throws IOException { 68 InputStream in = this.getServletContext().getResourceAsStream("1.png"); 69 int len; 70 byte[] buffer = new byte[1024]; 71 //这个Content-Encoding 的类型在tomcat/conf/web.xml里存在,web.xml包含市面上 72 //几乎所有的文件类型和对应的mime-type 73 response.setHeader("Content-type", "image/png"); 74 OutputStream out = response.getOutputStream(); 75 while((len = in.read(buffer)) > 0){ 76 out.write(buffer, 0, len); 77 } 78 } 79 80 /** 81 * 利用状态码302,配合location实现重定向 82 * @param response 83 */ 84 public void test(HttpServletResponse response){ 85 response.setStatus(302); 86 response.setHeader("location", "2.html"); 87 } 88 89 /** 90 * 通过Content-Encoding头和Content-Length,来实现浏览器识别gzip格式数据 91 * 注意:这里的data的数据量要大一点,否则你会发现,数据一压反而大了 92 * @param response 93 * @throws Exception 94 */ 95 public void test1(HttpServletResponse response) throws Exception{ 96 97 String data = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; 98 System.out.println("压缩前数据:" + data.getBytes().length + "字节"); 99 100 //byteArray往内存里写 101 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 102 103 // (GZIPOutputStream)包装流————>写入————>底层流(bout) 104 GZIPOutputStream gout = new GZIPOutputStream(bout); 105 106 gout.write(data.getBytes()); 107 //这里有一个限制,包装流有一个缓冲,如果说你的数据没有放慢这个缓冲, 108 //那么包装流就写不进底层流。怎么解决呢,很简单,我们把包装流关闭 109 //他就可以写到底层流了 110 gout.close(); 111 112 byte[] gzip = bout.toByteArray(); //得到压缩数据 113 114 System.out.println("压缩后数据:" + gzip.length + "字节"); 115 116 //通知浏览器数据采用的压缩格式 117 response.setHeader("Content-Encoding", "gzip"); 118 119 //这里还要通知浏览器数据的长度 120 response.setHeader("Content-Length", gzip.length+""); 121 122 //response.getOutputStream(),拿到浏览器的一个输出流,把压缩后的数据输出 123 response.getOutputStream().write(gzip); 124 125 } 126 127 128 public void doPost(HttpServletRequest request, HttpServletResponse response) 129 throws ServletException, IOException { 130 } 131 132 133 public void init() throws ServletException { 134 135 } 136 137 }
这里有一个range头,用这个头来实现断点下载,我这里那出来单说,这个是Http请求头的字段,对于这个range头,你得要服务器支持才行
tomcat5不支持,从tomcat6以后支持,所以,要检查下你的服务器支不支持。
断点下载就是,如果浏览器下载一个文件,下载到一半,突然断网了,适用于这个情况,断网了,但是我们已经下载了一部分,当有网的时候,我们不可能在去重新的去下载这个文件,我们要接着继续下载这个文件以后的内容。
range有三种格式来设置传输字节的范围
1.range:bytes=1000-2000 传输从1000到2000字节
2.range:bytes=1000- 传输web资源1000字节以后的所有内容
3.range:bytes=1000 传输最后1000字节
1 URL url = new URL("http://localhost:8080/day02/a.txt"); 2 //我们这里是http协议,所以我们要用HttpURLConnection 3 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 4 //打开了连接我们要设置range请求头,我们这里假设已经往我的本地下载了5个字节 5 //现在我们要下载5往后的数据 6 conn.setRequestProperty("range", "bytes=5-"); 7 //拿到一个写入流 8 InputStream in = conn.getInputStream(); 9 //这里要注意,我们之前已经下载了5个字节,现在要做的是在这5个字节后面追加 10 //查api我们知道FileOutputStream(url,boolean),后面这个参数是问你是否 11 //续写,默认是false,在这里改成打开 12 FileOutputStream out = new FileOutputStream("E:\\b.txt",true); 13 14 //模版方法 15 int len; 16 byte[] buffer = new byte[1024]; 17 while((len = in.read(buffer)) > 0){ 18 out.write(buffer, 0, len); 19 } 20 in.close(); 21 out.close();
ok,打完。