目录
状态和会话
状态:协议记住用户及其请求的能力
HTTP协议的无状态性
HTTP协议是无法记住用户和其请求的,表现为客户端第二次请求时不知道客户端的身份信息
客户A第一次请求登录,登录成功了;第二次请求加货物到购物车,因为HTTP协议是无状态的,不可以记录用户信息和追踪请求,导致服务器不知道当前请求的用户是谁,也就不知道加到谁的购物车里,无法做出响应
但是,按照设想,客户端是可以实现多次加货物到购物车的,并且服务器追踪所有请求,记录购物车的商品并计算总价;为了实现这一点,就需要追踪所有请求并和用户相关联
会话跟踪技术就成了对HTTP无状态协议的一种扩展
Cookie
Cookie和Session就是保持状态的记录,session底层依赖于cookie
cookie类似于你去坐火车,买票的时候有一个票据,记录了你的位置信息,比如(8号车厢20座位),根据这个位置你就可以知道自己的座位在哪,这个票据就是cookie
Cookie是服务器响应给客户端,并且存储在客户端的一份小数据。下次客户端访问服务器时,会自动带上这个Cookie。服务器通过Cookie就可以区分客户端
Cookie的API
对cookie的管理需要使用javax.servlet.http.Cookie类
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、创建cookie实例
//键值对的形式,name是键值对的key,”张三“是value
Cookie cookie = new Cookie("name", "张三");
//key固定了 value可以修改
//2、获取cookie名称
System.out.println(cookie.getName());
//3、获取cookie的值
System.out.println(cookie.getValue());
//4、给cookie设置新的值
cookie.setValue("李四");
//5、设置cookie的所在的域名
cookie.setDomain("127.0.0.1");
//6、返回cookie的域名
System.out.println(cookie.getDomain());
}
}
Cookie的管理,应该包括两个方面,服务器给客户端发送cookie,从客户端读取cookie
向客户端发送cookie
@WebServlet("/sendcookie")
public class SendCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、创建cookie对象
Cookie cookie = new Cookie("username", "张三");
//2、设置cookie的最大存活时间 这个cookie是存储在浏览器的内存中的,随着浏览器关闭,cookie就会消失
//如果想让cookie存储在磁盘上,就可以设置cookie的最大存活时间
//单位是s,如果参数为负数,表示不在硬盘存储,=0,表示删除这个cookie
cookie.setMaxAge(60*60);
//3、给客户端发送cookie对象
resp.addCookie(cookie);
resp.setContentType("text/html;charset=utf8");
PrintWriter out=resp.getWriter();
out.println("" +
"<html>"
+"<h3>"+"已经发送了cookie</h3>"
+"</html>"
);
}
}
执行之后,服务器将会在浏览器上写一个cookie文件
查看浏览器cookie
如果不设置持久化存储,cookie是保留在浏览器的内存的,随着浏览器的关闭,cookie就消失了,下一次用户就要重新登录
- 不设置MaxAge,默认响应会话Cookie(MaxAge<0),存在浏览器内存。Cookie随浏览器关闭而消失
- 设置MaxAge>0,响应持久性Cookie,会存在电脑硬盘的特定文件夹下(浏览器自定义的)
- 设置特定Cookie的MaxAge=0,则会删除已经存在客户端的此Cookie
从客户端读取cookie
@WebServlet("/readcookie")
public class ReadCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = "username";
String value = null;
Cookie[] cookies = req.getCookies();//得到请求的所有cookie对象
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().equals(name)) {
value = cookies[i].getValue();
break;
}
}
}
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("<html>" + "<h3>" + name + value + "</h3>" + "</html>");
}
}
Cookie的安全性问题
cookie是保留在客户端的,可以被人为删除,而且只要你的电脑被黑,数据就可能丢失
并且,cookie是有大小限制的。通常,一个浏览器只允许最多存放300个Cookie,每一个站点的Cookie最多20个,每一个Cookie的大小限制为4kb
Session
可能是出于cookie的安全性和cookie的大小限制,cookie每一次都要在请求中传输导致的速率等问题,提出了Session
Session,会话,是一个客户与服务器之间的不间断的请求响应序列。
session是存在于服务器的
如果使用cookie,那么可能账户,密码等信息直接保存在客户端,并且每次都要传输到客户端
使用Session,那么Cookie内不将会保存密码等重要信息,数据更加安全,而且Cookie内的数据也会减少,可以提高传输效率
sessionid通常是一个32位的16进制数字
SessionAPI
通过javax.servlet.http.HttpSession来管理会话
@WebServlet("/new")
public class SessionAPI extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、创建会话
// 使用HttpServletRequest的getSession()方法 创建和请求关联的会话,如果会话存在,直接返回会话,如果不存在,创建新的会话
HttpSession session = req.getSession();
System.out.println("SessionId" + session.getId());//返回SessionId
System.out.println("会话创建的时间" + session.getCreationTime());//会话创建的时间 时间从1970.1.1午夜到现在的毫秒数
System.out.println("新会话" + session.isNew());//如果这个会话没有和任何对象关联 返回true
session.setAttribute("name", "张三");//将一个键值对属性 写入session
// session.invalidate();//删除session
System.out.println(session.getAttribute("name"));//得到key对应的value值
session.setMaxInactiveInterval(10);//设置在会话失效之前,两个请求之间的最大间隔时间 单位s
Enumeration<String > names= session.getAttributeNames();//得到所有属性的name
while(names.hasMoreElements()) {
String name = names.nextElement();
System.out.println(name + session.getAttribute("name"));
}
session.removeAttribute("name");//删除某一属性
}
}
我们并没有说把这个SessionId打包到了Cookie里
resp.addCookie(cookie);这个语句我们并没有写,也就是Session会自己打包进入Cookie,那么这个Cookie就是一个会话Cookie,是在内存存储的
会话超时与失效
会话对象会占用一定的资源,因此会话是不需要长久保留的
HTTP协议没有提供任何机制让服务器知道用户已经离开了,但是规定当一个用户在指定时间内没有请求产生,就去终止会话,这称为会话超时
这个时间默认30分钟
可以在web.xml内修改
<session-conflg>
<session-time>
10
</session-time>
</session-conflg>
元素内指定以分钟为单位的默认超时时间,如果值<=0,表示永不会过期