【J2EE核心开发学习笔记 006】HTTP协议

来源:互联网 发布:保达软件 编辑:程序博客网 时间:2024/06/05 21:17

一、HTTP协议简介

提起HTTP协议我想大家都不陌生,我们经常上网访问网页就是使用它,它是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程。HTTP是WEB开发必备知识,对于管理和维护WEB站点很有用处。HTTP协议的版本分为:HTTP/1.0、HTTP/1.1。

HTTP1.0协议:客户端与web服务器建立连接后,只能获得一个web资源,在获取资源之后就断开连接。

HTTP1.1协议:允许客户端与web服务器建立连接后,在一个连接上获取多个web资源都不会断开连接,除非是访问出错和手动断开连接。

在Socket编程中,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干。HTTP协议传输的消息也是这样规定的,每一个HTTP包都分为HTTP头和HTTP体两部分,消息体是可选的,而消息头是必须的。每当我们打开一个网页,在上面点击右键,选择“查看源文件”,这时看到的HTML代码就是HTTP的消息体,而消息头可以通过浏览器的开发工具或者插件可以看到,比如火狐的Firebug,IE的Httpwatch,接下来我们分析一下HTTP请求和相应的详细过程。

二、HTTP请求格式

客户端通过发送 HTTP 请求向服务器请求对资源的访问。 它向服务器传递了一个数据块,也就是请求信息,HTTP 请求由三部分组成:请求行、  请求头和请求正文。


(1) 请求行

请求行用于描述客户端的请求方式、请求的资源名称以及使用的HTTP协议版本号。根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。

用户如果没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输地址访问,点超链接访问等都是get,用户如想把请求方式改为post,可通过更改表单的提交方式实现。不管POST或GET,都用于向服务器请求某个WEB资源,这两种方式的区别主要表现在数据传递上:如果请求方式为GET方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔,例如:GET /test/test.html?name=aaa&password=aaa HTTP/1.1,GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。如果请求方式为POST方式,则可以在请求的实体内容中向服务器发送数据,Post方式的特点:传送的数据量无限制。

HTTP1.1 中的请求方式:


(2) 请求头

每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。

HTTP请求中的常用消息头
accept:浏览器通过这个头告诉服务器,它所支持的数据类型
Accept-Charset: 浏览器通过这个头告诉服务器,它支持哪种字符集
Accept-Encoding:浏览器通过这个头告诉服务器,支持的压缩格式
Accept-Language:浏览器通过这个头告诉服务器,它的语言环境
Host:浏览器通过这个头告诉服务器,想访问哪台主机
If-Modified-Since: 浏览器通过这个头告诉服务器,缓存数据的时间
Referer:浏览器通过这个头告诉服务器,客户机是哪个页面来的 防盗链
Connection:浏览器通过这个头告诉服务器,请求完后是断开链接还是保持链接

三、HTTP响应格式

在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。

(1) 状态行

状态行由协议版本、数字形式的状态代码,及相应的状态描述组成,各元素之间以空格分隔。HTTP版本号 状态码 原因叙述<CRLF>

例如:HTTP/1.1 200 OK

状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。第一个数字有 5 种取值,如下所示。

    1xx:指示信息——表示请求已经接受,继续处理
    2xx:成功——表示请求已经被成功接收、理解、接受。
    3xx:重定向——要完成请求必须进行更进一步的操作
    4xx:客户端错误——请求有语法错误或请求无法实现
    5xx:服务器端错误——服务器未能实现合法的请求。

常见状态代码、状态描述、说明:


(2) 响应头信息

HTTP响应中的常用响应头(消息头)
  Location: 服务器通过这个头,来告诉浏览器跳到哪里
  Server:服务器通过这个头,告诉浏览器服务器的型号
  Content-Encoding:服务器通过这个头,告诉浏览器,数据的压缩格式
  Content-Length: 服务器通过这个头,告诉浏览器回送数据的长度
  Content-Language: 服务器通过这个头,告诉浏览器语言环境
  Content-Type:服务器通过这个头,告诉浏览器回送数据的类型
  Refresh:服务器通过这个头,告诉浏览器定时刷新
  Content-Disposition: 服务器通过这个头,告诉浏览器以下载方式打数据
  Transfer-Encoding:服务器通过这个头,告诉浏览器数据是以分块方式回送的
  Expires: -1  控制浏览器不要缓存
  Cache-Control: no-cache  
  Pragma: no-cache

