【JavaEE】HTTP(Part1 含面试题)

努力经营当下,直至未来明朗!


前言

开启后端学习之旅:

  1. HTTP协议:前后端交互的桥梁
  2. Tomcat:Java世界中最主流的HTTP服务器之一;写后端代码很多都是基于Tomcat二次开发的
  3. Servlet:Tomcat给后端程序员提供的开发服务器程序的API合集
  4. Linux:使用云服务器来部署写好的程序

一个人最大的痛苦来源于对自己无能的痛苦!

一、HTTP协议

  1. 网络技术中,最核心的概念就是“协议”。
  2. HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议
  3. HTTP就是应用层典型的协议。
  4. 应用层,很多时候需要程序员自定义应用层协议,但是也有一些现成的协议供我们直接使用。
  1. HTTP的应用:
    ① 浏览器和服务器之间的交互(打开网页),大概率都是HTTP协议
    ② 手机APP和服务器之间的交互,大概率都是HTTP协议
    ③ 服务器之间的相互调用,也可以使用HTTP
    (①②是主流,③非主流)

  2. 当前最新的HTTP版本是HTTP3.0,但是当下最常见的版本还是HTTP1.1,所以目前主要介绍的是1.1版本。

  3. 在浏览器中输入一个网址,等待网页生成的过程其实就是 浏览器和服务器通过HTTP进行交互了。

  4. HTTP协议是典型的“一问一答”模型的协议(也就是请求和响应一一对应)

  5. 学习HTTP协议,主要学习的就是HTTP放入报文格式:报文格式描述了HTTP请求和响应是啥样的

  6. 需要使用“抓包工具”来捕获到请求交互的详细情况。


抓包工具

  1. “抓包工具”:是个特殊的软件,相当于一个“代理程序”,浏览器给服务器的请求就会经过这个代理程序(响应也是经过该代理程序的),进一步的就能分析出请求和响应的结果如何。
    1

  2. 谈到“代理”,其实是分为两种的:
    ① 正向代理:给客户端提供服务的,和客户端关系紧密(站在服务器的角度,正向代理把真正的客户端给隐藏起来了,服务器并不知道真正的客户端是啥)
    ② 反向代理:给服务器提供服务的,和服务器关系紧密(站在客户端的角度,反向代理把真正的服务器给隐藏起来了,客户端并不知道真正的服务器是啥)

  3. 抓包工具有很多,我们使用fiddler(其他的如:wireshark,Charles,Chrome的开发者工具等),fiddler使用简单、功能强大,很多公司都在使用。

  4. 下载安装fiddler:

【补充一个好用的网站:cn.bing.com/ (很多都可以在上面搜)】

① cn.bing.com/ (当然也可以直接在浏览器上搜索)
②搜fiddler:进入官网,选择经典版
2
3

或者直接点击:
5

③ 下载安装后打开fiddler:

  • 左侧区域是抓到的请求/列表,应用程序通过http传输数据都能被fiddler抓到;
  • 双击左侧某个你想关注的请求详情,就会在右侧窗口显示出请求的具体情况。
  • 点击右上角的raw标签页显示的是HTTP 请求最原始的样子,右下角的raw标签页显示的是HTTP 响应 最原始的样子。
    (由于响应数据可能体积较大,服务器通常会返回一个“压缩”后的结果,点击上面的黄色的条条就可以进行解压缩了)

④ 注意事项:
可能会存在不一定能够抓取到很多请求的情况,那么:
A. 需要开启fiddler抓取HTTPS的功能(现在互联网上纯HTTP很少了,更多的是HTTPS,HTTPS可以理解为升级版本的HTTP,即在HTTP的基础上加了个加密层)
手动开启:菜单栏=> tools => options => HTTPS中4个选项全勾√ 上 => 点击ok => 首次勾选点击ok后会提示是否安装“根证书”,务必点击“是”!!!
6

B. 如果开启了上述HTTPS,也安装了根证书,但是还是抓不到:检查电脑上是否安装了其他的代理程序/代理作用的浏览器插件(如:翻墙工具/游戏加速器/steam++等本质上都是代理,这些程序都会和fiddler打架,也就是说:都可以安装,但是不能同时运行!)。使用fiddler务必要把其他的代理程序禁用/关闭。


协议总格式(重要!!)

7

