HTTP协议

一.HTTP协议简介
  HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程。客户端连上web服务器后,若想获得web服务器中的某个web资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器通迅的格式。
  HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。
1)协议对于事务处理没有记忆能力【事物处理】【记忆能力】
2)对同一个url请求没有上下文关系【上下文关系】
3)每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况【无直接联系】【受直接影响】
4)服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器【状态】
无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大另一方面,在服务器不需要先前信息时它的应答就较快。
二.HTTP1.0和1.1的区别
我们知道HTTP的底层协议是TCP协议,HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。这也造成了一些性能上的缺陷,例如,一个包含有许多图像的网页文件中并没有包含真正的图像数据内容,而只是指明了这些图像的URL地址,当WEB浏览器访问这个网页文件时,浏览器首先要发出针对该网页文件的请求,当浏览器解析WEB服务器返回的该网页文档中的HTML内容时,发现其中的图像标签后,浏览器将根据标签中的src属性所指定的URL地址再次向服务器发出下载图像数据的请求。这样访问一个页面时会产生多次连接,影响性能。
HTTP1.1针对HTTP1.0进行了改进,HTTP 1.1支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。持久链接对应的请求头为Connection:keep alive(HTTP1.1新增),如请求完成需要关闭,则变为Connection:close
同时HTTP1.1还增加了响应头RANGE:bytes。HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。RANGE:bytes=XXXX表示要求服务器从文件XXXX字节处开始传送,这就是我们平时所说的断点续传!也就是说HTTP1.1支持文件断点续传。
三.HTTP请求
 客户端连上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送了一个HTTP请求。
一个完整的HTTP请求包括如下内容:一个请求行、若干消息头、以及实体内容。

我们来看一个完整的HTTP请求实例(我们可以去下载一个HTTPWatch的抓包工具,不过这个抓包工具只适用于IE,好久都没用IE了)

POST /MyHttpDemo/TestPost HTTP/1.1          //请求行
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Referer: http://localhost:8080/MyHttpDemo/TestPost.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 28
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=E26BB93C6549F6EF060D7EED3232A4DA

username=%E5%A4%A7&pwd=11111            //实体内容

1)请求行
请求行中的POST为请求方式,我们通过阅读HTTPServlet抽象类的源码可知,请求方式有:POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT,常用的有: GET、 POST,早期的Web MVC框架设计者们并没有有意识地将URL当作抽象的资源来看待和设计,所以导致一个比较严重的问题是传统的Web MVC框架基本上都只支持GET和POST两种HTTP方法,而不支持PUT和DELETE方法。随着架构的发展,现在出现REST(Representational State Transfer),一套支持HTTP规范的新风格,
用户如果没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输地址访问,点超链接访问等都是get,用户如想把请求方式改为post,可通过更改表单的提交方式实现。
一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。(以后实现restful接口会讲到)
也就是说其实一开始设计的初衷是GET方式对应查询,POST方式对应修改。
由于现在常用的是POST和GET方式。我们有必要了解POST方式和GET方式。
I,在数据传递上:
GET方式数据跟在请求行中的URL后面,再URL后?的形式将数据带给服务器,数据大小有限制,一般不能超过1K。(因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。注意这是限制是整个URL长度,而不仅仅是你的参数值数据长度。
POST方式将数据放在请求体中,没有数据大小限制
II,安全性
POST的安全性要比GET的安全性高。比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击。Get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求,在FORM(表单)中,Method默认为”GET”,实质上,GET和POST只是发送机制不同,并不是一个取一个发!
2)消息头
HTTP请求中的常用消息头

  accept:浏览器通过这个头告诉服务器,它所支持的数据类型
  Accept-Charset: 浏览器通过这个头告诉服务器,它支持哪种字符集
  Accept-Encoding:浏览器通过这个头告诉服务器,支持的压缩格式
  Accept-Language:浏览器通过这个头告诉服务器,它的语言环境
  Host:浏览器通过这个头告诉服务器,想访问哪台主机
  If-Modified-Since: 浏览器通过这个头告诉服务器,缓存数据的时间
  Referer:浏览器通过这个头告诉服务器,客户机是哪个页面来的 防盗链
  Connection:浏览器通过这个头告诉服务器,请求完后是断开链接还是何持链接
3)请求体
提交给服务器的数据
四.HTTP响应头
一个HTTP响应代表服务器向客户端回送的数据,它包括: 一个状态行、若干消息头、以及实体内容 。
这里写图片描述
1)状态行
例:HTTP1.1 200 ok
状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类,如下所示:
这里写图片描述
302重定向,307请求转发
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
3)响应体
返回给浏览器的信息
五.利用响应头来控制浏览器的行为
1)利用Location实现请求重定向

package wangcc.header;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;

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

@WebServlet("/HeaderTest")
public class HeaderTest extends HttpServlet {

    /**
     * Constructor of the object.
     */
    public HeaderTest() {
        super();
    }

    /**
     * Destruction of the servlet. <br>
     */
    public void destroy() {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
    }

