1. HTTP的基本性质
1.1 优点
- 支持客户端/服务器模式。
即客户端打开连接发出请求,然后服务器根据该请求给出响应;
- 简单快速。
HTTP的报文格式是header+body,头部信息是key-value,文本简单,同时客户向服务器请求服务时,只需传送请求方法和路径;
- 灵活
HTTP允许传输任意类型的数据对象.
1.2 缺点
- HTTP是无状态的。
在同一个连接中,两次执行成功的请求之间没有任何关系。
优点:因为服务器不会去记录HTTP的状态,所以不需要额外的资源来记录状态信息,减轻了服务器的负担;
缺点:因为没有记忆能力,如果后续操作需要前面的信息,必须重传,效率低。例如,用户在进行购物时,用户将某一个商品加入购物车,切换页面后,再次添加另一个商品,者两次添加商品的请求之间没有任何关系。因此,浏览器就无法知道用户最终选择了哪些商品。可使用HTTP的头部进行扩展来解决此问题。
2. HTTP无状态的解决方案
2.1 Cookie(小甜饼)
- 定义
- 是服务器发送到浏览器,并保存到浏览器的一小块数据;
- 浏览器下次访问该服务器时,会自动携带该块数据,将其发送给服务器。
- 主要用于服务器判断请求是否来自同一个浏览器。
- 原理
- 通过在请求和响应报文中写入Cookie信息来控制客户端的状态。当客户端第一次向服务器请求信息时,会在服务器端生成一个客户端特有的识别码,以此为索引放在服务器的后端数据库中,并在响应报文中添加cookie返回,客户端会保存Cookie信息;
- 当该客户端再次向服务器发送请求报文时,会在请求报文中添加Cookie信息,服务器在收到请求报文时,检查后端数据库中是否在存在Cookie,提高了回复相应报文的速度。
- 在项目中的实际应用
问题1:客户端如何得到Cookie?答: 服务器端给出响应。
问题2:服务器端如何验证Cookie?答:客户端发送请求。
程序编写思路:
- 服务器端生成cookie,然后放在响应报文的头部,返回给浏览器
1.1 生成Cookie,每个cookie是一个key-value对象;
1.2 设置Cookie的生效路径(即访问路径为哪些时,才会带上Cookie);
1.3 设置Cookie的生存时间(即关闭浏览器Cookie可能就删除了).- 浏览在下次请求的时候会带上cookie。
- 程序代码测试
/*
* 服务器生成Cookie
* */
@RequestMapping(path = "/cookie/set", method = RequestMethod.GET)
@ResponseBody
public String setCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("code", CommunityUtil.generateUUID());
cookie.setMaxAge(60 * 10);
cookie.setPath("/community/alpha");
response.addCookie(cookie);
return "set cookie";
}
/*
* 浏览器发送Cookie
* */
@RequestMapping(path = "/cookie/get", method = RequestMethod.GET)
@ResponseBody
public String getCookie(@CookieValue("code") String code) {
System.out.println(code);
return "get cookie";
}
- 缺点:因为保存在客户端,不安全,引入Session机制
2.2 Session
- 定义
- 用于在服务端记录客户端信息;
- 数据放在服务端会更加安全,但是会增加服务端的内存压力。
- 原理
- 服务器端生成一个Session,存储浏览器的各种信息,同时有唯一的一个sessionId,服务器通过识别这个sessionId来实现业务的连续;
- 同时服务器端隐式的生成一个Cookie用于存放sessionId,会放在响应报文中返回给浏览器,浏览器会保存Cookie;
- 下次访问服务器时会携带此Cookie用于判断.
- 程序代码测试
/*
* 服务器端生成session
* */
@RequestMapping(path = "/session/set", method = RequestMethod.GET)
@ResponseBody
public String setSession(HttpSession session) {
session.setAttribute("id", 1);
session.setAttribute("name", "test");
return "set session";
}
/*
* 浏览器发送请求的时候session
* */
@RequestMapping(path = "/session/get", method = RequestMethod.GET)
@ResponseBody
public String getSession(HttpSession session) {
session.getAttribute("id");
session.getAttribute("name");
return "get session";
}
- 缺点
占用服务器的内存.
2.3 扩展:实际生产环境中为何不直接采用sesson?
原因:现实生活中多采用分布式集群架构,中间利用njx保证负载均衡;若服务器A为此请求生成了session,下一次请求时,因njx可能会请求到另一台服务器上,重新生成Cookie,占用大量内存。
优化:设置分配策略
- 利用黏性session: 记住上次访问主机的IP地址,下一次同一请求,还来请求这台服务器;【缺点:无法保证负载均衡】
- 利用同步session: 每生成一个session,在服务器集群中同步该session;【缺点:1. 同步对服务器产生性能影响;2. 服务器之间产生耦合,对部署不利。】
- 利用共享session: 专门设置一台服务器,用于存放session;【缺点:单机存在性能瓶颈,一旦宕机,则无法使用】
- 利用数据库[推荐使用]:大部分存在浏览器中,敏感数据直接放在mysql数据库集群中;【缺点:数据存放在硬件中,性能低】==> 优化:利用Redis数据库存放
3. Cookie和Session的比较
3.1 两者的形象比喻
- Cookie机制通过检查客户身上的通行证来确定客户身份;
- Session机制通过检查服务器上的客户明细表确认客户身份。
3.2 两者区别
- Cookie数据存放在客户的浏览器上;Session数据存放在服务器上;
- Session相对于Cookie更加安全;
- 如果考虑减轻服务器的负担,应当使用Cookie。