Java Web基础入门第十二讲 HTTP协议

什么是HTTP协议?

HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程。客户端连上WEB服务器后,若想获得WEB服务器中的某个WEB资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与WEB服务器通迅的格式。
HTTP协议是学习JavaWeb开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。

HTTP协议的版本

HTTP协议的版本有HTTP/1.0和HTTP/1.1。

HTTP1.0和HTTP1.1的区别

在HTTP1.0协议中,客户端与WEB服务器建立连接后,只能获得一个WEB资源;而HTTP1.1协议,允许客户端与WEB服务器建立连接后,在一个连接上获取多个WEB资源。
例如,有这样一个问题:一个web页面中,使用img标签引用了三幅图片,当客户端访问服务器中的这个web页面时,客户端总共会访问几次服务器,即向服务器发送了几次HTTP请求?服务器中的web页面为index.html,内容如下:

aaaaaaaaaaaaaaaaaaa

<img src="1.jpg" />
<img src="2.jpg" />
<img src="3.jpg" />

此时通过Chrome浏览器访问服务器中的index.html。
在这里插入图片描述
可发现客户端向服务器发送了4次HTTP请求,第一次获取到整个页面资源。第二次浏览器向服务器要1.jpg,然后依次向服务器要2.jpg、3.jpg。为了减少客户端向浏览器发送的请求数,减少服务器的压力,通常会利用css技术将多张图片归并为一张图片,请求时,只打开这张图片的一小部分。

HTTP请求

HTTP请求包括的内容

客户端连上服务器后,向服务器请求某个WEB资源,称之为客户端向服务器发送了一个HTTP请求。
在这里插入图片描述
例如,
在这里插入图片描述
WEB服务器通过客户端发送过来的这些请求信息,就可以确定向请求者回送什么资源,以及根据客户端的环境信息采用什么方式进行回送等。

HTTP请求的细节——请求行

请求行中的GET称之为请求方式,请求方式有以下几种:
在这里插入图片描述
不管POST或GET,都用于向服务器请求某个WEB资源,这两种方式的区别主要表现在数据传递上。
在这里插入图片描述
在这里插入图片描述

HTTP请求的细节——请求头

在这里插入图片描述
例如:

Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Referer: http://localhost:8080/examples/servlets/servlet/RequestParamExample
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: 31
Connection: Keep-Alive
Cache-Control: no-cache

HTTP响应

HTTP响应包括的内容

一个HTTP响应代表服务器向客户端回送的数据。
在这里插入图片描述
例如,
在这里插入图片描述
在一个HTTP响应中,WEB服务器通过响应头向WEB客户端描述客户端的请求成功与否,以及它所发送的数据类型等一些信息,客户端通过这些信息,进而可以知道如何对数据进行处理。

HTTP响应的细节——状态行

状态行格式为HTTP版本号 状态码 原因叙述<CRLF>。例,HTTP/1.1 200 OK。状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类,如下表所示:
在这里插入图片描述
这里还是细说几个常见的状态码。
在这里插入图片描述

HTTP响应细节——常用响应头

在这里插入图片描述

在服务端设置响应头来控制客户端浏览器的行为

新建一个动态web项目——day04,该项目的结构图如下:
在这里插入图片描述

设置Location响应头,实现请求重定向

在这里插入图片描述
当在Chrome浏览器中使用URL地址http://localhost:8080/day04/ServletDemo1访问ServletDemo1时,就可以看到服务器作出响应后发送到浏览器的状态码和响应头信息,如下图所示:
在这里插入图片描述
服务器返回一个302状态码告诉浏览器,你要的资源我没有,但是我通过location响应头告诉你哪里有,而浏览器解析响应头location后知道要跳转到/day04/1.html页面,所以就会自动跳转到1.html,如下图所示:
在这里插入图片描述

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

在这里插入图片描述
怎么实现数据的压缩?那就需要使用GZIPOutputStream流来压缩数据了。

