愿你如阳光,明媚不忧伤。
目録
1. HTTP 请求
HTTP Request 指从客户端到服务器端的请求消息。当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息,HTTP请求信息由4部分组成:
- 1.请求行(Request Line):由3部分组成,请求方法、请求URI、协议/版本,它们用空格分隔。
- 2.请求头(Request Header):包含许多有关的客户端环境和请求正文的有用信息。
- 3. 空行(Blank Line):请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。
- 4. 请求正文:用于存放需要发送给服务端的数据信息。
1.1 HTTP 请求行
请求行以一个方法名开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:
Method Request-URI HTTP-Version CRLF
其中 Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。
方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed);当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。当然,所有的方法支持的实现都应当符合下述方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。
1.1.1 请求方法
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
-
GET
平时网页的一些基本的URL都是GET请求的,用于执行查询操作。使用GET方法时,请求参数和对应的值附加在URL后面,利用问号(“?”)代表URL的结尾与请求参数的开始,各个数据之间用(“&”)符号隔开。所以GET方式的请求一般不包含“请求内容”部分,请求数据以地址的形式表现在请求行。
例如:/index.jsp?id=100&name=ouseki。
因此就会有下面的问题:
1.数据都明文暴露,用户可以直接看到
2.数据长度有限制,不适合传送大量数据
-
POST
由于上面GET的缺点,POST正好弥补了这些问题。POST方法把数据都存放在请求体body里面,以名称/值的形式出现,这样既突破了长度的限制,又保证用户无法直接看到。POST方式大多用于页面的表单中。
-
HEAD
HEAD请求仅要求服务器返回头部信息,不会返回相应体。不需要传输任何实际内容,通常用于测试数据是否存在、当做心跳检测等等。
-
PUT
与GET相反,用于改变某些内容。上传某些资源。
-
PATCH
这个方法不太常见,是servlet 3.0提供的方法,主要用于更新部分字段。与PUT方法相比,PUT提交的相当于全部数据的更新,类似于update;而PATCH则相当于更新部分字段,如果数据不存在则新建,有点类似于neworupdate。
-
DELETE
删除某些资源
-
TRACE
要求目标服务器返回原始HTTP请求的内容。可以理解成我们为了看看一条请求在到达服务器前数据发生了什么变化。使用这个命令,它会在最后一站返回原始信息,这样就可以观察到中间是否修改过请求。
-
OPTIONS
询问服务器支持的方法。把URL设置为("*")可以查看服务器支持的所有请求方法
-
CONNECT用于某些代理服务器,能把请求的连接转化为一个安全隧道。
在控制器中,我们可以通过设置RequestMapping的method方法,改变接收数据controller。虽然URL是一样的,但是由于请求方法不同,他们会根据请求方法使用相应的控制器方法处理请求。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class RequestMappingMethodController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public @ResponseBody String get() {
return "get";
}
@RequestMapping(value = "/test", method = RequestMethod.POST)
public @ResponseBody String post() {
return "post";
}
}
1.1.2 URL
URL:统一资源定位符,是一种资源位置的抽象唯一识别方法。
组成:<协议>://<主机>:<端口>/<路径>
端口和路径有时可以省略(HTTP默认端口号是80,HTTPS默认端口号是443)
1.1.3 协议及版本
协议版本的格式为:HTTP/主版本号.次版本号,常用的有HTTP/1.0和HTTP/1.1
- demo
1.2 HTTP 请求头
每个请求头由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,请求头可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。请求头通知服务器有关于客户端请求的信息,典型的请求头有:
更多请求头参见 → List of HTTP header fields
- Connection
表示是否需要持久连接。如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片)能显著地减少下载所需要的时间。Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,当客户端再次发送Request,需要重新建立TCP连接。
Connection: keep-alive
- Host
发送请求时,该报头域是必需的。主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。
Host: sentry.csdn.net
- User-Agent
告诉服务器, 客户端使用的操作系统和浏览器的名称和版本。
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
- Accept
客户端可识别的内容类型列表。
更多MIME类型请参考 → Media type
Accept:text/plain
- Cookie
最重要的header,客户端的Cookie就是通过这个报文头属性传给服务端的。
服务端是怎么知道客户端的多个请求是隶属于一个Session呢?注意到后台的那个jsessionid=5F4771183629C9834F8382E23BE13C4C木有?原来就是通过HTTP请求报文头的Cookie属性的jsessionid的值关联起来的!也可以通过重写URL的方式将会话ID附带在每个URL的后面。
Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23BE13C4C
- Referer
表示这个请求是从哪个URL过来的,假如你通过百度搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是https://www.baidu.com。
Referer: https://www.baidu.com/
- Cache-Control
对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。
Cache-Control:Public 可以被任何缓存所缓存
Cache-Control:Private 内容只缓存到私有缓存中
Cache-Control:no-cache 所有内容都不会被缓存
1.3 空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
1.4 HTTP 请求正文
请求正文不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求正文相关的最常使用的请求头是Content-Type和Content-Length。
2. HTTP 响应
HTTP Response 在接收和解释请求消息后服务器端返回来的响应消息。与 HTTP 请求类似,HTTP响应信息也由4部分组成:
- 1. 状态行(Status Line):由2部分组成,协议版本、状态码及状态描述
- 2. 响应头(Response Header):包含许多有关的服务端环境和响应正文的有用信息。
- 3. 空行(Blank Line):响应头和响应体之间是一个空行,这个行非常重要,它表示响应头已经结束,接下来的是响应正文。
- 4. 响应正文(Response Body):用于存放需要返回给客户端的数据信息。
2.1 HTTP 状态行
和请求报文相比,响应报文多了一个“响应状态码”,它以“清晰明确”的语言告诉客户端本次请求的处理结果。状态行格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF
其中,HTTP-Version表示服务器HTTP协议的版本,Status-Code表示服务器发回的响应状态代码,Reason-Phrase表示状态代码的文本描述。状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
2.1.1 状态码及状态描述
了解更多 → 浏览器状态码详解
分类 | 描述 |
---|---|
1xx 消息 | 一般是告诉客户端,请求已经收到了,正在处理,需要请求者继续执行操作 |
2xx 处理成功 | 操作被成功接收并处理 |
3xx 重定向到其它地方 | 需要进一步的操作以完成请求 |
4xx 客户端处理发生错误 | 如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等 |
5xx 服务端处理发生错误 | 如服务端抛出异常,路由出错,HTTP版本不支持等 |
2.2 HTTP 响应头
了解更多 → List of HTTP header fields
- Content-type
用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。如下设置,将决定浏览器以HTML形式解析数据。
了解更多 → HTTP content-type
Content-Type: text/html; charset=utf-8
- Cache-Control
响应输出到客户端后,服务端通过该报文头属告诉客户端如何控制响应内容的缓存。
如下设置让客户端对响应内容缓存3600秒,即在3600秒内,如果客户再次访问该资源,将直接从客户端的缓存中返回内容给客户,不需要再从服务端获取 。当然,这个功能是靠客户端实现的,服务端只是通过这个属性提示客户端应该这么做,做不做还是取决于客户端,如果是自己宣称支持HTTP的客户端,则就应该这样实现。
Cache-Control: max-age=3600
- ETag
一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会相应发生变化。它是Cache-Control的有益补充,可以让客户端更智能地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。
关于ETag的说明可以参见 → HTTP ETag
Spring 3.0还专门为此提供了一个org.springframework.web.filter.ShallowEtagHeaderFilter用于生成响应的ETag。实现原理很简单,对JSP输出的内容MD5,这样内容有变化ETag就相应变化了,可以帮助减少请求和响应的交互。
ETag: "737060cd8c284d8af7ad3082f209582d"
- Location
表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。如下的报文头属性,将使客户端redirect到百度的首页中:
Location: http://www.baidu.com
- Set-Cookie
设置和页面关联的Cookie。Servlet不应使用response.setHeader(“Set-Cookie”, …),而是应使用HttpServletResponse提供的专用方法addCookie。
Set-Cookie: UserID=ouseki; Version=1
2.2.1 在服务端通过HttpServletResponse的API写响应报文头
// 添加一个响应报文头属性
void setHeader(String name, String value) {
}
// Cookie,Location这些响应HttpServletResponse为它们都提供了VIP版的API:
// 添加Cookie报文头属性
void addCookie(Cookie cookie) {
}
// 不但会设置Location的响应报文头,还会生成303的状态码
void sendRedirect(String location) {
}
2.3 HTTP 响应正文
用于存放需要返回给客户端的数据信息,配合Content-type响应头使用。
【每日一面】
URI、URL、URN三者之间的关系
URI (Uniform Resource Identifier)统一资源标识符。是一个用于标识某一互联网资源名称的字符串,提供资源访问,在某一规则下能把一个资源独一无二地标识出来。包括URL或者URN或者两者一起,例如通过身份证号码可以确定一个人,也可以通过家庭住址确定一个人,也可以结合家庭住址和姓名确定一个人。
URL (Uniform Resource Locator)统一资源定位符。提供资源标记,如同一个人的住址。最大的缺点是当信息资源的存放地点发生变化时,必须对URL作相应的改变。因此人们正在研究新的信息资源表示方法,例如URN、URC等。
URN (Uniform Resource Name)统一资源名。提供资源命名,如同一个人的姓名。URN不依赖于位置,并且有可能减少失效连接的个数。它可以允许人们在不指出其位置和获得方式的情况下获得资源。
URL和URN都是URI的一个子集,URL指定要使用的协议类型,而URI不涉及协议规范