四、在服务端设置响应头来控制客户端浏览器

(1) 设置Location响应头,实现请求重定向获取WEB应用的初始化参数

package bobo.servlet.study;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * @author DaveBobo * */public class ServletDemo01 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setStatus(302);//设置服务器的响应状态码        /**         *设置响应头,服务器通过 Location这个头,来告诉浏览器跳到哪里,这就是所谓的请求重定向         */        response.setHeader("Location", "/JavaWeb_Servlet001/1.jsp");    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}
当在浏览器中使用URL地址"http://localhost:8080/JavaWeb_Servlet001/servlet/ServletDemo01"访问ServletDemo01时,就可以看到服务器作出响应后发送到浏览器的状态码和响应头信息,如下图所示:

服务器返回一个302状态码告诉浏览器,你要的资源我没有,但是我通过Location响应头告诉你哪里有,而浏览器解析响应头Location后知道要跳转到/JavaWeb_Servlet001/1.jsp页面,所以就会自动跳转到1.jsp,如下图所示:


(2) 设置Content-Encoding响应头,告诉浏览器数据的压缩格式

package bobo.servlet.study;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.zip.GZIPOutputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * @author DaveBobo *这个小程序是用来演示以下两个小知识点 *1、使用GZIPOutputStream流来压缩数据 *2、设置响应头Content-Encoding来告诉浏览器,服务器发送回来的数据压缩后的格式 */public class ServletDemo02 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        String data = "abcdabcdabcdabcdabcdabcdab" +                "cdabcdabcdabcdabcdabcdabcdabcdabc" +                "dabcdabcdabcdabcdabcdabcdabcdabc" +                "dabcdabcdabcdabcdabcdabcdabcdabcdab" +                "cdabcdabcdabcdabcdabcdabcdabcdabcdab" +                "cdabcdabcdabcdabcdabcdabcdabcdabcdab" +                "cdabcdabcdabcdabcdabcdabcdabcdabcdab" +                "cdabcdabcdabcdabcdabcdabcdabcdabcdabcd";        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();        response.setHeader("Content-Encoding", "gzip");        response.setHeader("Content-Length",g.length +"");        response.getOutputStream().write(g);    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

(3) 设置content-type响应头,指定回送数据类型

package bobo.servlet.study;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ServletDemo03 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        /**         * 浏览器能接收(Accept)的数据类型有:          * application/x-ms-application,          * image/jpeg,          * application/xaml+xml,          * image/gif,          * image/pjpeg,          * application/x-ms-xbap,          * application/vnd.ms-excel,          * application/vnd.ms-powerpoint,          * application/msword,          */        response.setHeader("content-type", "image/jpeg");//使用content-type响应头指定发送给浏览器的数据类型为"image/jpeg"        //读取位于项目根目录下的img文件夹里面的head.jpg这张图片,返回一个输入流        InputStream in = this.getServletContext().getResourceAsStream("/img/head.jpg");        byte buffer[] = new byte[1024];        int len = 0;        OutputStream out = response.getOutputStream();//得到输出流        while ((len = in.read(buffer)) > 0) {//读取输入流(in)里面的内容存储到缓冲区(buffer)            out.write(buffer, 0, len);//将缓冲区里面的内容输出到浏览器        }    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}
服务器发给浏览器的响应信息如下:


(4) 设置refresh响应头,让浏览器定时刷新

package bobo.servlet.study;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ServletDemo04 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        /**         * 设置refresh响应头,让浏览器每隔3秒定时刷新         */        // response.setHeader("refresh", "3");        /**         * 设置refresh响应头,让浏览器3秒后跳转到http://www.baidu.com         */        response.setHeader("refresh", "3;url='http://www.baidu.com'");        response.getWriter().write("DaveBobo");    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

(5)设置content-disposition响应头,让浏览器下载文件

package bobo.servlet.study;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class ServletDemo05 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        /**         * 设置content-disposition响应头,让浏览器下载文件         */        response.setHeader("content-disposition", "attachment;filename=xxx.jpg");        InputStream in = this.getServletContext().getResourceAsStream("/img/head.jpg");        byte buffer[] = new byte[1024];        int len = 0;        OutputStream out = response.getOutputStream();        while ((len = in.read(buffer)) > 0) {            out.write(buffer, 0, len);        }    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}<a target=_blank target="_blank" name="top"></a>


0 0
原创粉丝点击