(在fiddler中点击右边view可以在记事本中详细查看)
HTTP是一个文本格式的协议。(行文本)

  1. 以下是完整的HTTP请求的格式:
    以搜狗网站为例:
    1)首行:
    8
    ① GET:方法,是干啥的
    ② https://www.sogou.com/content-search.xml :URL,描述了网络上的唯一资源
    ③ HTTP/1.1:版本号
  1. 请求头header:是一个按行组织的键值对,每一行是一个键值对,键和值之间使用 :空格来分割
    9

3)空行:一个HTTP请求的header可以有若干个,就使用空行作为header的结束标记,就类似于链表的null。(重点了解)

4)正文body:有的请求有,有的没有。格式很多,最常见的就是json。

10
(这是某个网站登录请求的正文)

补充:如何清空fiddler中左侧抓到的请求?
先选中一个 -> Ctrl+A -> delete

  1. 完整的HTTP响应的格式:
    1)首行:
    ① HTTP/1.1 :版本号
    10
    ② 200是状态码,一般用200表示请求成功
    (其实大多数响应后面还会有一个ok,表示状态码的描述,就是对状态码表示解释说明)
    11
    ③ 响应报头:同样也是键值对的结构
    ③ 空行
    ④正文:可以是json、html、css、js、图片等

  2. 为什么HTTP报文中要存在空行?

① 因为 HTTP 协议并没有规定报头部分的键值对有多少个, 空行就相当于是 “报头的结束标记”, 或者是 “报头和正文之间的分隔符”.
HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的。如果没有这个空行, 就会出现 "粘包问题"


二、HTTP协议中的细节

【HTTP请求】

  1. 认识URL:唯一资源定位符 (用这个来找到网络上的资源)-》 也就是:浏览器地址栏的内容
    区别:URI唯一资源标识符(用这个来区分网络上的资源)
    【这两个概念非常相似,很多时候我们是不会进行显示区分的】

  2. URL里面是啥样的,是由“RFC标准文档”来进行描述的。RFC标准文档描述了很多网络中的协议标准,包括IP、UDP、TCP、HTTP等

  3. URL并非是HTTP独有的,很多协议都是可以使用的

  4. HTTP服务器一般不会把电脑上所有的资源都提供到网络上,通常都是指定某个目录,把目录里的作为网络可访问的资源。

  5. HTTP服务器都是可以在启动的时候指定绑定某个端口的,但是在大多数情况下HTTP服务器默认使用的端口号就是80.包括在浏览器中写一个URL也不一定要写端口号,如果不写就相当于默认访问http80端口,https是443端口

  6. 【访问静态资源:访问硬盘的真实文件; 访问动态资源:直接在内存中根据请求进行构造文件】

  7. URL中 ?后面内容:query string查询字符串:相当于浏览器给服务器传递的一些必要的参数。
    此处的查询字符串是通过“键值对”格式来组织的,键值对之间使用**&分割**,键和值之间使用**=来分割**。
    如:https://editor.csdn.net/md?not_checkout=1&articleId=128333065
    (editor.csdn.net会通过DNS域名解析系统解析为一个具体IP地址)

  8. HTTP header中也是有很多键值对的,这里的键和值大多都是标准规定好的(虽然也可以自定义,但是以标准规定为主)

  9. URL里的查询字符串中的键值对完全是自定义的。
    因此,查询字符串就是前后端交互数据的重要桥梁!

  10. 片段标识符:用来区分一个网页中的哪个部分,常见于小说网站或者文档网站。借助片段标识符快速跳转到网页的某个部分。

  11. URL重要的部分:
    ① IP地址+端口号(基础)
    ② 带层次的路径(开发中常用)
    ③ 查询字符串(开发中常用)

URL中已经包含了一些特殊含义的符号了,如:/ ? @ …但是万一query
string中也包含了这些符号就可能会出现问题(浏览器可能会错误识别URL,服务器也可能会错误解析URL),这就非常类似于编程语言里面的变量名不能是“关键字”。
此时就使用URL encoding对特殊符号进行转义,但是转义的不仅仅是这些特殊符号,还有汉字

  1. 使用URL encoding对特殊符号、汉字进行转义,转义的规则:就是把待转义的字符串的每个字符用十六进制进行表示,每个字节前面加个 % (注:UTF8中每个汉字3字节,具体十六进制可以查看utf8文档)

  2. 把原始字符转成转义后的字符:URL encode(编码)
    把转义后的字符还原成原始的字符:URL decode(解码)

