HTTP
-
HTTP(Hyper Text Transfer Protocol)
, 译为超文本传输协议
-- 是互联网中应用最广泛的应用层协议之一
-- 设计HTTP
最初的目的是: 提供一种发布和接收HTML
页面的方法, 由URI
来标识具体的资源
-- 后面用HTTP
来传递的数据格式不仅仅是HTML
, 应用非常广泛 -
HTML(Hyper Text Markup Language)
: 超文本标记语言
-- 用以编写网页
版本
-
1991年, HTTP/0.9
-- 只支持GET
请求方法获取文本数据(比如HTML
文档), 且不支持请求头, 响应头等, 无法向服务器传递太多信息 -
1996年, HTTP/1.0
-- 支持POST
,HEAD
等请求方法, 支持请求头, 响应头等, 支持更多种数据类型 (不再局限于文本数据)
-- 浏览器的每次请求都需要与服务器建立一个TCP
连接, 请求处理完成后立即断开TCP
连接 -
1997年, HTTP/1.1
(最经典, 使用最广泛的版本)
-- 支持PUT
,DELETE
等请求办法
-- 采用持久连接(Connection: keep-alive)
, 多个请求可以共用一个TCP
连接 -
2015年, HTTP/2.0
-
2018年, HTTP/3.0
报文格式
image.png image.png-
ABNF (Augmented BNF)
-- 是BNF (Backus-Naur Form, 译为: 巴科斯-瑙尔范式)
的修改, 增强版
-- 在RFC 52234
中表明:ABNF
用作internet
中通信协议的定义语言
--ABNF
是最严谨的HTTP
报文格式描述形式, 脱离ABNF
谈论HTTP
报文格式, 往往都是片面, 不严谨的 -
关于
HTTP
报文格式的定义
--RFC 2616 4.HTTP Message(旧)
--RFC 7230 3.Message Format(新)
ABNF-核心规则
image.png
报文格式-request-line, status-line
request-line = method SP request-target SP HTTP-version CRLF
HTTP-version = HTTP-name "/" DIGIT"."DIGIT"
HTTP-name = %48.54.54.50;HTTP
GET /hello/ HTTP/1.1
status-line = HTTP-version SP status-code SP reason-phrase CRLF
status-code = 3DIGIT
reason-phrase = *(HTAB / SP / VCHAR / obs-text)
HTTP/1.1 200
HTTP/1.1 200 OK
报文格式 - header-filed, message-body
header-filed = filed-name ":" OWS field-value OWS
field-name = token
field-value = *(field-content / obs-fold)
OWS = *(SP / HTAB)
message-body = *OCTET
URL
的编码
-
URL
中一旦出现了一些特殊字符(比如中文, 空格), 需要进行编码
-- 在浏览器地址栏输入URL
时, 是采用UTF-8
进行编码 -
比如
-- 编码前:https://www.baidu.com/s?wd=百度
-- 编码前:https://www.baidu.com/s?wd=%E5%8D%8E%E4%B8%BA
请求方法
-
GET
常用于读取的操作, 请求参数直接拼接在URL
的后面(浏览器对URL
是有长度限制的) -
POST
常用于添加, 修改, 删除的操作, 请求参数可以放到请求体中(没有大小限制)**(URL也可以拼接参数, 请求体里也拼接参数)**
-
HEAD
请求得到的与GET
请求相同的响应, 但没有响应体
-- 使用场景举例: 在下载一个大文件前, 先获取其大小, 再决定是否要下载. 以此可以节约带宽资源 -
OPTIONS
用于获取目的资源所支持的通信选项, 比如服务器支持的请求方法
--OPTIONS * HTTP/1.1
-
PUT
用于对已存在的资源进行整体覆盖 -
PATCH
用于对资源进行部分修改(资源不存在, 会创建新的资源) -
DELETE
用于删除指定的资源 -
TRACE
请求服务器回显其收到的请求信息, 主要用于HTTP
请求的测试和诊断 -
CONNECT
可以开启一个客户端与所请求资源之间的双向沟通的通道, 它可以用来创建隧道(tunnel)
-- 可以用来访问采用了SSL(HTTPS)
协议的站点
头部字段(Header Field)
- 头部字段可以分为
4
种类型
-- 请求头字段(Request Header Fields)
✅有关要获取的资源或客户端本身信息的消息头
-- 响应头字段(ResponseHeader Fields)
✅有关响应的补充信息, 比如服务器本身(名称和版本等)的消息头
-- 实体头字段(Entity Header Fields)
✅有关实体主体的更多信息, 比如主体长度(Content-Length)
或MIME
类型
-- 请求头字段(General Header Fields)
✅同时适用于请求和响应消息, 但与消息主体无关的消息头
请求头字段
image.png image.png image.png响应头字段
image.png image.png image.png状态码(Status Code)
-
在
RFC 2616 10.Status Code Definitions
规范中定义
-- 状态码指示HTTP
请求是否已成功完成 -
状态码可以分为
5
类
-- 信息响应:100~199
-- 成功响应:200~299
-- 重定向:300~399
-- 客户端错误:400~499
-- 服务器错误:500~599
-
100 Continue
-- 请求的初始部分已经被服务器收到, 并且并没有被服务器拒绝. 客户端应该继续发送剩余的请求, 如果请求已经完成, 就忽略这个响应
-- 允许客户端发送带请求体的请求前, 判断服务器是否愿意接手请求(服务器通过请求头判断)
-- 在某些情况下, 如果服务器在不看请求体就拒绝请求时, 客户端就发送请求体是不恰当或者低效的 -
200 OK
请求成功 -
302 Found
请求的资源被暂时移动到了由Location
头部指定的URL
上 -
304 Not Modified
说明无需再次传输请求内容, 也就是说可以使用缓存内容 -
400 Bad Request
由于语法无效, 服务器无法理解该需求 -
401 Unauthorized
由于缺乏目标资源要求的身份验证凭证 -
403 Forbidden
服务器端有能力处理该请求, 但是拒绝授权访问 -
404 Not Found
服务器端无法找到所请求的资源 -
405 Method Not Allowed
服务器禁止了使用当前HTTP
方法的请求 -
406 Not Acceptable
服务器端无法提供与Accept-Charset
以及Accept-Language
指定的值相匹配的响应 -
408 Request Timeout
服务器想要将没有在使用的连接关闭
-- 一些服务器会在空闲连接上发送此信息, 即便是在客户端没有发送任何请求的情况下 -
500 Internal Server Error
所请求的服务器遇到意外的情况并阻止其执行请求 -
501 Not Implemented
请求的方法不被服务器支持, 因此无法被处理(注意和405
的区别)
-- 服务器必须支持的方法(即不会返回这个状态码的方法)只有GET
和HEAD
-
502 Bad Gateway
作为网关或代理角色的服务器, 从上游服务器(如tomcat
)中接收到的响应是无效的 -
503 Service Unavailable
服务器尚未处于可以接受请求的状态
-- 通常造成这种情况的原因是由于服务器停机维护或者已超载
form
提交-常用属性
-
action
请求的URI
-
method
请求方法(GET, POST)
-
enctype
POST
请求时, 请求体的编码方式
--application/x-www-form-urlencoded
(默认值)
✅用&
分隔参数, 用=
分隔键和值, 字符用URL
编码方式进行编码
-- multipart/form-data
✅文件上传时必须使用这种编码方式
form
提交-multipart/form-data
- 参考
RFC 1521
- 请求头
--Content-Type: multipart/form-data; boundary=xxx
image.png
同源策略
-
浏览器有个同源策略
image.png(Same-Origin Policy)
-- 它规定了: 默认情况下,AJAX
请求只能发送给同源的URL
-- 同源是指3
个相同: 协议, 域名(IP)
, 端口
-
img, script, link, iframe, video, audio
等标签不受同源策略的约束
跨域资源共享
-
解决
AJAX
跨域请求的常用方法
--CORS(Cross-Origin Resource Sharing)
跨域资源共享 -
CORS
的实现需要客户端和服务器同时支持
-- 客户端
✅所有的浏览器都支持(IE
至少是IE10
版本)
-- 服务器
✅需要返回相应的响应头(比如Access-Control-Allow-Origin
)
✅告知浏览器这是一个允许跨域访问的请求
后端在返回数据前就应该先判断origin和允许访问的是否一致, 否则就算浏览器报错跨域问题, 前端一样可以拿到数据, 后端的数据就存在不安全性
会话跟踪
-
HTTP
是一种"无状态"(stateless)
的协议
-- 每次客户端访问网页时, 客户端都会打开与Web
服务器的单独连接
-- 并且服务器不会自动保留之前客户端请求的任何记录
-- 所以服务器无法识别多个请求是否来自同一个客户端(比如浏览器) -
在很多应用场景中, 都有以下需求
-- 服务器能够识别出多个请求是够来自同一个客户端
-- 在来自同一个客户端的多个请求之间共享数据 -
以上需求可以使用会话跟踪技术来完成. 在
Java
中, 实现会话跟踪的常用方法是
--Cookie
--Session
Cookie & Session
-
Cookie
是直接存储在浏览器本地的一小串数据
-- 使用document.cookie
访问Cookie
-- 在修改Cookie
时, 只会修改其中提到的Cookie
--name=value
必须被编码(encodeURIComponent)
-- 一个Cookie
最大为4kb
, 每个网站最多有20+
个左右的Cookie
(具体取决于浏览器) -
Windows
中Chrome
浏览器的Cookie
存放位置
--C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Cookies
-- 使用SQLite
数据库进行存储
Cookie的有效期
-
如果没有设置
Cookie
的过期时间, 则当浏览器关闭时,Cookie
就失效了 -
expries
-- 必须完全采用GMT
时区的格式, 可以受用date.toUTCString
来获取
-- 例如:expires=Tue, 19 Jan 2038 03:14:07 GMT
-
max-age
-- 过期时间距离当前时间的秒数
-- 例如:max-age=60
-
Cookie
(只归一个浏览器管)
-- 在客户端(浏览器)存储一些数据, 存储到本地磁盘(硬盘)
-- 服务器可以返回Cookie
交给客户端去存储 -
Session
(针对用户浏览器的,会话跟踪
)
-- 在服务器存储一些数据, 存储到内存中
Cookie
的作用域
-
domain
和path
标识定义了Cookie
的作用域, 即Cookie
应该发送给哪些URL
-
domain
-- 标识指定了哪些主机可以接受Cookie
-- 如果不指定, 默认为当前文档的主机(不包含子域名); 如果指定了domain
, 则一般包含子域名
-- 例如: 如果设置domain=520it.com
, 则Cookie
也包含在子域名中(如bbs.520it.com
) -
path
-- 标识指定了主机下的哪些路径可以接受Cookie
, 子路径也会被匹配
-- 例如:设置path=/docs
, 则以下地址都会匹配
✔️/docs
✔️/docs/one/
✔️/docs/one/img
服务器设置Cookie
-
Cookie
通常是由Web
服务器使用响应头Set-Cookie
设置的 -
关于
max-age
-
-在
JavaScript
中, 如果设置为0或者负数, 会立即删除Cookie
-- 在Java
中: 如果设置为0
, 是立即删除Cookie
; 如果设置为负数, 按默认情况处理
getSession
内部的原理
- 检查客户端是否有发送一个叫做
JSESSIONID
的Cookie
-- 如果没有
✔️创建一个新的Session
对象, 并且这个Session
对象会有一个id
✔️这个Session
对象会保留在服务器的内存中
✔️在响应的时候, 会添加一个Cookie(JSESSIONID=Session对象的id)
给客户端
-- 如果有
✔️返回id
为JSESSIONID
的Session
对象
JSESSIONID
-
默认情况下, 当用户关闭浏览器时,
Cookie
中存储的JSESSIONID
就会被销毁 -
可以通过以下代码延长
JSESSIONID
在客户端的寿命
Cookie cookie = new Cookie("JSESSIONID", request.getSession().getId());
cookie.setMaxAge(3600);
response.addCookie(cookie);
Session
的有效期
-
Session
的有效期默认是30
分钟 - 可以在
web.xml
中配置失效时间(单位是分钟)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
总结
-
Cookie
-- 数据存储在浏览器客户端
-- 数据有大小和数量的限制
-- 适合存储一些小型, 不敏感的数据
-- 默认情况下, 关闭浏览器后就会销毁 -
Session
-- 数据存储在服务器端
-- 数据没有大小和数量的限制
-- 可以存储大型, 敏感的数据(比如用户信息)
-- 默认情况下, 未使用30
分钟后就会销毁
网友评论