学习Web开发不好好学习HTTP报文,将会“打拳不练功,到老一场空”,你花在犯迷糊上的时间比你沉下心来学习HTTP的时间肯定会多很多。
Http请求报文解析
- 请求行 下图123(第一行)
- 请求头
- 请求体
请求行
- 1是请求方法,get和post是最常见的HTTP方法。
- 2为请求对应的url + 3为http协议版本
请求头
- 4是是http的报文头,报文头包含若干个属性,格式为“属性名:属性值”服务端根据此获取客户端的信息
请求体
+5是报文体,它将一个页面表单中的组件值通过param1=value1 p a r a m 2 = v a l u e 2 的 键 值 对 形 势 编 码 成 一 个 格 式 化 串 , 它 承 载 多 个 请 求 参 数 的 数 据 。 不 但 报 文 体 可 以 传 递 请 求 参 数 , 请 求 u r l 也 可 以 通 过 / t e s t . h t m l ? p a r a m 1 = v a l u e 1 param2=value2的键值对形势编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求url也可以通过/test.html?param1=value1 param2=value2的键值对形势编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求url也可以通过/test.html?param1=value1param2=value2的方式来传递请求参数
得出以下图片
更详细的表达一个报文的结构
常见的Http报文属性
-
- Accept
请求报文头可以通过Accept报文头属性 来告诉服务端,客户端接收什么类型
- Accept
//例如
Accept:text/plain
- Accecpt属性的值可以为 一个或多个MIME类型的值
-
- Referer 表示这个请求是从哪个url来的
比如说你从A网站,点击了一个广告到了B网站,referer就是A网站的网址
- Referer 表示这个请求是从哪个url来的
-
- Cache-Control
对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。
如以下设置,相当于让服务端将对应请求返回的响应内容不要在客户端缓存:
- Cache-Control
Cache-Control: no-cache
- 更多报文属性
如何访问请求报文头
请求报文头是由客户端发来的,由服务端进行读取。以下是HttpServletRequest一些用于读取请求报文头的API
//获取请求报文中的属性名称
java.util.Enumeration<java.lang.String> getHeaderNames();
//获取指定名称的报文头属性的值
java.lang.String getHeader(java.lang.String name)
由于一些请求报文头属性“太著名”了,因此HttpServletRequest为它们提供了VIP的API
//获取报文头中的Cookie(读取Cookie的报文头属性)
Cookie[] getCookies() ;
//获取客户端本地化信息(读取 Accept-Language 的报文头属性)
java.util.Locale getLocale()
//获取请求报文体的长度(读取Content-Length的报文头属性)
int getContentLength();
HttpServletRequest可以通过
HttpSession getSession()
获取请求所关联的HttpSession,其内部的机理是通过读取请求报文头中Cookie属性的JSESSIONID的值,在服务端的一个会话Map中,根据这个JSESSIONID获取对应的HttpSession的对象。(这样,你就不会觉得HttpSession很神秘了吧,你自己也可以做一个类似的会话管理 )
HTTP响应报文解剖
响应报文结构
- 响应行 下图12(第一行)
- 响应头
- 响应体
- 1.报文协议及版本
- 2.状态码及状态描述
- 3.响应报文头,也是由多个属性组成的
- 4.相应报文体,即我们 真正需要的信息
响应状态码
与请求报文相比,响应报文多了一个“响应状态码”,它以“清晰明确”的语言告诉客户端本次请求的处理结果。
常见状态码
1xx 消息,一般是告诉客户端,请求已经收到了,正在处理,别急...
2xx 处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息.
3xx 重定向到其它地方。它让客户端再发起一个请求以完成整个处理。
4xx 处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。
5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。
有些响应码,Web应用服务器会自动给生成。你可以通过HttpServletResponse的API设置状态码:
//设置状态码,状态码在HttpServletResponse中通过一系列的常量预定义了,如SC_ACCEPTED,SC_OK
void setStatus(int sc)
常见的http响应报文头属性
-
- Cache-Control
响应输出到客户端后,服务端通过该属性告诉客户端如何控制响应内容的缓存
- Cache-Control
-
下面的设置让客户端对响应内容缓存3600秒,也即在3600秒内,如果客户再次访问该资源,直接从客户端的缓存中返回内容给客户,不要再从服务端获取(当然,这个功能是靠客户端实现的,服务端只是通过这个属性提示客户端“应该这么做”,做不做,还是决定于客户端,如果是自己宣称支持HTTP的客户端,则就应该这样实现)。
Cache-Control: max-age=3600
-
- ETag
- 一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会发生变化,它是Cache-Control的有益补充,可以让客户端“更智能"地处理什么时候从服务端取资源,什么时候可以直接从缓存中返回响应
- 3.Location
- 我们在JSP中让页面Redirect到一个某个A页面中,其实是让客户端再发一个请求到A页面,这个需要Redirect到的A页面的URL,其实就是通过响应报文头的Loaction属性告诉客户端的,如下报文头属性,将客户端redirect到iteye的页面中
Location: http://www.iteye.com
- 4.Set-Cookie
- 服务端可以设置客户端的Cookie,其原理就是通过这个响应报文头属性实现的
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Cookie,Location这些响应都是有福之人,HttpServletResponse为它们都提供了VIP版的API
//添加Cookie报文头属性
void addCookie(Cookie cookie)
//不但会设置Location的响应报文头,还会生成303的状态码呢,两者天仙配呢
void sendRedirect(String location)