【写代码经常要考虑到编码、解码,但是有第三方库可以使用,只不过我们一定要有这个意识!!】
(可以搜索网上的 URLencode在线编码解码工具)


【HTTP中的“方法”】

可以把“方法”理解为该请求想要干嘛
13

GET、POST是最重要的!可以应对90%以上的场景


【GET】:最常用的HTTP请求

  1. 浏览器地址栏直接输入URL,此时就会触发GET

  2. html中的link,a,img,script也会触发GET请求(请求指定页面信息,并返回实体)

  3. form表单:html中的form标签,可以构造出GET请求

  4. ajax:(后面讲)

  5. 【补充】在页面上按住ctrl之后再点击刷新(其实也就是ctrl+f5)是强制刷新,能够在fiddler中看到更多请求。

浏览器在加载页面的时候,往往要加载这个页面依赖的很多其他资源,如css,图片,js等,加载这些资源显然是需要消耗一定的时间的。为了提高页面加载效率,浏览器就会对加载过的这些css,图片,js等进行缓存,也就是直接保存在本地磁盘上。下次再访问同一个网页时,之前的css,图片,js等就不必从网络上加载,而是直接从硬盘读取就行。使用ctrl+f5强制刷新就可以让浏览器不走缓存,而是直接强制重新从网络上获取资源。

  1. 【GET请求的特点】

① 首行的第一部分为 GET
② URL 的 query string 可以为空, 也可以不为空.
③ header 部分有若干个键值对结构.
④ body 部分为空.

(如果需要给服务器传递一些参数,这些参数通常就是通过query string进行传递的)

  1. 网上有这样的说法:GET请求长度最多是1KB/2KB/1MB…
    RFC标准文档中其实对长度是没有规定的
    虽然标准没有谈到长度上限,但是浏览器和HTTP服务器在实现的时候可能是有长度上限的,也可能没有(取决于具体的实现)。
    所以网上说法是错误的!!

【POST】

  1. 应用场景没有GET那么多,其产生的途径:
    ① form表单
    ② ajax

(POST一般是在登录页面比较常见)

  1. POST请求的特点:

① 首行的第一部分为 POST
② URL 的 query string 一般为空 (也可以不为空)
③ header 部分有若干个键值对结构.
④ body 部分一般不为空.
⑤ body 内的数据格式通过 header 中的 Content-Type 指定.
⑥ body 的长度由 header 中的 Content-Length 指定.

  1. POST在传递信息给服务器的时候,通常就会把信息给放到body中。

  2. 经典面试题】GET和POST的区别
    1)先盖棺定论:GET和POST没有本质区别(即:GET和POST使用的场景基本可以相互代替)
    2)细节上谈区别:
    ① 语义上:GET的语义是“从服务器获取数据”,POST的语义的“往服务器提交数据”
    ② 使用习惯上:给服务器传递的数据,GET通常是放在url的query string中的,POST通常是放在body中的。
    ③ GET请求建议实现成“幂等”的,POST一般不要求实现“幂等”。

(幂等:简单来说大概就是输入是确定的,输出结果也就是确定的,即输入一样时输出也是一致的)

【设计服务器的时候,就需要提供一些“接口/API”:API传入的参数就视为输入,API返回的结果就视为输出。
基于GET的API一般会建议设计成幂等的,基于POST的API则无要求(建议不要求一定要遵守)】

④ 在幂等的基础上,GET的请求结果是可以缓存的(浏览器默认行为);POST则一般不会缓存。

如果当前GET确实是幂等的,就不必处理,直接让浏览器缓存没问题;
但是如果当前的GET不是幂等的,就需要通过特殊技巧避免浏览器产生缓存(典型的技巧就是让每次GET请求的URL都不相同,通过特殊的query
string来保证url不同)

  1. 【网上有这样的说法:POST比GET更安全,依据是:
    GET还把参数放到url里,如果你实现登录页面,一点登录,你的用户名和密码就直接以query string形式放到url里面,就会直接显示到浏览器地址栏中,这样就会被别人看到,所以GET是不安全的;POST是把参数放到body中,body不会显示到浏览器界面上,即此时用户名和密码不会直接显示出来,则POST就是安全的。】
    ==但是该说法是错误的!==我们平时所说的“安全”指的是数据被黑客截获之后不会造成信息泄露这样的影响。并且只要代码中没有加密,就谈不上安全。(针对密码等敏感信息进行加密才谈得上安全)

