一直对session的各种理论不是特别清晰,所以有时间自己做个试验来验证一下。
准备:
windows环境电脑一台
nginx 负载和反向代理
2个tomcat 处理用户请求,其中一个tomcat端口号所有的8都让我改成9了。
证明如果浏览器页面不关,不会生成新的session
代码如下
在servlet的doGet方法里
HttpSession session = request.getSession();
sessionId = session.getId();
PrintWriter out = response.getWriter();
out.print("<html><body>");
out.print(sessionId);
out.print("</body></html>");
out.flush();
out.close();
nginx配置如下:
upstream localhost {
server 127.0.0.1:8080 ;
server 127.0.0.1:9090 ;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
我要的预期结果:无论我怎么刷新,页面上都显示一个sessionId
运行:
首先,我们只开一台tomcat,无论我怎么刷新,页面上的sessionid都是不变的。
因为tomcat容器管理了session,当发现cookie里有session,并且根据该sessionid也能取到session对象的时候,就不创建新的session。
这就是request.getSession()这句代码的基本实现原理。
接下来,再开一台tomcat,就是9090那台,刷新,发现sessionid一直在变。
原因其实很简单,因为虽然浏览器访问的时候cookie中带了sessionid,可是集群中的另一台tomcat根据该sessionid找不到session对象,
所以又重新创建了session。
好,修改一下代码
System.out.println("running......");
String sessionId = "";
if(request.getCookies()==null){
HttpSession session = request.getSession();
sessionId = session.getId();
}else{
Cookie c = request.getCookies()[0];
if(c.getName().equalsIgnoreCase("JSESSIONID"))
{
sessionId = c.getValue();
}
}
PrintWriter out = response.getWriter();
out.print("<html><body>");
out.print(sessionId);
out.print("</body></html>");
out.flush();
out.close();
运行发现sessionId就不变了。
其他方法,比如把session存数据库,存缓存,思路都是一样。
本例中不可以禁用cookie。当然禁用了也不怕,改一下程序,重写url让url中带上sessionid也可以,简单说一下思路,不写了。
其他内容:
1 session的生命周期问题,session何时生,何时死呢?
session并不会在关闭浏览器时死,而是过期才死,或者主动invalidate才死。
request.getSession(true)时生,对于jsp,由于session是内建对象,即使不调用,也会生。
2 为什么关了浏览器,重新打开输入刚才那个网址,重新生成了session呢?
因为关闭浏览器时,摧毁了cookie。只要在代码中设置了cookie的失效时间,就可以实现关了浏览器,再打开,还是刚才的session。
3 服务器怎么知道那个session应该给那个用户使用呢?
根据cookie中带的那个sessionid
这些基本概念都是单服务器情况下,如果不牢牢掌握,在集群环境下会更晕,session和cookie其实是非常深奥的话题。