spring session源码解析
2024-09-01 16:59:11
模块划分
core部分代码
存储实现部分部分:
jdbc实现
具体存储的实现类
例如:org.springframework.session.jdbc.JdbcOperationsSessionRepository
支持jdbc访问的都可以作为存储介质
JdbcOperationsSessionRepository通过sql来访问后端存储:
private static final String CREATE_SESSION_QUERY = "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) VALUES (?, ?, ?, ?, ?, ?, ?)";
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) SELECT PRIMARY_ID, ?, ? FROM %TABLE_NAME% WHERE SESSION_ID = ?";
private static final String GET_SESSION_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES FROM %TABLE_NAME% S LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID WHERE S.SESSION_ID = ?";
private static final String UPDATE_SESSION_QUERY = "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? WHERE PRIMARY_ID = ?";
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = "UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ?";
private static final String DELETE_SESSION_ATTRIBUTE_QUERY = "DELETE FROM %TABLE_NAME%_ATTRIBUTES WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ?";
private static final String DELETE_SESSION_QUERY = "DELETE FROM %TABLE_NAME% WHERE SESSION_ID = ?";
private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES FROM %TABLE_NAME% S LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID WHERE S.PRINCIPAL_NAME = ?";
private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% WHERE EXPIRY_TIME < ?";
核心流程
org.springframework.session.web.http.OncePerRequestFilter包装request和response对象
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryFilter.SessionRepositoryRequestWrapper(request, response, this.servletContext);
SessionRepositoryFilter.SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryFilter.SessionRepositoryResponseWrapper(wrappedRequest, response);
try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
} finally {
wrappedRequest.commitSession();
}
}
org.springframework.session.web.http.SessionRepositoryFilter核心流程:
- 获取session如果没有判断,是不是因为session无效,无效需要覆盖掉
-获取session如果有,则如果与当前sessionId不同,则需要回写
private void commitSession() {
SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper.HttpSessionWrapper wrappedSession = this.getCurrentSession();
if (wrappedSession == null) {
if (this.isInvalidateClientSession()) {
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
}
} else {
S session = wrappedSession.getSession();
this.clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.save(session);
String sessionId = session.getId();
if (!this.isRequestedSessionIdValid() || !sessionId.equals(this.getRequestedSessionId())) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
}
}
}
配置类:org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration
配置类:org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration
继承SpringHttpSessionConfiguration
总结:
通过此次源码阅读,更加理解了接口是面对不同场景或变化时,一种智慧的抽象.
参考
https://docs.spring.io/spring-session/docs/current/reference/html5/
最新文章
- [Evolutionary Algorithm] 进化算法简介
- php动态更改post_max_size, upload_max_filesize等值
- Eclipse 中 安装 SVN 插件
- p范数(p norm)
- 配置JDK时环境变量path和JAVA_HOME的作用是什么?
- [GIF] The Phase Property in GIF Loop Coder
- 如何修改linux系统主机名称
- C#程序中:如何启用进程、结束进程、查找进程
- sql点滴40—mysql乱码问题总结
- 一 : springmvc常用注解
- JavaScript的sleep实现--Javascript异步编程学习
- 【2019雅礼集训】【可持久化线段树】【模型转化】D1T2Permutation
- 配置javaJDK环境
- Codeforces Gym 101252D&;&;floyd判圈算法学习笔记
- 潭州课堂25班:Ph201805201 django 项目 第三十二课 后台站点管理(课堂笔记)
- 【转】.htaccess详解及.htaccess参数说明
- 关于typeid和typeof
- c日志宏
- TP5一对一、一对多关联模型的使用
- C#导出HTML到PDF组件 Pechkin
热门文章
- C#使用GUID作为随机数种子
- Android 调用 WebService
- 搭建docker+swoole+php7 的环境
- Rust入坑指南:坑主驾到
- 11g bug event &#39;cursor: mutex S&#39;-引发的CPU冲高问题
- 案例——TCP上传图片
- Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
- webshell检测方法归纳
- PHP7源码之array_unique函数分析
- 非阻塞IO模型