HTTP没有加密功能,HTTPS具有一定的加密功能。 但是相对来说,实践中主要还是通过业务上代码来实现加密的。

  1. 其他方法:

① PUT 与 POST 相似,只是具有幂等特性,一般用于更新
② DELETE 删除服务器指定资源
③ OPTIONS 返回服务器所支持的请求方法
④ HEAD 类似于GET,只不过响应体不返回,只返回响应头
⑤ TRACE 回显服务器端收到的请求,测试的时候会用到这个
⑥ CONNECT 预留,暂无使用


【认识请求“报头”header】

  1. 报头中的键值对大部分是标准规定的,都有特定的含义;当然也可以使用一些自定义的键值对。
  2. 每个键值对占一行, 键和值之间使用分号分割。

【Host】

URL中不是也有这个服务器主机的IP和端口吗,为啥还要搞个Host?

① 事实上,URL中的IP和端口 与 Host中的IP和端口不一定完全一样(当请求是经过代理来访问的时候可能不一样的,当然这一点在fiddler上没有体现出来)。
请求中的URL地址是经过的代理地址,而Host的地址是目标服务器的地址。


【Content-Length 和 Content-Type】

  1. 这两个字段不一定有,但是如果有一个就一定会有另一个!

如果请求没有body就没有这两个字段(如GET一般是没有body的),反之则有(如POST一般是有body的)

  1. HTTP协议在传输层是基于TCP的(至少在HTTP3.0之前是这样的,3.0就变成UDP了)。

  2. TCP是面向字节流的,就会存在粘包问题。(所以在存在body时,Content-Length是很重要的,可以区分下一个HTTP)

  3. Content-Length不需要手动设置,一般是浏览器和HTTP服务器自己计算好的。

  4. Content-Type也是很重要的:body中的数据可以放很多种格式,存的不同格式的数据,对于接收方来说,对应截然不同的解析方式。

  5. 三种Content-Type选项:
    面试一般不会考这三种选项,但是对于日常开发/调试时很有用的,通过抓包以及代码来熟悉。
    ① application/x-www-form-urlencoded: form 表单提交的数据格式。 此时 body 的格式形如:

title=test&content=hello
// 和query string格式一样使用键值对,键值对之间&,键和值之间=