    /**
     * The doGet method of the servlet. <br>
     * 
     * This method is called when a form has its tag value method equals to get.
     * 
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // testLocation(response);
        try {
            testdownload(response);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    /**
     * The doPost method of the servlet. <br>
     * 
     * This method is called when a form has its tag value method equals to
     * post.
     * 
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

    }

    /**
     * Initialization of the servlet. <br>
     * 
     * @throws ServletException
     *             if an error occurs
     */
    public void init() throws ServletException {
        // Put your code here
    }

    // 状态码302
    // 当状态码为300~399时,表示为完成请求,客户需要进一步细化请求,例如请求的资源被移动到另一个地址
    // 常用的有302,304,307
    // 302等同于重定向,这个马上会说到,先带一下这个点
    // 对于状态码302,使用get方式请求,会自动重定位到新的位置
    // 但是对于post方式,需要用户确认是否重定向到新位置,但是现在很多浏览器都默认这种情况会重定向

    public void testLocation(HttpServletResponse response) {
        response.setStatus(302);
        // 这里在看一下/ /在这里代表什么呢?
        // 代表webapps目录,服务器根目录,在这里即代表路径http://localhost:8080
        // 所以全路径http://localhost:8080/aa/index.html
        // 为什么呢,因为这里是将/aa/index.html返回给浏览器
        // 让浏览器去请求/aa/index.html这个地址,也就是说/是给浏览器用的
        // 当/是给浏览器用的时候,就代表webapps目录,服务器根目录
        response.setHeader("Location", "/aa/index.html");
    }

    // public void testContentEncoding(HttpServletResponse response)
    // throws IOException {
    // String data = "中国,江西,特别,就将,九江,武宁,巾口";
    // ByteArrayOutputStream bout = new ByteArrayOutputStream();
    // GZIPOutputStream gzip = new GZIPOutputStream(bout);
    // gzip.write(data.getBytes());
    // gzip.close();
    // String value = bout.toString();
    // System.out.println(value);
    // }
    public void testContentType(HttpServletResponse response)
            throws IOException {
        response.setHeader("content-type", "image/jpeg");
        String path = this.getServletContext().getRealPath("/img/IMG_4206.JPG");
        InputStream in = new FileInputStream(path);
        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 testRefresh(HttpServletResponse response) throws IOException {
        response.setHeader("refresh", "3;url='http://www.baidu.com'");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("王聪冲");
    }

    public void testdownload(HttpServletResponse response) throws IOException {
        response.setHeader("content-disposition", "attachment;filename="
                + URLEncoder.encode("凯尔特人队训", "UTF-8") + ".jpg");
        String path = this.getServletContext().getRealPath("/img/IMG_4206.JPG");
        FileInputStream in = new FileInputStream(path);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }

    }

}
    public void testLocation(HttpServletResponse response) {
        response.setStatus(302);
        // 这里在看一下/ /在这里代表什么呢?
        // 代表webapps目录,服务器根目录,在这里即代表路径http://localhost:8080
        // 所以全路径http://localhost:8080/aa/index.html
        // 为什么呢,因为这里是将/aa/index.html返回给浏览器
        // 让浏览器去请求/aa/index.html这个地址,也就是说/是给浏览器用的
        // 当/是给浏览器用的时候,就代表webapps目录,服务器根目录
        response.setHeader("Location", "/aa/index.html");
    }

当使用浏览器访问URL为 http://localhost:8080/MyHttpDemo/TestHeader 的资源时,Servlet容器(这里为Tomcat)初始化HeaderTest这个Servlet,调用其构造方法,由于他没有重写init(ServletConfig config)方法或init()方法,所以直接只调用父类的父类GenericServlet的nit(ServletConfig config)方法,将容器相关信息初始化,然后调用HTTPServlet重写的Service方法,进入该方法后,调用被HeaderTest重写的doGet方法(动态绑定)。然后调用testLocation方法。
HTTP响应为:
这里写图片描述
我们首先将状态码设置好
response.setStatus(302);
然后设置响应头
response.setHeader(“Location”, “/aa/index.html”);
 服务器返回一个302状态码告诉浏览器,你要的资源我没有,但是我通过Location响应头告诉你哪里有,而浏览器解析响应头Location后知道要跳转到页面http://localhost:8080/aa/index.html.
这里注意/到底代表什么?
一句话,给浏览器用的就代表webapps目录,服务器的根目录,这里是http://localhost:8080/
如果是给服务器用就代表项目的根目录,这里就是http://localhost:8080/MyHttpDemo/
另外一种实现重定向的方法
requeset.senRedirect(url);
在执行这个方法时,内部已经执行了
response.setStatus(302);
然后设置响应头
response.setHeader(“Location”,url);

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

public void testContentType(HttpServletResponse response)
            throws IOException {
        response.setHeader("content-type", "image/jpeg");
        String path = this.getServletContext().getRealPath("/img/IMG_4206.JPG");
        InputStream in = new FileInputStream(path);
        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);// 将缓冲区里面的内容输出到浏览器
        }
    }

响应信息为:
这里写图片描述
3)设置content-disposition响应头,让浏览器下载文件

    public void testdownload(HttpServletResponse response) throws IOException {
        response.setHeader("content-disposition", "attachment;filename="
                + URLEncoder.encode("凯尔特人队训", "UTF-8") + ".jpg");
        String path = this.getServletContext().getRealPath("/img/IMG_4206.JPG");
        FileInputStream in = new FileInputStream(path);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }

    }

响应信息为:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值