package cn.liayun.web.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

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("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test2(response);
	}

	// 压缩数据并输出
	private void test2(HttpServletResponse response) throws IOException {
		String data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
				+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
				+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
				+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
				+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
				+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
		System.out.println("原始数据大小:" + data.getBytes().length);

		ByteArrayOutputStream bout = new ByteArrayOutputStream();// 内存里面的一个字节数组

		GZIPOutputStream gout = new GZIPOutputStream(bout);
		gout.write(data.getBytes());
		gout.close();

		byte[] gzip = bout.toByteArray();// 得到压缩后的数据
		System.out.println("压缩后的大小:" + gzip.length);

		// 通知浏览器,数据采用了压缩格式
		response.setHeader("Content-Encoding", "gzip");
		response.setHeader("Content-Length", gzip.length + "");
		response.getOutputStream().write(gzip);
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

服务器发给浏览器的响应信息如下:
在这里插入图片描述
此时Eclipse控制台打印如下信息:
在这里插入图片描述

设置content-type响应头,控制浏览器以哪种方式处理数据

package cn.liayun.web.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test3(response);
	}
	
	// 通过content-type头字段,控制浏览器以那种方式处理数据
	private void test3(HttpServletResponse response) throws IOException {
		response.setHeader("content-type", "image/jpeg");

		InputStream in = this.getServletContext().getResourceAsStream("/1.jpeg");
		int len = 0;
		byte[] buffer = new byte[1024];

		OutputStream out = response.getOutputStream();
		while ((len = in.read(buffer)) > 0) {
			out.write(buffer, 0, len);
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

提示:Content-Type头字段对应的值可通过Tomcat服务器下conf/web.xml文件查找。
服务器发给浏览器的响应信息和ServletDemo1的运行结果(在浏览器中显示出了图片)如下图所示:
在这里插入图片描述

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

package cn.liayun.web.servlet;

import java.io.IOException;

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("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test4(response);
	}
	
	// 定时刷新
	private void test4(HttpServletResponse response) throws IOException {
		response.setHeader("refresh", "3;url='http://www.sina.com.cn'");

		String data = "aaaaaaaaaa";
		response.getOutputStream().write(data.getBytes());
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

浏览器隔了3秒钟请求一次后,将会刷新到新浪上去。

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

package cn.liayun.web.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test5(response);
	}
	
	private void test5(HttpServletResponse response) throws IOException {
		response.setHeader("content-disposition", "attachment;filename=2.jpg");

		InputStream in = this.getServletContext().getResourceAsStream("/2.jpg");
		int len = 0;
		byte[] buffer = new byte[1024];

		OutputStream out = response.getOutputStream();
		while ((len = in.read(buffer)) > 0) {
			out.write(buffer, 0, len);
		}
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

在Chrome浏览器中访问ServletDemo1就会弹出文件下载框,如下图所示:
在这里插入图片描述
点击在文件夹中显示,可以发现服务器端的2.jpg文件已经被下载到了本机中。

HTTP的一个实用头字段——Range

HTTP请求头字段

Range头指示服务器只传输一部分WEB资源。这个头可以用来实现断点续传功能。
在这里插入图片描述
例如,WEB服务器有一个资源,比如是a.txt,内容如下:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

有一个用户下载了一部分数据,并存储到D盘中的a.txt中,内容为:

aaaaa

此时该用户想接着下载完剩下的数据,该怎么做呢?此时他就不能通过浏览器去访问了,而应该自己写程序去访问指定的资源。

package cn.liayun.ie;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class RangeDemo {

	public static void main(String[] args) throws Exception {
		URL url = new URL("http://localhost:8080/day04/a.txt");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		
		conn.setRequestProperty("Range", "bytes=5-");
		
		InputStream in = conn.getInputStream();
		int len = 0;
		byte[] buffer = new byte[1024];
		FileOutputStream out = new FileOutputStream("d:\\a.txt", true);
		while ((len = in.read(buffer)) > 0) {
			out.write(buffer, 0, len);
		}
		
		in.close();
		out.close();
	}

}

运行以上程序,该用户就下载完剩下的数据了。

HTTP响应头字段

需要说明的是HTTP响应头字段不常用。

  • Accept-Ranges:这个字段说明WEB服务器是否支持Range,支持则返回Accept-Ranges: bytes;如果不支持,则返回Accept-Ranges: none
  • Content-Range:指定了返回的WEB资源的字节范围。这个字段值的格式类似Content-Range: 1000-3000/5000这样。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李阿昀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值