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.02018年, HTTP/3.0
报文格式


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-核心规则

报文格式-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.1PUT用于对已存在的资源进行整体覆盖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)
✅同时适用于请求和响应消息, 但与消息主体无关的消息头
请求头字段



响应头字段



状态码(Status Code)
在
RFC 2616 10.Status Code Definitions规范中定义
-- 状态码指示HTTP请求是否已成功完成状态码可以分为
5类
-- 信息响应:100~199
-- 成功响应:200~299
-- 重定向:300~399
-- 客户端错误:400~499
-- 服务器错误:500~599100 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和HEAD502 Bad Gateway作为网关或代理角色的服务器, 从上游服务器(如tomcat)中接收到的响应是无效的503 Service Unavailable服务器尚未处于可以接受请求的状态
-- 通常造成这种情况的原因是由于服务器停机维护或者已超载
form提交-常用属性
-
action请求的URI -
method请求方法(GET, POST) -
enctypePOST请求时, 请求体的编码方式
--application/x-www-form-urlencoded(默认值)
✅用&分隔参数, 用=分隔键和值, 字符用URL编码方式进行编码
-- multipart/form-data
✅文件上传时必须使用这种编码方式
form提交-multipart/form-data
- 参考
RFC 1521 - 请求头
--Content-Type: multipart/form-data; boundary=xxx

同源策略
-
浏览器有个同源策略
(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)
✅告知浏览器这是一个允许跨域访问的请求
会话跟踪
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 GMTmax-age
-- 过期时间距离当前时间的秒数
-- 例如:max-age=60Cookie(只归一个浏览器管)
-- 在客户端(浏览器)存储一些数据, 存储到本地磁盘(硬盘)
-- 服务器可以返回Cookie交给客户端去存储Session(针对用户浏览器的,会话跟踪)
-- 在服务器存储一些数据, 存储到内存中
Cookie的作用域
domain和path标识定义了Cookie的作用域, 即Cookie应该发送给哪些URLdomain
-- 标识指定了哪些主机可以接受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分钟后就会销毁










