先叙述一下 session 的实现原理吧!
session 服务器为每个客户端访问开辟的一块内存区域,可以存放一些客户端的一些操作信息
正常情况下在用户通过客户端访问服务器这个过程中 session 一直存活,直到客户端关闭,服务器中的 session 被销毁
非正常情况下,服务器调用 session.invalidate() 方法进行手动销毁
session 依赖于 cookie !!!
没有 cookie 是无法通过 request.getSession() 获取对应的客户端的 session 的
具体实现原理
客户端第一次访问服务器,服务器返回
在服务器返回的响应头中,可以看到 Set-Cookie 字段,这个字段中,JSESSION=94E09A118319882388C08A27A42696DB
94E09A118319882388C08A27A42696DB 为服务器保存的 session 对应的 ID
当客户端再访问该网站的其他链接 ?
服务器的响应头则不会再有 Set-Cookie 字段了?
但是再看客户端的请求头 ?
会自动的将 JSESSIONID 这个 Cookie 带上 ?,服务器根据该字段对应的值就可以拿到该客户端保存在服务器的 session 对象
此时可以通过 request.getSession() 获得对应的 session 对象
然而这都是基于客户端没有禁止 Cookie 的情况下,当客户端禁止了 Cookie ,当访问服务器的其他链接,将不会携带 Cookie 了,此时又该怎么办呢?(*^_^*)
解决办法之一:将 jsessionid 这个保存在客户端的值拼接在对应的 url 上,这样服务器可以通过解析 url 将 jsessionid 对应的值取出来,然后通过这个 sessionId 去获取保存在服务器中的 session 实例对象
通过 HttpServletResponse response,response.encodeURL() 方法进行将对应的 jsessionid 拼进去
现在说一下 response.encodeURL() 该函数的作用吧
首先判断客户端是否禁止了 Cookie ,如果没有禁止,则返回 request.getRequestURI() 这个的值不会拼接上 jsessionid
如果判断客户端禁止了 Cookie, 则会在 request.getContextPath()+"/hello/index" 后拼接上 jsessionid=xxx ?
当再访问服务器时,链接上拼上了 jsessionid 值 ?
客户端禁止了 Cookie ,所以请求头中 Cookie 值并没有带上 ?
然后就可以通过服务器解析对应的 url 获取 jsessionid 获取对应的 sessionId, 然后根据 sessionId 查询服务器对应的 session 实例对象 ?
基本的原理已经讲的差不多了,现在给出一个基于 SpringBoot 的一个解决方案,获取 session 的
MySessionContext 代码
package mr.s.javaee.context;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
public class MySessionContext {
private static MySessionContext instance;
private HashMap<String,HttpSession> sessionMap;
private MySessionContext() {
sessionMap = new HashMap<String,HttpSession>();
}
public static MySessionContext getInstance() {
if (instance == null) {
instance = new MySessionContext();
}
return instance;
}
public synchronized void addSession(HttpSession session) {
if (session != null) {
sessionMap.put(session.getId(), session);
}
}
public synchronized void delSession(HttpSession session) {
if (session != null) {
sessionMap.remove(session.getId());
}
}
public synchronized HttpSession getSession(String sessionID) {
if (sessionID == null) {
return null;
}
return sessionMap.get(sessionID);
}
}
SessionListener 代码
package mr.s.javaee.listener;
import mr.s.javaee.context.MySessionContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener {
private MySessionContext myc = MySessionContext.getInstance();
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
myc.addSession(session);
}
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
myc.delSession(session);
}
}
最后需要修改一下,启动类!加上 @ServletComponentScan 注解 ?
具体获得 session 的核心代码
String uri = request.getRequestURI();
String sessionId = uri.split("jsessionid=")[1];
System.out.println(sessionId);
MySessionContext myc= MySessionContext.getInstance();
HttpSession session = myc.getSession(sessionId);
String name = session.getAttribute("name").toString();