② multipart/form-data: form 表单提交的数据格式(在 form 标签中加上
enctyped=“multipart/form-data” . 通常用于提交图片/文件。
(这个格式主要在上传文件的时候会出现)
③ application/json: 数据为 json 格式. body 格式形如:

{"username":"123456789","password":"xxxx","code":"jw7l",
"uuid":"d110a05ccde64b16a861fa2bddfdcd15"}

(这个JSON格式比较香,所以大家都爱用。)

  1. 关于Content-Type详细可参考:Content-Type

【User-Agent (简称 UA】

  1. 举例:User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36

① Mozilla:其实就是之前提及的前端查文档使用的MDN的组织
② (Windows NT 10.0;WOW64):操作系统信息,Windows NT是操作系统内核
③ AppleWebKit/537.36:一个浏览器内核
④Chrome/86.0.4240.198:浏览器
⑤ Safari/537.36:mac电脑上默认的浏览器

  • 小结:UA主要包含的信息就是操作系统信息和浏览器信息,描述了用户在使用啥样的设备上网。

系统不同,浏览器不同,设备不同,对于某些页面的支持程度可能是不一样的。所以通过UA来收集浏览器/操作系统的信息。进一步就可以知道该浏览器/系统都支持啥样的页面了。

  1. 可以根据UA来识别PC、平板、手机,分别开发出不同版本的页面,但是这样工作量会加大。所以程序员就发明了“响应式页面”,通过特殊的CSS和JS来感知当前浏览器的窗口尺寸,根据不同的尺寸重新排列页面布局。
    这使得UA作用进一步被削弱,但是其至少可以用来在服务器端统计用户的设备情况(大数据)。

【Referer】

  1. 并不是每个请求都有的。如直接在浏览器地址栏输入一个地址or直接点击收藏夹都是没有referer的。
  2. Referer指的是当前页面是从哪个页面跳转过来的,也就是上级页面是啥。
  3. 典型应用场景:浏览器广告计费功能,广告主统计点击次数就是使用referer作为参考,有多少次点击是从该网页跳转的(即上级网页)。

【Cookie】

  1. 也是请求头中一种重要的数据

  2. 是浏览器在本地存储数据(存到硬盘上)的一种机制。

  3. 服务器保存了大部分信息,但是浏览器也需要保存一些特殊的信息,为了保证数据的持久化存储就需要保存到硬盘上;但是浏览器为了安全起见,禁止网页的js访问你的电脑的硬件(文件系统)。所以,浏览器专门提供了特殊的API给网页来用,可以让网页来存储一些简单的数据。
    15

  4. 补:浏览器提供的持久化存储方案有很多:

① Cookie:是最经典的一种方案(最老)
② LocalStorage:是比较新的一种方式
③ IndexDB:是更新的方案

  1. 当前浏览器保存了很多的Cookie:(可以通过点击浏览器地址栏中最前面的小图标进行查看)
    Cookie是按照域名维度来进行组织的,不同的域名下有不同的Cookie。一个网站发起的http请求可能是来自于多个域名的,每个cookie都是一个键值对

每个键值对中都有:key、value、cookie的有效范围(域名+路径)。

  1. Cookie 和 query string一样,都是程序员自定义的。

  2. 注意区分
    ① Cookie不是缓存,是持久化存储数据的手段。
    ② Cookie和GET没直接关系,其他的POST、PUT啥的也都有cookie。
    ③ 持久化存储是保存在硬盘上的,这个数据你想咋用就咋用
    ④ 缓存里的数据不是持久化的(也可以在内存中缓存),缓存的数据是用来“提高访问速度” 的。

  3. Cookie中的键值对都是保存的简单字符串,如果想让其存储个图片、视频、flash啥的是万万做不到的。
    比如,可以使用Cookie存:
    ①上次访问页面的时间
    ②当前页面的访问次数
    ③当前访问页面的身份信息

    (具体存啥是由程序员自己定义的,不是浏览器自动存的)

  4. Cookie是存在浏览器中的,但是来源是服务器,还要再回到服务器。

①当我们的浏览器访问了服务器之后,在服务器返回的响应报文中,可以在响应header中包含一个/多个Set-Cookie这样的资源,浏览器看到Set-Cookie就会把这些数据保存在浏览器本地(Set-Cookie是程序员在服务器代码中构造出来的)
②当浏览器保存了Cookie之后,下次浏览器访问同一个网站时,就会把之前本地存储的Cookie再通过http请求header中的Cookie给带过去。
③ 为啥要转一圈呢?因为服务器要服务的客户端是很多的,这些不同的客户端应该要有不同的数据。
(Cookie会占硬盘,但是空间不大,而且会有到期时间)

  1. Cookie典型应用场景:
    最常使用的场景就是在客户端维持登录状态:在某个网站登录成功后,浏览器就会记住当前登录用户的身份信息(也就是:服务器给浏览器的响应中带了Set-Cookie,会有一个身份标识),然后接下来访问该网站的其他页面时,服务器也能知道是谁在登录(此时浏览器发送的请求中带着Cookie这个字段,该字段中就包含了身份标识)。

【很多网站是基于Cookie实现的,但是也有很多新的网站不是使用Cookie,而是使用如LocalStorage之类的进行实现的】
(key是身份信息,value是详细信息)

  1. 【Cookie中的用户身份标识就是sessionId,而服务器上的用户的信息就是session/会话。
    Cookie只针对当前域名下的网站生效(其实就相当于就诊卡只针对某个特定医院生效)】
    举例:医院看病(刷卡就是Cookie)

  2. 路径一般是/,意思就是在整个网站下的所有路径都是生效的。但是有些页面特殊,需要特定的cookie,这些特定的cookie在别的页面中无意义。

  3. 登录过程:
    16


【认识请求“正文”body】

(请求报文的body:GET一般是没有的,POST一般是有的)

正文中的内容格式和 header 中的 Content-Type 密切相关,其三种方式也就是三种Content-Type选项。(了解)


THINK

  1. HTTP报文格式:请求和响应【重要!!!】
  2. URL:主要关注①ip+端口; ②带层次的路径; ③查询字符串query string (涉及到url的encode和decode)
  3. HTTP方法:GET、POST!
  4. 经典面试题:GET和POST区别!
  5. 认识请求报头,主要是Cookie!!

yyy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

'Dream是普通小孩耶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值