HTTP协议相关
什么是HTTP
http协议是hyper text transfer protocol(超文本传输协议)的简写,基于TCP/IP通信协议传递数据。http协议是应用层的面向对象的协议,工作在客户端-服务器架构上。浏览器作为http客户端通过url向http服务端即web服务器发送所有请求,web服务器收到请求后,向客户端发送响应信息。
https://upload-images.jianshu.io/upload_images/2964446-5a35e17f298a48e1.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/551/format/webp
HTTP报文结构
http request报文
报文由三部分组成:分别是请求行、请求头和请求体。
以一个实际的例子来说明
- 请求行中包含:请求方法、请求资源(uri)和http版本号。请求方法包含get、post、put、delete等
- 请求头包含若干个属性,格式为
属性名:属性值
- Accept:通过这个字段告诉服务器客户端接收什么类型的响应,通常有text/plain、application/json等格式
- Cookie:服务器通过Cookie值知道客户端的多个请求属于一个Session
- Referer:表示这个请求从哪个URL而来
- Cache-Control:对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。
- 其他参见:https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
- 请求体:请求中需要传递的参数
如何访问请求头中的信息
访问请求头中的信息可以通过类HttpServletRequest去获取,而在springMVC中,HttpServletRequest要通过RequestContextHolder来获取。具体使用方式参见:
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest httpServletRequest = ((ServletRequestAttributes)requestAttributes).getRequest();
// 获取所有头部名字并追加到sb中
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
StringBuilder sb = new StringBuilder();
while (headerNames.hasMoreElements()) {
String ele = headerNames.nextElement();
sb.append(ele + " ; ");
}
// 获取特定头部 值并追加到sb
Enumeration<String> headers = httpServletRequest.getHeaders("content-type");
sb.append("\n");
while (headers.hasMoreElements()) {
sb.append(headers.nextElement() + " ; ");
}
// 获取Cookie
Cookie[] cookies = httpServletRequest.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("content-type")) {
sb.append("\n" + cookie.getValue());
break;
}
}
// 获取sessionId
HttpSession session = httpServletRequest.getSession();
sb.append("\nsessionId:" + session.getId());
http response报文
response报文也主要由响应行、响应头、响应体组成:
以一个实际的例子来说明
- 响应行:包括报文协议及版本、状态码及状态描述
- 状态码主要分为5段,分别是
- 1xx:告诉客户端,请求已收到,正在处理
- 2xx:处理成功,一般表示请求已受理、已经处理完成等信息
- 3xx:重定向到其他地方,要客户端再发起一个请求以完成整个处理
- 4xx:处理发生错误,责任在客户端,如客户端请求一个不存在的资源,客户端未被授权、禁止访问等
- 5xx:处理发生错误,责任在服务器,如服务端抛出异常、路由出错、http版本不支持等等
- 状态码主要分为5段,分别是
- 响应头:由多个属性组成
- cache-control:响应输出到客户端后,服务端通过该报文头告诉客户端如何控制响应内容的缓存
- ETag:一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会相应发生变化。它是Cache-Control的有益补充,可以让客户端“更智能”地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。
- Location:我们在JSP中让页面Redirect到一个某个A页面中,其实是让客户端再发一个请求到A页面,这个需要Redirect到的A页面的URL,其实就是通过响应报文头的Location属性告知客户端的
- Set-cookie:设置客户端的Cookie
- 其他报文头详见:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
- 响应体
如何访问http response中的信息
在服务端,可以通过HttpServletResponse去读取、设置请求头中的信息。HttpServletResponse中主要包含如下API。
// 添加cookie到response头中,该函数可被多次调用,加入不同name的cookie
public void addCookie(Cookie cookie);
// 检查response header中是否包含名为name的头部
public boolean containsHeader(String name);
// encode url和redirect url,返回编码后的url
public String encodeURL(String url);
public String encodeRedirectURL(String url);
// 响应头相关
public void setHeader(String name, String value);
public void addHeader(String name, String value);
public void setIntHeader(String name, int value);
public void addIntHeader(String name, int value);
public void setDateHeader(String name, long date);
public void addDateHeader(String name, long date);
public String getHeader(String name);
public Collection<String> getHeaders(String name);
public Collection<String> getHeaderNames();
// 响应状态相关
public void setStatus(int sc);
public int getStatus();
//不但会设置Location的响应报文头,还会生成303的状态码呢,两者天仙配呢
public void sendRedirect(String location) throws IOException;
参考文章
Http请求、响应结构体介绍:https://blog.csdn.net/u010256388/article/details/68491509
Http协议介绍:https://www.jianshu.com/p/80e25cb1d81a
RequestContextHolder分析:https://juejin.im/entry/584bac6eb123db0066127bae