无状态就是不保存状态,HTTP就是无状态协议,HTTP协议自身不会对请求和响应之间的通信状态进行保存,也就是说,在HTTP协议这个级别,协议对于发送过的请求或者响应都不做持久化处理。
cookie是在客户端保留少量数据的技术,主要通过响应头向客户端响应一些客户端要保留的信息
session是在服务器端保留更多的数据的技术,主要通过HttpSession对象保存一些和客户端相关的信息
cookie和session配合记录请求状态
cookie是一种客户端会话技术,cookie由服务器产生,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器里去
- 服务器创建cookie,将cookie放入响应对象中,Tomcat容器将cookie转化为set-cookie响应头,响应给客户端
- 客户端在收到cookie的响应头时,在下次请求该服务的资源时,会以cookie请求头的形式携带之前收到的Cookie
- cookie是一种键值对格式的数据
- 由于cookie是存储于客户端的数据,比较容易暴露,一般不存储一些敏感或者影响安全的数据
创建cookie对象:Cookie cookie1 =new Cookie("key","value");
将cookie对象放入响应对象:resp.addCookie(cookie1)
获取请求对象中的cookie对象:Cookie[] cookies = req.getCookies();
setMaxAge():见下文
setPath(String path):见下文
默认情况下Cookie的有效期是一次会话范围内,我们可以通过cookie的setMaxAge()方法让Cookie持久化保存到浏览器上
- 服务器端并没有明确指定Cookie的存在时间
- 在浏览器端,Cookie数据存在于内存中
- 只要浏览器还开着,Cookie数据就一直都在
- 浏览器关闭,内存中的Cookie数据就会被释放
- 服务器端明确设置了Cookie的存在时间
- 在浏览器端,Cookie数据会被保存到硬盘上
- Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
- 持久化Cookie到达了预设的时间会被释放
cookie.setMaxAge(int expiry)参数单位是秒,表示cookie的持久化时间,如果设置参数为0,表示将浏览器中保存的该cookie删除
访问互联网资源时不能每次都需要把所有Cookie带上。访问不同的资源时,可以携带不同的cookie,我们可以通过cookie的setPath(String path) 对cookie的路径进行设置
例:
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 =new Cookie("c1","c1_message");
// 设置cookie的提交路径
cookie1.setPath("/web03_war_exploded/servletB");
Cookie cookie2 =new Cookie("c2","c2_message");
// 将cookie放入响应对象
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
}
cookie1在设置完提交路径"/web03_war_exploded/servletB"后,只有在访问"/web03_war_exploded/servletB"时,cookie1才会被携带到请求头中
HttpSession是一种保留更多信息在服务端的一种技术,服务器会为每一个客户端开辟一块内存空间,即Session对象。客户端在发送请求时,都可以使用自己的Session。这样服务端就可以通过Session来记录某个客户端的状态了
- 服务端在为客户端创建session时,会同时将session对象的id,即JSESSIONID以cookie的形式放入响应对象
- 后端创建完session后,客户端会收到一个特殊的cookie,叫做JSESSIONID
- 客户端下一次请求时携带JSESSIONID,后端收到后,根据JSESSIONID找到对应的session对象
- 通过该机制,服务端通过session就可以存储一些专门针对某个客户端的信息
- session也是域对象
获取session对象:HttpSession session = req.getSession(); 获取Session的ID:String jSessionId = session.getId(); 判断session是不是新创建的session:boolean isNew = session.isNew(); 向session对象中存入数据:session.setAttribute("key",value);
获得session对象中数据(根据key值):session.getAttribute(”key”);
用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。
客户端关闭行为无法被服务端直接侦测,或者客户端较长时间不操作也经常出现,类似这些的情况,就需要对session的时限进行设置了
Session的默认时效是在未使用的情况下,三十分钟自动清除
也可以通过HttpSession的API 对最大闲置时间进行设定:
// 设置最大闲置时间
session.setMaxInactiveInterval(60);
也可以直接让session失效
// 直接让session失效
session.invalidate();
域对象是一些用于存储数据和传递数据的对象,传递数据不同的范围,称之为不同的域,不同的域对象代表不同的域,共享的数据的范围也不同。
- 请求域对象是HttpServletRequest ,传递数据的范围是一次请求之内及请求转发
- 会话域对象是HttpSession,传递数据的范围是一次会话之内,可以跨多个请求
- 应用域对象是ServletContext,传递数据的范围是本应用之内,可以跨多个会话
API | 功能 |
---|---|
void setAttribute(String key,Object value) | 向域对象中添加/修改数据 |
Object getAttribute(String key); | 从域对象中获取数据 |
removeAttribute(String key); | 移除域对象中的数据 |
- 请求转发时,请求域可以传递数据请求域内一般放本次请求业务有关的数据,如:查询到的所有的部门信息
- 同一个会话内,不用请求转发,会话域可以传递数据会话域内一般放本次会话的客户端有关的数据,如:当前客户端登录的用户
- 同一个APP内,不同的客户端,应用域可以传递数据应用域内一般放本程序应用有关的数据 如:Spring框架的IOC容器