目录
- web应用中的基本单位是web资源,但是web资源是分布在网络中的任意主机上,所以本机的浏览器想要获取这些web资源,必须通过一种网络协议来实现——Http协议
- Hyper 超Text 文本 Transer传输 Protocol协议
- HTTP协议的是以web资源为基本单位,每次请求也是针对一个web资源进行
- Http协议设计之初,是为传输超文本,HTML的前身,随着互联网的发展,HTTP协议传输的不仅仅是超文本,目前其实任意类型都是可以的,其前端三剑客的主流,但是其他多媒体资源也是可以的
- HTTP协议是一套应用层协议,(一开始是专注于业务,但现在HTTP协议本身也成为了基础的协议之一了),所以HTTP协议必须在一套传输层协议(TCP UDP)的基础上进行传输,
- HTTP在1.0,1.1.,2.0是基于TCP协议进行工作,HTTP本身没有做什么可靠性的服务,必须依靠传输层的可靠性(我们从HTTP1.0,1.1协议)
- HTTP在3.0之后,开始基于UDP协议进行,(HTTP协议内部自己完成了可靠性的工作)

一次完整的HTTP分为
- 请求 客户端发起 服务器接收
- 响应 客户端接收 服务器发起
所以对应着两种格式:请求格式,响应格式
请求格式中携带的信息有哪些
- 访问的是那个web资源(URL来标识)
- 当前获取的这个资源的内容(还是将用户的输入提交到资源上,不同的请求方法来表明)
- 本次采用的是那个HTTP协议(请求行带有协议的版本号)
- 本次请求的一些描述信息(请求头)
- 如果本次是要提交信息给服务器,这些信息也得携带
例子
响应格式的信息有哪些
- 本次响应的版本号(响应行带有版本号)
- 本次响应的结果(响应行带有状态)
- 本次响应的一些描述信息(响应头)
- 返回给请求方的资源(响应体)
为什么 HTTP 报文中要存在 "空行"?
- 因为 HTTP 协议并没有规定报头部分的键值对有多少个. 空行就相当于是 "报头的结束标记", 或者 是 "报头和正文之间的分隔符".
- HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 "粘包问题".
自己写的HTTP协议
package com.lsc.demo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class MyHttpClient { public static void main(String[] args) throws Exception { // 只能进行一次请求-响应的 HTTP 客户端 // 主机 127.0.0.1 // 端口(进程) 8080 // 资源路径 /hello.html try (Socket socket = new Socket("127.0.0.1", 8080)) { // 准备 HTTP 请求内容 // 文本 String // 格式:请求行 String requestLine = "GET /hello.html HTTP/1.0\r\n"; // 请求头:完全可以没有,但必须一个空行结尾 String requestHeader1 = "Name: peixinchen\r\n\r\n"; // 请求头中共有 1对 key-value String requestHeader2 = "Name: peixinchen\r\nAge: 1993\r\n\r\n"; // 请求头中共有 2对 key-value String requestHeader3 = "\r\n"; // 请求头中共有 0 对 key-value // 请求体,GET 是没有请求体 // 最终的请求 —— 要发送给服务器的东西 String request = requestLine + requestHeader3; // 发送服务器的过程 byte[] requestBytes = request.getBytes("ISO-8859-1"); // 字符集编码 // 发送(数据会经由 TCP、IP、以太网发送给服务器) OutputStream os = socket.getOutputStream(); os.write(requestBytes); os.flush(); // 请求既然已经发送,我们要做的就是等待响应 InputStream is = socket.getInputStream(); Scanner scanner = new Scanner(is, "UTF-8"); // 响应的前面字符集应该是 ISO-8859-1,后边是 UTF-8 while (scanner.hasNextLine()) { String line = scanner.nextLine(); System.out.println(line); } } } }自己写的服务器
package com.lsc.demo; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class MyHttpServer { public static void main(String[] args) throws IOException { try (ServerSocket serverSocket=new ServerSocket(8080)){ while (true){ Socket socket=serverSocket.accept();//三次握手建立结束 // 读取用户的请求 这里就不具体读了,一律采用相同的方式回应 //发送响应 响应体 资源内容 // Content-Type: 浏览器应该按照什么格式来看到我们响应的资源内容的(资源内容放在响应体中) //响应体的资源 String responseBody="Welcome MyHttpServer
"; byte[] responseBodyBytes=responseBody.getBytes(StandardCharsets.UTF_8); int contentLength=responseBody.length(); String response="HTTP/1.0 200 OK \r\n" +"Sever: lsc\r\n" +"ContentType: text/html; charset=utf-8\r\n" +"ContentLength:"+contentLength+"\r\n" +"\r\n"; byte[] responseBytes=response.getBytes("ISO-8859-1"); OutputStream os=socket.getOutputStream(); os.write(responseBytes); os.write(responseBodyBytes); os.flush(); //发送完毕之和,直接关闭TCP连接 socket.close(); } } } }我们自己写的服务器的信息
基本格式
- 作用:平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.
- https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql ),换句话说,URL不仅仅针对HTTP协议设计的,网络中是所有资源都可以用URL来命名 ftp://协议,文件传输协议
- user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
www.example.jp: 服务器地址 . 此处是一个 " 域名 ", 域名会通过 DNS 系统解析成一个具体的 IP 地址 . (通过 ping 命令可以看到 ),通过IP来确定处于网络中的那台主机 端口号 : 端口号来确定资源是由服务器的那个进程提供的 . 当端口号省略的时候 , 浏览器会根据协议类型自动决定使用 哪个端口. 例如 http 协议默认使用 80 端口 , https 协议默认使用 443 端口![]()
- /dir/index.html: 带层次的文件路径. 因为即便是同一个进程,也会管理着多个资源,所以需要通过路径确定
- uid=100: 查询字符串(query string). 本质是一个键值对结构. 键值对之间使用& 分隔. 键和值之间使用 = 分隔.其形式是?name1=v1&name=v2
- 片段标识: 此 URL 中省略了片段标识. 片段标识主要用于页面内跳转.
URI和URL的区别
- URL是唯一资源路径
- URI是唯一的资源标识符,URL是URI的子集
URL 中的可省略部分
- 协议名: 可以省略, 省略后默认为 http://
- ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
- 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
- 带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问 /index.html
- 查询字符串: 可以省略
- 片段标识: 可以省略
情景一
情景二通过资源来引用另一个资源
- /dir/world.html表示的是绝对路径,以static为根目录
- ./chengoeixin.html相对路径,以当前文件所在的目录为根目录./表示就是当前文件目录java,../表示当前文件目录的父级目录
URL内容的要求
- URL中的字符是有一定的要求,出现在URL中的字符必须在一个特顶的集合中,比如汉字这种都有不允许出现在URL中的,但是如果想在URL中携带这些非标准的字符,就需要通过URL编码,将其转换为标准字符集
URL编码的大体规则
- 并且有些字符有着特顶的用途,?# & /都有其标准的含义的
- 表示动态资源要接收两个参数 name值放到String name 变量中
- required=false,表示可以不传,默认值为null
基于SSM进行的Web开发
- SSM SpringBoot+SpringMVC+Mybatis组合形成的一套框架。是为了方便的进行Web开发,会大量使用注解进行代码标注
- SpringBoot 提供了loC功能(DI服务)
- SpringMVC:提供了Web开发的能力
- Mybatis提供了比直接使用JDBC进入另一种编程范式中
几个Spring常用的注解
- @Controller :表示这个类可以作为动态资源的承载容器存在,具体的动态资源是Java方法实现
- 被这几个注解其中的一个修饰的方法(并且存在于@Controller修饰的类中),会被作为一个动态资源存在,资源的最终的URL路径就是注解中标注的这个路径
- 如果存在路径完全相同的两个动态资源,则服务器就会启动失败,因为违法了URL是资源的唯一标识符
@ResponseBody
- 响应体,这个注解修饰方法的,表示该方法完整地返回整个响应体的内容,
- 方法返回的String类型的值,会被当成HTTP的响应的响应体,然后及那个HTTP协议,传递给客户端(浏览器),内容格式类型,默认采用text/html(HTML的格式体现)
- 响应体就是
....
,默认的格式是HTML格式在网页显示
总结
- @Controller创建一个类
- @RequestMapping/@GetMapping/@PostMapping来修饰一个方法并且带上唯一的资源路径(绝对路径)
- 方法返回值类型是String,无形成
- @ResponseBody修饰方法
- 返回HTML内容
- 我们在浏览器直接输入URL访问,都是GET方法,
- 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求.,浏览器会自动发起对资源的请求,不需要用户介入
- ,需要用户点击之后,才会发起新的资源请求
- POST,不借助第三方的工具的情况下,只有两种方法可以做到
- 利用
表单 - 使用JS发起HTTP请求(一般称为ajax)
关于form表单发起POST
img标签的自动请求
a标签的点击之后请求
使用JavaScripts来发起请求
//1实例化一个XMLHttpRequest对象 var xhr=new XMLHttpRequest() //2调用对象的open方法, 设置发送请求的方法 资源路径 xhr.open('get','/demo') //xhr.open('post,'/demo') //设置回调函数,当/demo资源响应返回的时候,应该干什么 //提供事件绑定机制 //事件:load事件(当响应返回的时候) //事件处理 回调函数 xhr.onload=function(){ console.log(xhr.status)//打印响应的状态 成功是200 console.log(xhr.responseText)//打印响应的响应体 //还有其他东西,现在不关心 } //4真正的发送请求出去 xhr.send()
执行顺序
面试题 GET VS POST
- 两个方法表示的语义不同,GET表示的是获取,POST表示的是发布
- 表现现象不同,GET应该具有幂等性的,并且无副作用,POST应该不具备幂等性,并且有副作用,具有幂等性且无副作用的HTTP请求是可以被缓存的
- GET请求不允许有HTTP请求体,但是POST方法请求允许有请求体(不是必须有)
- POST稍微比GET安全一点点,对于GET数据放在URL中很容易被看到,POST放在了请求体中(两者都是不安全的),GET是通过query string中不论携带什么数据,总体上必须满足key=value的形式,但是POST非常灵活
何为缓存
- 基于性能的考虑,所以每次的请求并不是都需要服务器参加(请求服务器需要经过网络,相对来说性能耗时比较久),暂时的保留一段事件,供下次使用
- 1xx表示处于一定的流程中,基本很少见到 HTTP->WebSocket
- 2xx表成功
- 3xx表示重定向/缓存等操作
- 4xx客户端导致的失败
- 5xx服务器导致的失败
- 200(成功) 400(请求错误,最常见的就是确实必要的参数) 405(请求的方法,该资源不支持,比如不支持方法),500(服务器错误,代码出现异常) 404(访问了不正确的资源路径)
如何做到200
- 访问正确的资源路径
- 使用正确的方法
- 参数必须符合
如何做到400
- 访问正确的资源路径
- 访问正确的方法
- 由于客户端的错误,可能是用户没有按照资源的要求来
如何做到404
- 访问不正确的资源路径
如何做到405
- 资源路径正确,但是访问的HTTP方法不正确
如何做到500
- 服务器出现异常,服务器的代码出现了问题
站内和站外重定向
永久重定向和临时重定向
- 永久重定向的意思就是我去买石头记,说石头记以后都没有,要买就买红楼梦了,永久重定向的状态码是301,用的非常少
- 临时重定向的意思,这几天没有了石头记,先买红楼梦,以后再买石头记就可以直接买302
临时重定向的继续划分
发送请求的方式根重定向的联系
转发