Session会话追踪的实现机制

前言

         HTTP协议是一个无状态协议,什么是无状态协议呢?  Web应用程序无法区分收到的不同的HTTP请求是否是同一个浏览器发出的。

        在Web应用程序中,Servlet和客户的通信采用“请求/响应”的模式。那服务器又是如何分别不同用户的呢?例如:当一个用户登录成功后,如果他继续访问其他页面,Web程序如何才能识别出该用户身份?   

        为了跟踪用户状态, Servlet容器提供了Session机制用以跟踪用户。服务器可以向浏览器分配一个唯一ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以识别用户身份。

什么是Session机制?

        Session相当于程序在服务器上建立的一份客户档案,当程序需要为某个客户端的请求创建一个Session时,服务器首先检查这个客户端的请求里是否包含了一个Session标识(即SessionId),如果已经包含一个sessionId则说明以前已经为此客户创建过Session,服务器就按照SessionId把这个Session检索出来使用。如果客户请求不包含sessionId,会自动获得一个Session ID。并本次响应中返回给客户端保存。

        我们把这种基于唯一ID识别用户身份的机制称为Session。如果用户在一段时间内没有访问服务器,那么Session会自动失效,下次即使带着上次分配的Session ID访问,服务器也认为这是一个新用户,会分配新的Session ID。一次Session会话中往往包含着若干次request请求。


        JavaEE的Servlet机制内建了对Session的支持。当我们需要获取Session时,可以通过request请求对象的getSession()方法。例如;

HttpSession session=request.getSession();



服务器识别Session的关键就是依靠一个名为JSESSIONID的Cookie。在Servlet中第一次调用request.getSession()时,Servlet容器自动创建一个Session ID,然后通过一个名为JSESSIONID的Cookie发送给浏览器:

例如运行如下代码:

@WebServlet("/text_session.do")
public class TextSessionServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("TextSessionServlet被GET到");
	
		// 第一次在访问Session时,服务器会创建Session
		// 并根据Session_ID,创建一个名称为"JSESSIONID"的Cookie,将Session_ID保存在Cookie
		// 将该Cookie响应回至浏览器保存
		// 接下来的每次发起请求时,客户端浏览器都会在请求中,添加JESSIONID
		// 用于服务器确认"身份"
		HttpSession session =req.getSession();
		System.out.println(session.getId());
	}
}

控制台结果:

 网页请求头所在第一次创建Session返回JSESSIONID:


Cookie

        实际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONID的Cookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。
        创建一个新Cookie时,除了指定名称和值以外,通常需要设置setPath("/"),浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath("/user/"),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie。通过setMaxAge()设置Cookie的有效期,单位为秒,最后通过resp.addCookie()把它添加到响应。
        通过创建Cookie,我们可以实现在客户端浏览器中存储数据的目的,例如保存用户名和密码。在Chrome浏览器中,单个 Cookie的长度不能超过 4069 个字符(包括 name,但不包括 = 号)。
我们可以在浏览器看到服务器发送的Cookie,以百度为例:

创建Cookie对象

@WebServlet("/text_cookie.do")
public class TextCookieServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//创建cookie对象
		Cookie cookie1=new Cookie("phone_number", "12323234545");
		Cookie cookie2=new Cookie("name", "xiaoming");
		Cookie cookie3=new Cookie("sex", "boy");
		Cookie cookie4=new Cookie("height", "188cm");
		cookie1.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
		cookie2.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
		cookie3.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
		cookie4.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
		
		//响应
		resp.addCookie(cookie1);//添加至响应头
		resp.addCookie(cookie2);//添加至响应头
		resp.addCookie(cookie3);//添加至响应头
		resp.addCookie(cookie4);//添加至响应头
	
	}
}

 

如果我们要读取Cookie,例如,在TextCookieServlet中,读取Cookie以获取用户设置的语言,可以写一个方法如下:

@WebServlet("/text_get_cookie.do")
public class TextGetCookieServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("测试获取cookie");
		Cookie[] cookies=req.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				System.out.println(cookie.getName());
				System.out.println(cookie.getValue());
				System.out.println();
			}
		}
	}
}

观察控制台: 

 

所以,读取Cookie主要依靠遍历HttpServletRequest附带的所有Cookie

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雾远望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值