概述:
HTTP不管是在面试,还是在工作过程中运用的比较广泛,但对绝大部分的软件开发工程师对于HTTP协议的理解程度却远远不够。这篇文章可以让你全方位的理解什么是HTTP并掌握HTTP协议。
HTTP定义
Hyper Transfer protocol 超文本传输协议
什么是传输协议
传输协议:定义了客户端和服务器端通信时,发送数据的格式
流程图
image.pngHTTP协议的特点
1.基于TCP/IP的高级协议
2.默认端口:80
3.基于请求/响应模型。1次请求对应一次响应
4.无状态的:每次请求之间相互独立,不能交互数据
历史版本
1.0:每一次请求响应都会建立新的连接
1.1:复用连接
请求消息数据格式
1.请求行
请求方式 请求url 请求协议/版本
例如:GET /login.xml HTTP/1.1
请求方式:
Http协议有7种请求方式,常用的有2种
GET:
1.请求参数,在请求行中 在url后
2.请求的url长度是有限制的
3.get请求不太安全
POST:
1.请求参数在请求体中
2.请求的URL长度是没有限制的
3.post请求是安全的
HEAD:
HEAD方法与GET方法相同,但没有响应体,仅传输状态行和标题部分。这对于恢复相应头部编写的元数据非常有用,而无需传输整个内容。
PUT:
PUT方法用于将数据发送到服务器以创建或更新资源,它可以用上传的内容替换目标资源中的所有当前内容。它会将包含的元素放在所提供的URI下,如果URI指示的是当前资源,则会被改变。如果URI未指示当前资源,则服务器可以使用该URI创建资源。
DELETE:
DELETE方法用来删除指定的资源,它会删除URI给出的目标资源的所有当前内容。
CONNECT:
CONNECT方法用来建立到给定URI标识的服务器的隧道;它通过简单的TCP / IP隧道更改请求连接,通常实使用解码的HTTP代理来进行SSL编码的通信(HTTPS)
OPTIONS:
OPTIONS方法用来描述了目标资源的通信选项,会返回服务器支持预定义URL的HTTP策略。
TRACE:
TRACE方法用于沿着目标资源的路径执行消息环回测试;它回应收到的请求,以便客户可以看到中间服务器进行了哪些(假设任何)进度或增量。
2.请求头
格式
请求头的名称:请求头的值
常见的请求头
User-Agent :浏览器告诉服务器,我访问你使用的浏览器版本信息,可以在服务器端获取该头的信息,解决浏览器的兼容性问题
Referer:告诉服务器,当前请求的从哪里来
作用:1.防止盗用 2.统计
3.请求空行
空行
4.请求体 (正文)
响应消息数据格式
1.request和response对象的原理
image.png1.request和response是由服务器创建的,我们只是使用它们
2.request对象是来获取请求消息的。response对象是来设置响应消息
2.request:获取请求消息
3.request继承体系结构
ServletRequest。 ——>接口
|
| 继承
|
HttpServletRequest ——>接口
|
| 实现HttpServletRequest接口
|
RequestFacade (类tomcat)
4.request功能
1.获取请求消息数据
1.获取请求行消息
*请求方式 请求url 请求协议/版本
例如:GET /day04/demo1?username=zhangsan HTTP/1.1
*方法 :
1.获取请求方式GET
String getMethod()
2.获取虚拟目录:/day04
*String getContextPath()
3.获取servlet路径。/demo1
*String getServletPath()
4.获取get请求参数:username=zhangsan
*String getQueryString();
5.获取请求的url
*String getRequestURI();/day04/demo1
*StringBuffer getRequestURL();http://localhost/day04/demo1
URL和URI是什么
URL:统一资源定位符
URI:统一资源标识符
URI的范围大于URL
6.获取协议及版本 HTTP/1.1
*String getProtocal();
7.获取客户机的ip地址
*String getRemoteAddr();
2.获取请求头消息
方法:
String getHeader(String name);通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames();获取所有的请求头的名称
3.获取请求体消息
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
步骤:
1.获取流对象
BufferedReader getReader(). 获取字符输入流,只能操作字符数据
ServletInputStream getInputStream();获取字节输入流,可以操作所有的类型数据
2.再从流对象中拿数据
2.其他功能
1.获取请求参数 通用方式
*String getParameter(String name)根据参数名称获取参数值
- String[] getParameterValues(String name);根据参数值名称获取参数值的数组 多用于复选框
*Enumeration<String> getParameterNames();获取所有的参数名称
*Map<String,String[]> getParameterMap();
中文乱码问题:
get方式 : tomcat 8 已经解决
post方式:乱码 解决:在获取参数之前设置编码
2.请求转发:一种在服务器内部的资源跳转方式
通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path).
使用RequestDispatcher对象进行转发:forward(ServletRequest request,ServletResponse response)
特点:
1.浏览器地址栏路径没有发生变化
2.只能转发到当前的服务器资源中
3.转发是一次请求
3.共享数据
1.域对象:一个有作用范围的对象,可以在范围内共享数据
2.request的域:一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
1.setAttribute(String name,Object object); 存储数据
2.Object getAttribute(String name);通过键值获取
3.removeAttribute(String name);通过键移除键值对
Response响应
1. 响应行
1格式 :协议/版本 响应的状态码 状态码描述
2响应状态码:服务器告诉客户端浏览器本次请求访问的的响应的状态
状态码都是3为数字
分类:
1.1xx:服务器接受客户端 但没有接受完成,等待一段时间发送1xx状态码
2.2xx:成功
3.3xx:重定向。代表的状态码 302(重定向) 304(缓存)
4.4xx 客户端错误 路径没有对应的资源,404 405请求的方式没有对应的doxxx方法
5.5xx:服务器端出现异常
2.响应头
1.格式 头名称:值
2.常见的响应头:
Content-Type :标示服务器告诉客户端本次响应的数据格式以及编码格式
Content-disposition:服务器告诉客户端以什么格式打开响应体数据值。in-line;默认值,当前页面内打开
attachment:filename=xxx以附件形式打开响应体,文件下载中使用
响应空行
响应体:传输的数据
response对象
功能:设置响应消息
1.设置响应行
1.格式;HTTP/1.1 200 ok
2.设置状态码:setState(int sc)
3.设置响应头setHeader(String name,String value)
4.设置响应体
使用步骤
1.获取输出流
字符输出流 PrintWrite getWrite()
字节输出流ServletOutPutStream getOutPutStream()
2.使用输出流,将输出流输出到客户端,
重定向和转发的区别
重定向的特点:redirect
1.地址栏发生变化
2.重定向可以访问其他站点(服务器)的资源
3.重定向是两次请求,不能使用request对象来共享数据
转发的特点:forward
1.转发地址栏路径不变
2.转发只能访问当前服务器下的资源
3.转发时一次请求,可以使用request对象来共享数据
//设置状态码302
response.setStatus(302);
//设置响应头location
response.setHeader("location","/loginServlet");
//简单的重定向方法
response.sendRedirect("/loginServlet");
路径的分类:
1.相对路径:通过相对路径不可以确定唯一资源
不以‘/’开头,以‘.’开头的路径
规则:找到访问当前资源和目标资源之间的相对位置关系
./ : 当前目录
../ : 后推一级目录
动态获取虚拟目录 : request.getContextPath();
2.绝对路径:通过绝对路径可以确定唯一资源
以’/’开头的为绝对路径
规则:判断定义的路径是给谁用的
给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
建议虚拟目录动态获取:request.getContextPath();
服务器使用:不需要加虚拟目录
服务器输出字符数据到浏览器
步骤
获取流之前,设置流的默认编码,ISO-8859-1. 设置为GBK
response.setCharacterEncoding(“utf-8”);
//告诉浏览器,服务器的发送的消息体数据的编码。建议浏览器使用该编码解码
response.setHeader(“Content-Type”,”text/html;charset=utf-8”);
简单的形式,获取编码:response.setContentType(”text/html;charset=utf-8”);
1.获取字符输出流
PrintWriter pw = response.getWriter()
2.输出数据
pw.write(String str)
4.获取对象ServletContext
1.概念:
代码整个web应用,可以和程序的容器(服务器)来通信
2.功能:
1.获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式:大类型/小类型。text/html。 image/jpeg
获取:String getMineType(String s)
2.域对象:共享数据
1.setAttribute(String name,Object value);
2.getAttribute(String name);
3.removeAttribute(String name);
4.ServletContext对象范围:所有用户共享的数据
3.获取文件的真实(服务器)路径
context.getRealPath(“/文件”);
注意src中的class文件路径是在WEB-INF/classes/
实战 这里以文件上传为例
DownloadDemo.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/day14/downloadServlet?filename=a.png">图片</a>
</body>
</html>
服务器DownloadServlet文件
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1获取请求参数,文件名称
String filename = request.getParameter("filename");
//2 使用字节流加载文件到内存
//2.1找到文件服务器路径
ServletContext servletContext = request.getServletContext();
String realPath = servletContext.getRealPath("/image/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3设置response响应头
//3.1设置响应头类型,content-type
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type", mimeType);
//3.2设置响应头打开方式,content-disposition
//解决中文文件问题
//1.获取user-agent请求头
String agent = request.getHeader("user-agent");
//2.使用工具类方式编码文件即可
response.setHeader("content-disposition", "attachment;filename=" + DownLoadUtils.getFileName(agent, filename));
ServletOutputStream outputStream = response.getOutputStream();
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
//关闭输入流
fis.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
以及兼容工具类DownLoadUtils
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
Base64.Encoder encoder = Base64.getEncoder();
String result = encoder.encodeToString(filename.getBytes("utf-8"));
filename = "=?utf-8?B?" + result + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
网友评论