一、基础认知
cookie英文意思是甜点的意思,我们可以在Web应用程序中可以使用cookie在客户端保持HTTP状态信息。cookie相当于是web服务器送给客户端浏览器的甜点。至于什么时候送,送什么样的甜点,有效期是多长时间,完全由服务器来决定。这就像我们刚入学的时候,班主任就会给你办一张听课证,听课证上面有你的相关的信息,以后每次到学校来都要戴着听课证。听课证就是学校送给你的cookie。
刚才我们把cookie比喻成听课证,那么session就是你的学生档案,这个档案是存放在学校的。session是一种将会话保存在服务器端的技术,用来跟踪用户。session通常借助cookie来传递会话标识号。
客户端与服务器进行通信依靠HTTP协议,而HTTP协议是一种无状态的协议,服务器无需关心客户端是谁,每次都需要检查客户端的身份,这时就需要借助cookie来进行验证客户端的身份。
二、会话追踪
Servlet API 规范中定义了一个Httpsession接口,该接口中定义了各种管理和操作会话状态的方法。一个Httpsession对象就相当于档案袋,它是保持会话状态信息的存储结构。一个客户端在web服务器对应一个各自的HttpSession对象。
只有客户端访问某个特殊的Servlet程序,并且这个Servlet程序决定与客户端开启一个会话时, web应用程序才会创建一个与客户端对应的HttpSession对象,并为这个HttpSession对象分配一个独一无二的会话标识号(SessionID).然后在响应消息中将这个会话标识号传递给客户端。客户端需要记住这个SessionID,并在后续的每次访问请求中把这个SessionID传递给服务器,服务器程序依据回传的SessionID就知道这次请求是那个客户端发送的,从而选择与之对应的HttpSession对象。
服务器识别 Session 的关键就是依靠一个名为 JSESSIONID 的 Cookie 。在Servlet 中第一次调用 req.getSession() 时, Servlet 容器自动创建一个 Session ID ,然后通过一个名为 JSESSIONID的Cookie 发送给浏览器:
web应用程序创建了与某个客户端对应的HttpSession对象之后,只要没有超出一个限定的空闲时间段,HttpSession对象就驻留在web服务器内存之中。HttpSession接口中定义了一个setAttribute方法将对象存储到HttpSession对象中,相当于往档案袋中放入档案信息。还定义了一个getAttribute来取得放进去的对象。
三、代码实现
获取会话
通过调用HttpServletRequest的getSession()方法获取HttpSession会话
HttpSession session = req.getSession();
获取Session唯一标识符:session.getId()
Session创建时间: session.getCreationTime()
Session最后访问:session.getLastAccessedTime()
实现代码:
@WebServlet("/session_demo.do")
public class SessionDemoServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取会话
HttpSession session = req.getSession();
System.out.println("Session ID:" + session.getId());
System.out.println("Session创建时间:" + new Date(session.getCreationTime()));
System.out.println("Session最后访问:" + new Date(session.getLastAccessedTime()));
}
}
运行结果:
Session测试
产生“幸运数字”,并存入当前会话
@WebServlet("/three.do")
public class ThreeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过本次请求request,获取当前会话HttpSession
HttpSession session = req.getSession();
System.out.println("本次会话:" + session.getId());
// 产生“幸运数字”,并存入当前会话
int luckyNumber = (int)(Math.random() * 100);
System.out.println("本次的幸运数字:" + luckyNumber);
session.setAttribute(session.getId(),luckyNumber);
System.out.println();
}
}
获取在会话中保存的“幸运数字”,并响应输出
@WebServlet("/testSession.do")
public class TestSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取本次会话
HttpSession session = req.getSession();
System.out.println("本次会话:" + session.getId());
// 获取在会话中保存的“幸运数字”
String result = String.valueOf(session.getAttribute(session.getId()));
// 响应输出
PrintWriter writer = resp.getWriter();
writer.write(result);
writer.flush();
}
}
只要在同一个会话,一个会话存入的值在另一个会话中可以访问到存入的值
同一个会话可以是两个不同的Servlet,只要访问的服务器、ip地址一样就OK
四、Session与Cookie的区别
测试Session
第一次在访问Session时,服务器会创建Session
并根据Session_ID,创建一个名称为"JSESSIONID"的Cookie,将Session_ID保存到该Cookie
将该Cookie响应至浏览器客户端保存
接下来的每次发起请求,客户端浏览器都会在请求头中添加JSESSIONID
用于服务器确认“身份”
@WebServlet("/test_session.do")
public class TestSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("GET请求:TestSessionServlet被请求到了!");
HttpSession session = req.getSession();
System.out.println(session.getId());
}
}
测试Cookie
@WebServlet("/test_cookie.do")
public class TestCookieServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("cokiiiiiiiiiiiiiie");
// 创建Cookie对象
Cookie cookie1 = new Cookie("phone_number","13527605421");
cookie1.setMaxAge(60*60*24*7); // 设置过期时间
Cookie cookie2 = new Cookie("user_name","user");
Cookie cookie3 = new Cookie("user_password","mhtk7605421");
// 响应
resp.addCookie(cookie1); // 将Cookie添加至响应头
resp.addCookie(cookie2);
resp.addCookie(cookie3);
}
}
测试获取Cookie
@WebServlet("/test_cookie_value.do")
public class TestCookieValueServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("测试获取Cookie");
// 获取该客户端浏览器本次请求头(request header)中所有的Cookie
Cookie[] cookieArray = req.getCookies();
if(cookieArray != null) {
for(Cookie ck : cookieArray) {
System.out.println(ck.getName());
System.out.println(ck.getValue());
System.out.println();
}
}
}
}
总结:
我们把这种基于唯一ID识别用户身份的机制称为 Session 。每个用户第一次访问服务器后,会自动获得 一个 Session ID 。如果用户在一段时间内没有访问服务器,那么 Session 会自动失效,下次即使带着上次分配的 Session ID 访问,服务器也认为这是一个新用户,会分配新的 Session ID 。一次 Session 会话中往往包含着若干次 request 请求。
使用 Session 时,由于服务器把所有用户的 Session 都存储在内存中,如果遇到内存不足的情况,就需要把部分不活动的 Session 序列化到磁盘上,这会大大降低服务器的运行效率,因此,放入 Session 的数据不能太大,否则会影响服务器的运行。
通过读写 Cookie 可以在客户端存储数据。
以上就是对于Session会话追踪的实现机制的分享,如有不当之处还请大家多多评论指正,喜欢文章的可以留下您的关注和点赞,一起学习,一起加油!