目录1.7 HTTP 响应详解1.7.1 认识“状态码”status code200 OK404 Not Found搜狗的404百度的404B站的404403 Forbidden405 Method Not Allowed500 Internal Server Error504 Gateway Timeout302 Move temporarily301 Moved Permanently状态码小结特殊状态码4181.7.2 认识响应“报头”header课件内容Content-Type1.7.3 认识响应“正文”body课件内容1text / html2text / css3application / javascript4application / json1.8 通过 form 表单构造 HTTP 请求课件内容1.8.1 form 发送 GET 请求构造的 HTTP 请求体会 form 代码和 HTTP 请求之间的对应关系1.8.2 form 发送 POST 请求构造的 HTTP 请求1.9 通过 ajax 构造 HTTP 请求重点课件内容1.9.1 发送 GET 请求1.9.2 发送 POST 请求1.10 通过 Java socket 构造 HTTP 请求课件内容1.11 通过 Postman 工具构造 HTTP 请求1.11.1 下载 Postman1.11.2 创建账号1.11.3 运行 Postman 并初步配置1.11.4 使用 Postman1.12 通过 Apifox 构造 HTTP 请求1.12.1 下载 Apifox1.12.2 创建账号1.12.3 运行 Apifox 并初步配置1.12.4 使用 Apifox书接上文Java EE7.网络原理- HTTP/HTTPS第三弹~~1.7 HTTP 响应详解1.7.1 认识“状态码”status code描述响应结果正确还是出错~~出错又是啥原因~~闲聊当时学C语言的时候讲了一个章节字符串内存函数~~~strerror把 errno 翻译成 可读的字符串~~这里的 errno error numberNumber缩写成 NO.~~再举个例子比如那种比较经典款式的洗衣机翻盖的那种如果洗的过程中你掀开盖子那么洗衣机就会立即停止工作然后液晶屏上会显示 E02这个 E02 就是一种状态码~~这种状态码就是返回出错原因的关键手段~~再比如说有一天你一见到你女朋友发现她面色不善~~1.她不说为啥生气让你猜这种咱就很难受有时候女生的脑回路非常神奇八竿子打不着的事儿能串到一块儿去咱会觉得莫名其妙~~2.她明确告诉你她为啥生气了~~这种是咱们比较希望看到的~~我们不怕出错我们怕的是出错之后不知道啥原因~~所以 HTTP 协议中就会通过状态码来完成这样的功能~~这些状态码都是 “HTTP 标准的大佬们”他们定义好的~~这些状态码看上去很多但其实一方面他们有着规律另一方面我们只需要掌握常见的几个就可以了~~以下为常见的状态码200 OK这是一个最常见的状态码表示访问成功~~我们抓包抓到的大部分结果都是 200例如访问搜狗百科404 Not Found访问的资源没找到~~访问的资源是啥我们之前说过在 URL 里面①通过 IP 定位到主机✔②通过端口号 port 定位到程序✔③通过路径 path 定位到程序管理的资源❌404 Not Found 就代表 IP 没问题端口没问题但是通过路径定位到访问资源的时候访问的资源不存在path 访问的资源在服务器上没有~~GetMapping 这些配置路由请求的路径和路由描述的路径不一致就会 404~~闲聊程序员不怕 404~~因为这表示的是用户的使用方式不对不是程序员的 Bug~~500才是最可怕的~~我们在搜狗百科的原有链接上随便加一个 abc.htmlhttps://baike.sogou.com/abc.html访问后就会出现这是因为原本服务器上就没有 abc.html 这个资源自然就访问不到了~~每个服务器的 404 页面都有自己的风格搜狗的404https://sogou.com/abc.html百度的404https://www.baidu.com/abc.htmlB站的404而我们在 Fidder 中就可以抓到这个可以看到即使状态码是有错的但也可以在 body 中返回一些 html 之类的把你的这个 404 页面好好打扮一番~~403 Forbidden访问被拒绝没有权限比如当你在码云上访问别人的私有仓库时就会显示无访问权限405 Method Not Allowed方法没有被实现~~请求的方法和服务器这边声明的注解不匹配就会出现 405网上找别人的网站出现 405 是比较难找的~~但是咱们自己开发过程中很容易出现 405 ~~500 Internal Server Error服务器出现错误服务器处理逻辑的代码中抛出异常但是你没有 catch 到~~咱们平时常用的网站很少会出现500但是偶尔也能看到~~504 Gateway Timeout服务器访问超时了~~Gateway网关~~即网络的入口一夫当关的关当你请求发了很久服务器的网关都没有进行响应我们就认为服务器访问超时了~~在服务器资源紧张的时候是容易触发的~~当服务器负载比较大的时候服务器处理单条请求的时候消耗的时间就会很长就可能会导致出现超时的情况比如学校的抢课系统、双十一“秒杀”场景~~302 Move temporarily临时重定向~~临时每次都会去转接服务器理解重定向访问服务器 A。服务器 A 告诉你去找 B ~~比如迁移域名~~如果直接迁移了就会使所有保存旧域名的同学都无法访问了因此需要把服务器架设在新域名上给旧域名设置重定向可以重定向到新域名这样一来同学访问新域名当然 OK访问旧域名就会自动跳转到新域名~~答疑这个用注解设置吗不是通过注解而是其他方式后续会讲到~~301 Moved Permanently永久重定向当浏览器收到这种响应时后续的请求都会被自动改成新的地址301 也是通过 Location 字段来表示要重定向到的新地址状态码小结2XX都可以视为是成功~~3XX都是重定向4XX客户端出错~~用户构造的请求有问题~~5XX服务器出错~~Java程序员主要关注这个5XX~~一定是服务器出大问题了大概率就是你代码有Bug像 5XX 这种都是写代码的时候返回的给我们调试 Bug 的~~500 就是 Spring 里面写好了的妥妥的异常没 catch 到而 502 Bad Geteway 叫错误的网关描述的就比较含糊需要对应你实际的业务场景中处理的具体是哪里错了可以根据你代码的情况灵活分配的一个典型的例子网关后面要调用的服务器某些出现问题了某个服务器/某组服务器挂了网关感知到这一点之后认为当前剩余的服务器不足以支持整个业务就可以设为 502特殊状态码418I am a teapot我是一个茶壶HTTP 的 RFC 标准文档中明确定义的~~这是个彩蛋开发中用不到设计 HTTP 标准的大佬开了个玩笑~~闲聊但这个不适合中国的国情~~咱们在国内当程序员不要在公司搞这个即使你搞开源项目也慎重搞这个~~之前阿里有一个开源的前端的 UI 组件库Ant Design开发者就搞了个彩蛋~~在圣诞节这天在它控件中显示一个“小云彩”结果圣诞节当天大家使用的时候发现我的按钮怎么被啃了一口还有老哥给阿拉伯地区的国家开发项目中东不是信基督教的~~就导致 Ant Design 在业界的影响力一落千丈~~作者最后也出面公开道歉啥的~~答疑Q1PHP 也能做网站开发但是他和Java哪个效率高是不是 PHP 能做的Java也能之前我们讲 Java 的发展过程的时候讲过这个问题Java 的发展的几个阶段1.做前端JS2.做后端JSP做手机J2ME3.做后端Spring做手机Android2000 - 2010年左右~~网站开发的主力 PHPJSP 只能排老二~~开发简单网站PHP 确实有优势但是网站规模变大业务变复杂有分布式系统这种PHP 就难以胜任了~~Q2C嘎嘎历史平淡无奇C的年代还不是“英雄辈出”能打的没几个~~C呈碾压姿势~~包括后来的Java、Python~~不管你们谁赢了到最后都是我C赢了能影响C地位的也就一个 Rust但 Rust 是一个比较新的语言是2010年之后才有的~~目的就是为了替代 C保持和 C一样的性能的前提下能够更好处理内存问题主要体现在能够提前发现内存错误访问非法内存识别出哪些内存需要释放~~我是不太看好~~因为 Rust 的语法也很复杂不比 C 简单多少~~C 现在发展也在持续进行虽然标准委员会的大佬经常搞一些莫名奇妙的东西至少 C 是在演化~~如果同学们在学校学过 C你大概率也看不懂“现代C”Q3我上回在某个平台上还看到川普要在2026年全面去C去不去 C 不知道泽胜应该是先要遭殃~~1.7.2 认识响应“报头”header课件内容响应报头的基本格式和请求报头的格式基本一致类似于 Content-TypeContent-Length 等属性的含义也和请求中的含义一致Content-Type响应中的 Content-Type 常见取值有以下几种text / htmlbody 数据格式是 HTMLtext / cssbody 数据格式是 CSSapplication / javascriptbody 数据格式是 JavaScriptapplication / jsonbody 数据格式是 JSON在教务系统主页通过 Ctrl F5 方式强制刷新这四种都能看到1.7.3 认识响应“正文”body课件内容正文的具体格式取决于 Content-Type观察上面几个抓包结果中的响应部分1text / htmlServer: nginx/1.17.3 Date: Thu, 10 Jun 2021 07:25:09 GMT Content-Type: text/html; charsetutf-8 Last-Modified: Thu, 13 May 2021 09:01:26 GMT Connection: keep-alive ETag: W/609ceae6-3206 Content-Length: 12806 !DOCTYPE htmlhtmlheadmeta charsetutf-8meta http-equivX-UA-Compatible body, #app { height: 100%; margin: 0px; padding: 0px; } .chromeframe { margin: 0.2em; background: #ccc; color: #000; padding: 0.2em 0; } #loader-wrapper { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999999; } ……2text / cssHTTP/1.1 200 OK Server: nginx/1.17.3 Date: Thu, 10 Jun 2021 07:25:09 GMT Content-Type: text/css Last-Modified: Thu, 13 May 2021 09:01:26 GMT Connection: keep-alive ETag: W/609ceae6-3cfbe Content-Length: 249790 font-face{font-family:element-icons;src:url(../../static/fonts/element-icons.53 ……3application / javascriptHTTP/1.1 200 OK Server: nginx/1.17.3 Date: Thu, 10 Jun 2021 07:25:09 GMT Content-Type: application/javascript; charsetutf-8 Last-Modified: Thu, 13 May 2021 09:01:26 GMT Connection: keep-alive ETag: W/609ceae6-427d4 Content-Length: 272340 (window[webpackJsonp]window[webpackJsonp]||[]).push([[app],{0:function(t, ……4application / jsonHTTP/1.1 200 Server: nginx/1.17.3 Date: Thu, 10 Jun 2021 07:25:10 GMT Content-Type: application/json;charsetUTF-8 Connection: keep-alive X-Content-Type-Options: nosniff X-XSS-Protection: 1; modeblock Cache-Control: no-cache, no-store, max-age0, must-revalidate Pragma: no-cache Expires: 0 vary: accept-encoding Content-Length: 12268 {msg:操作成功,code:200,permissions:[]}1.8 通过 form 表单构造 HTTP 请求课件内容form表单是 HTML 中的一个常用标签可以用于给服务器发送 GET 或者 POST 请求不要把 form 拼写成 from1.8.1 form 发送 GET 请求form 的重要参数action构造的 HTTP 请求的 URL 是什么method构造的 HTTP 请求的方法是 GET 还是 POSTform 只支持 GET 和 POSTinput 的重要参数type表示输入框的类型。text 表示文本password 表示密码submit 表示提交按钮name表示构造出的 HTTP 请求的 query string 的 key。query string 的 value 就是输入框的用户输入的内容valueinput 标签的值。对于 type 为 submit 类型来说value 就对应了按钮上显示的文本form actionhttp://abcdef.com/myPath methodGET input typetext nameuserId input typetext nameclassId input typesubmit value提交 /form页面展示的效果在输入框随便填写数据点击“提交”此时就会构造出 HTTP 请求并发送出去构造的 HTTP 请求GET http://abcdef.com/myPath?userId100classId200 HTTP/1.1 Host: abcdef.com Proxy-Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/w Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9,en;q0.8注意由于我们的服务器的地址是随便写的因此无法获取到正确的 HTTP 响应体会 form 代码和 HTTP 请求之间的对应关系form 的 action 属性对应 HTTP 请求的 URLform 的 method 属性对应 HTTP 请求的 URLinput 的 name 属性对应 query string 的 keyinput 的内容 对应 query string 的 value1.8.2 form 发送 POST 请求修改上面的代码把 form 的 method 修改为 POSTform actionhttp://abcdef.com/myPath methodGET input typetext nameuserId input typetext nameclassId input typesubmit value提交 /form页面效果不变构造的 HTTP 请求POST http://abcdef.com/myPath HTTP/1.1 Host: abcdef.com Proxy-Connection: keep-alive Content-Length: 22 Cache-Control: max-age0 Upgrade-Insecure-Requests: 1 Origin: null Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/w Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9,en;q0.8 userId100classId200主要的区别method 从 GET 变成了 POST数据从 query string 移动到了 body 中使用 form 还可以提交文件后面再介绍1.9 通过 ajax 构造 HTTP 请求重点课件内容ajax 是 js 提供的 API原生 ajax 非常难用通过 XMLHttpRequest 类 构造请求非常麻烦~~后来有了一个第三方库jQuery$.ajax({ method:get, url:xxxxx, success:function(body){ } })流行了十几年~~2010年之前~~再后来 JS 框架开始崛起前端的三大框架1.Anglar2.Vue3.React做的都比 jQuery 好于是 jQuery 就失宠了~~转而采用一些更轻量的方式来实现 ajax 封装~~像 axios 也是其中之一这个 axios 是当前比较主流的一种前端访问后端的一种方式这都是属于第三方的~~JS 标准里后面也添加 fetch 一套 API原生的 XMLHttpRequert 升级版~~相对于原生的 fetch会更先进一些会搭配 js 的 promise 等语法机制实现更简单的开发过程答疑Q1bootstrap 呢这个不能算是框架这个是个 UI 组件库和 Ant Design 是并列关系UI 组件库是通过 HTML / CSS 来显示一些好看的框架而 Anglar、Vue、React 和界面无关是组织前端代码主要是JS 代码换句话说 UI 组件库只是前端框架的一个组成部分Q2技术总监和架构师是同一级别吗技术总监是单例的CTO架构师则不是技术总监就是最牛的架构师~~Q3我们数据库老师说他是技术总监很多大学老师其实是很牛的~~可能不是上课念PPT牛而是科研能力、掌握的资源……很牛~~从前端角度除了浏览器地址栏能构造 GET 请求form 表单能构造 GET 和 POST 之外还可以通过 ajax 的方式来构造 HTTP 请求并且功能更强大ajax 全称 Asynchronous Javascript And XML是 2005年提出来的一种 JavaScript 给服务器发送 HTTP 请求的方式特点是可以不需要 刷新页面 / 页面跳转 就能进行数据传输在 JavaScript 中可以通过 ajax 的方式构造 HTTP 请求1.9.1 发送 GET 请求创建 test.html在 script标签中编写以下代码此处使用的是 jquery 的 ajax而不是原生 ajax原生 ajax 比较难用!-- 引入 jquery -- script srchttps://code.jquery.com/jquery-3.6.3.min.js/script script $.ajax({ type: get, url: https://www.sogou.com?studentNamezhangsan, // 此处 success 就声明了一个回调函数就会在服务器响应返回到浏览器的时候触发该回 // 正是此处的 回调 体现了 异步 success: function(data) { // data 则是响应的正文部分. console.log(当服务器返回的响应到达浏览器之后浏览器触发该回调通知到咱们) } }); console.log(浏览器立即往下执行后续代码); /script注意如果把 send 中的地址改成其他服务器的地址比如 http://www.sougou.com/index.html 这种大概率是会出错的错误形如这个错误是因为 ajax 默认不能“跨越”也就是“百度下面的 html 中的 ajax 不能访问 搜狗 的内容”这样的设定也是完全合理的如果想要强行进行跨域则需要服务器进行配合在服务器的响应中“允许跨域”才可以咱们的示例服务器 42.192.83.143:8080/AjaxMockServer/info 进行了允许跨域设置因此我们的界面才能访问到其中的数据关于 跨域 这个话题此处不深入讨论浏览器和服务器的交互过程引入 ajax 后在我们当前的例子中test.html 是通过本地文件的方式打开的这个环节不涉及 HTTP 交互后面我们把 test.html 放到 Tomcat 上就会产生上面的效果了1.9.2 发送 POST 请求对于 POST 请求需要设置 body 的内容1.先使用 setRequestHeader 设置 Content-Type2.再通过 send 的参数设置 body 内容发送 application/x-www-form-urlencoded 数据数据格式同 form 的 post!-- 引入 jquery -- script srchttps://code.jquery.com/jquery-3.6.3.min.js/script script $.ajax({ type: post, url: https://www.sogou.com, contentType: application/x-www-form-urlencoded, data: studentNamezhangsan, success: function(data) { // data 则是响应的正文部分. console.log(当服务器返回的响应到达浏览器之后浏览器触发该回调通知到咱们) } }); console.log(浏览器立即往下执行后续代码); /script发送 application / json 数据!-- 引入 jquery -- script srchttps://code.jquery.com/jquery-3.6.3.min.js/script script $.ajax({ type: post, url: https://www.sogou.com, contentType: application/json, data: { name: zhangsan }, success: function(data) { // data 则是响应的正文部分. console.log(当服务器返回的响应到达浏览器之后浏览器触发该回调通知到咱们) } }); console.log(浏览器立即往下执行后续代码); /script其他代码不变只是改下方的代码1.10 通过 Java socket 构造 HTTP 请求课件内容HTTP 请求本质上就是 TCP 请求只需要构造一个字符串符合 HTTP 协议格式写入到 TCP socket 中~~所谓的“发送 HTTP 请求”本质上就是按照 HTTP 的格式往 TCP Socket 中写入一个字符串所谓的“接收 HTTP 响应”本质上就是从 TCP Socket 中读取一个字符串再按照 HTTP 的格式来解析我们基于 Socket 的知识完全可以构造出一个简单的 HTTP 客户端程序用来发送各种类型的 HTTP 请求import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.io.IOException; public class HttpClient { private Socket socket; private String ip; private int port; public HttpClient(String ip, int port) throws IOException { this.ip ip; this.port port; socket new Socket(ip, port); } public String get(String url) throws IOException { StringBuilder request new StringBuilder(); // 构造首行 request.append(GET url HTTP/1.1\n); // 构造 header request.append(Host: ip : port \n); // 构造 空行 request.append(\n); // 发送数据 OutputStream outputStream socket.getOutputStream(); outputStream.write(request.toString().getBytes()); // 读取响应数据 InputStream inputStream socket.getInputStream(); byte[] buffer new byte[1024 * 1024]; int n inputStream.read(buffer); //读到的响应字符串就是符合 HTTP 协议响应报文结构的内容~~ return new String(buffer, 0, n, utf-8); } public String post(String url, String body) throws IOException { StringBuilder request new StringBuilder(); // 构造首行 request.append(POST url HTTP/1.1\n); // 构造 header request.append(Host: ip : port \n); request.append(Content-Length: body.getBytes().length \n); request.append(Content-Type: text/plain\n); // 构造 空行 request.append(\n); // 构造 body request.append(body); // 发送数据 OutputStream outputStream socket.getOutputStream(); outputStream.write(request.toString().getBytes()); // 读取响应数据 InputStream inputStream socket.getInputStream(); byte[] buffer new byte[1024 * 1024]; int n inputStream.read(buffer); return new String(buffer, 0, n, utf-8); } public static void main(String[] args) throws IOException { HttpClient httpClient new HttpClient(42.192.83.143, 8080); String getResp httpClient.get(/AjaxMockServer/info); System.out.println(getResp); String postResp httpClient.post(/AjaxMockServer/info, this is body); System.out.println(postResp); } }使用 Java 构造的 HTTP 客户端不再有“跨越”限制了此时也可以用来获取其他服务器的数据了跨域只是浏览器的行为对于 ajax 有效对于其他语言来说一般都和跨域无关、HttpClient httpClient new HttpClient(www.sogou.com, 80); String resp httpClient.get(/index.html); System.out.println(resp); // 此时可以获取到 搜狗主页 的 html1.11 通过 Postman 工具构造 HTTP 请求也是工作中经常用到的情况实际开发中像上面讲的那几种方式我们一般很少用 Java 去构造 HTTP 请求除非是写爬虫另外 ajax 这一套是前端开发去干的前端开发才会去通过 js 去构造跟咱们关系也不是特别大而通过 Postman 这样的工具构造 HTTP 请求跟我们的关系是比较大的因为以后我们写一个服务器程序肯定要测试咋测试由于前端和后端是分开开发的当你把后端代码写完后前端可能还没开始写那你就不测了吗当然不是此时我们就可以通过工具来构造请求访问服务器来验证其功能Postman 就是其中很常见的一种工具Postman 也是老牌的 HTTP 构造工具了最初是 chrome 的一个插件后来由于太好用了影响力太大了就单独独立出来了企业也是用这个~~答疑接口文档后端写吗前后端一起商量好具体谁写不一定~~1.11.1 下载 Postman直接去 Postman 官网下载即可1.11.2 创建账号1.11.3 运行 Postman 并初步配置非专业人士点击 NO 即可新手小白比如大学生填成下面这样就可以如果你是专业人士也可以自定义填写1.11.4 使用 Postman在 Workspaces 部分 新建一个完成填写后新建创建成功设置请求并输入网址Params配置查询字符串HeadersBody正文Scripts是执行前的脚本我们用的不多Tests 和 Settings 我们就不过多关注了整体上来说通过这里的界面就可以把一个 HTTP 请求里的各个部分从方法到 URL再到路径、再到参数、再到各种 Header 头咱们都可以去进行设置接着我们点击 Send 发送请求有了这个之后我们就可以很方便的去构造请求来去验证我们这里的程序是否正确~~其实 Postman 的基本使用还是非常简单的相比于这些简单朴素的工作来说这个 Postman 还有一个非常香的功能我们会发现这里有个代码模板功能手动构造的请求都能自动转成代码~~而且这里还支持了很多种语言如果后续你需要代码构造这么个请求就直接把这个代码复制粘贴过来就可以了~~这个功能放在前几年还是很香的但是现在大家已经觉得没啥了AI 都能写代码的年代了~~1.12 通过 Apifox 构造 HTTP 请求Apifox 目前国内用的越来越多了~~因为 Postman 是外国搞的而 apifox 是国内团队搞的“中国人更懂中国人”~~相比之下Apifox 最大的优势是可以直接编写 接口文档~~以前我们写接口文档都是拿文本文档来写比较麻烦而 Apifox 就可以像填空一样给写出来比较方便1.12.1 下载 Apifox直接去 Apifox 官网下载即可一路 next 即可完成1.12.2 创建账号直接微信扫码关注公众号登录即可1.12.3 运行 Apifox 并初步配置直接跳过即可1.12.4 使用 Apifox完成上述步骤后就来到了这个界面我们发现其余内容与 Postman 基本上一摸一样但是功能会更加详细、丰富~~答疑公司现在是用哪个都有只不过是功能上略有差异~~以前的时候清一色都是 PostmanApifox 属于后起之秀抢占了 Postman 一部分市场具体抢占了多少咱这儿也没有具体数据~~后续挑战项目的时候会介绍 Apifox 的一些情况~~使用起来要更麻烦一点上述 HTTP 报文格式的内容需要重点掌握~~这都是 工作经常用面试高频考题~~fiddler、postman、apifox 这些工具大家也要能够掌握~~