XML配置spring session jdbc实现session共享
概述
session的基础知识就不再多说。
通常,我们会把一个项目部署到多个tomcat上,通过nginx进行负载均衡,提高系统的并发性。此时,就会存在一个问题。假如用户第一次访问tomcat1,并登陆保存了用户信息,但是下一次访问的时候,nginx让用户访问tomcat2,此时tomcat2中并没有用户的session信息,用户必须重新进行登录操作。这样会极大的破坏用户的体验。
对此,我们有两大类解决方案。一个是将nginx的负载均衡机制设为根据iphash,也就是用户每次保证能访问同一台tomcat,但是该方法也存在着弊端,当tomcat挂掉以后,用户必须重新登陆。第二种方法较为常用,就是通过某些方法进行session共享。常用的方法有使用spring session,如果项目中有用到shiro,可以通过重写AbstractSessionDAO,即重写shiro的session存储机制完成。
本文将先从spring session入手,完成session共享。由于最近接触的是一个老项目,使用ssm框架,本文基于xml的方式进行配置。熟悉spring boot的朋友可以直接到spring boot官网进行查看,配置较为简单。由于老项目的并发量并不是很高,因此本文使用spirng-session-jdbc来进行session共享。大型项目可选择使用非关系型数据库Redis等
代码地址
https://github.com/DenchZhou/ssm/tree/master/spring-session-jdbc
如果有用的话不妨给个star,感恩!
配置
Maven依赖
加入maven依赖 以下使用的是2.0以上的版本 如果在没有网的环境下记得添加其他相关依赖如spring-jdbc、spring-session-core、spring-context
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
数据库表
我们需要添加两张数据库表,spring session通过将httpsession序列化保存至数据库,需要session的时候再从数据库中取出并反序列化。因此我们需要保证数据库中存在保存session的表格。
/* 2.x版本使用的数据库表*/
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
上面的数据库表适用于2.0以上的版本,总共有七个字段。如果maven依赖1.x版本使用的数据库表不一样。
/* 1.x版本使用的数据库表*/
CREATE TABLE `SPRING_SESSION` (
`SESSION_ID` char(36) NOT NULL DEFAULT '',
`CREATION_TIME` bigint(20) NOT NULL,
`LAST_ACCESS_TIME` bigint(20) NOT NULL,
`MAX_INACTIVE_INTERVAL` int(11) NOT NULL,
`PRINCIPAL_NAME` varchar(100) DEFAULT NULL,
PRIMARY KEY (`SESSION_ID`) USING BTREE,
KEY `SPRING_SESSION_IX1` (`LAST_ACCESS_TIME`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `SPRING_SESSION_ATTRIBUTES` (
`SESSION_ID` char(36) NOT NULL DEFAULT '',
`ATTRIBUTE_NAME` varchar(100) NOT NULL DEFAULT '',
`ATTRIBUTE_BYTES` blob,
PRIMARY KEY (`SESSION_ID`,`ATTRIBUTE_NAME`),
KEY `SPRING_SESSION_ATTRIBUTES_IX1` (`SESSION_ID`) USING BTREE,
CONSTRAINT `SPRING_SESSION_ATTRIBUTES_ibfk_1` FOREIGN KEY (`SESSION_ID`) REFERENCES `SPRING_SESSION` (`SESSION_ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
spring xml相关配置
<context:annotation-config/>
<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration">
<property name="tableName" value="spring_session"/>
<property name="maxInactiveIntervalInSeconds" value="1800"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
使用context:annotation-config和JdbcHttpSessionConfiguration是因为Spring Session没有提供XML命名空间的支持。我们可以在配置相关的属性注入,如数据库表名,session保持的时间等等。然后就是事务管理器的配置,数据源的配置不再详细说明了。可以看最上面的项目源码。
web.xml配置过滤器
spring session通过自定义一个filter,通过filter职责链将用自己定义的request替换httpservletrequest,从而使用自己httpsession。因此我们必须配置一下Filter,并且最好把他放在最前面,使其优先执行。
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
spring 配置读取我们的spring配置文件。
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<!-- 默认匹配所有的请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
测试
我的项目中只写了一个简单的查找user并放入session中
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findUser")
@ResponseBody
public String findUserById(HttpServletRequest request){
UserEntity user = userService.findUserById(1);
HttpSession session = request.getSession();
session.setAttribute("user", user);
return user.toString();
}
}
可以通过数据库管理工具查看


参考
官方文档 https://docs.spring.io/spring-session/docs/current/reference/html5/#introduction
踩坑
有朋友问我SpringSessionJdbc配置HttpSessionListener不生效,查了一下官方文档。

想要实现HttpSession的监听需要三个步骤,在第一步中
- SessionRepository需要实现支持并配置触发SessionDestroyedEvent和SessionCreatedEvent,在SpringSessionJdbc的JdbcOperationsSessionRepository中并未配置相关Event,实现的接口也没有包含该Event,所以SpringSessionJdbc并没有这个功能。而SpringSessionRedis有这个功能。


官方解释,使用JdbcOperationsSessionReopsitory并不支持事件机制
XML配置spring session jdbc实现session共享的更多相关文章
- applicationContext.xml配置Spring样板
<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://ww ...
- 基于XML配置Spring的自动装配
一.了解Spring自动装配的方式 采用传统的XML方式配置Bean组件的关键代码如下所示 <bean id="userMapper" class="edu.cn. ...
- Spring的JDBC的使用(配置和CRUD)
导包: Spring的JDBC模板的使用 一.默认连接池 创建数据库 create database spring4; use spring4; create table account(id int ...
- Spring的jdbc模板1
Spring是EE开发的一站式框架,有EE开发的每一层解决方案.Spring对持久层也提供了解决方案:ORM模块和jdbc模块,ORM模块在整合其他框架的时候使用 Spring提供了很多的模板用于简化 ...
- 十八 Spring的JDBC模板:引入外部属性文件
配置外部属性文件 配置文件里引入属性文件,两种方式 第一种: 第二种: 引入属性文件的值: 测试: <?xml version="1.0" encoding="UT ...
- 十六 Spring的JDBC模版入门,默认连接池
Spring是EE开发一站式框架,有EE开发的每层的解决方案,Spring对持久层也提供了解决方案:ORM模块和JDBC的模版
- Spring框架——JDBC与事务管理
JDBC JDBCTemplate简介 XML配置JDBCTemplate 简化JDBC模板查询 事务管理 事务简介 Spring中的事务管理器 Spring中的事务管理器的不同实现 用事务通知声明式 ...
- 更加优雅地配置Spring Securiy(使用Java配置和注解)
Spring Security 借助一系列Servlet Filter 来提供安全性功能,但是借助Spring的小技巧,我们只需要配置一个Filer就可以了,DelegatingFilterProxy ...
- SpringInAction--XML配置Spring Aop
前面学习了如何用注解的方式去配置Spring aop,今天把XML配置的方法也看了下,下面顺便也做了个记录 先把spring中用xml配置aop的配置元素给贴出来: <aop:advisor&g ...
随机推荐
- linux 命令基础大全
pwd:显示当前路径 cd :切换目录 用法:cd cd ../ 切换到上级目录 cd / 切换到根目录 cd ~ (或只有cd )切换到当前用户主目录(home底下以用户名命名的文件夹) /r ...
- 【spring源码分析】IOC容器初始化(九)
前言:上篇文章末尾提到createBeanInstance方法中使用工厂方法实例化Bean对象,本文将对该方法进行分析. AbstractAutowireCapableBeanFactory#inst ...
- php之微信公众号发送模板消息参观模仿
上篇文章中鞋到了公众号发送末班消息,他是最后调用两个方法,本文章简化一下 将下面的php方法放到一个可以引入的公共类中即可 构建模板消息: 我把需要用到的模板消息 都写成一个个方法,放在公共类文件中了 ...
- 试试Linux下的ip命令,ifconfig已经过时了
linux的ip命令和ifconfig类似,但前者功能更强大,并旨在取代后者.使用ip命令,只需一个命令,你就能很轻松地执行一些网络管理任务.ifconfig是net-tools中已被废弃使用的一个命 ...
- EXCEL记录
ー.重要快捷键 Ctrl + F → 查找 Ctrl + H → 替换 Ctrl + G → 定位 Ctrl + 1 → 设置单元格格式 Ctrl + Enter → 一并输入多个单元格 Ctrl + ...
- Mysql 中的日期时间字符串查询
一.将数据库中的Date格式的数据,或者指定日期的字符串格式化为想要的样式 DATE_FORMAT (date, format)能根据格式串format 格式化日期或日期和时间值date,返回结果字符 ...
- this.$router.push、replace、go的区别
1.this.$router.push() 描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面. 用法: 2.this.$router.replace() ...
- DAY23、面向对象特性
一.复习1.类: 对象属性的查找顺序:先找自身再找类 类的名称空间:直接写在类中 对象的名称空间:写在__init__方法中,通过self.属性形成名称空间中的名字 类的方法:在类中用@classme ...
- servlet(6) 链接数据库
一.servlet链接mysql步骤: 1.注册驱动器:Class.forName("com.mysql.jdbc.Driver"); 加载类并执行下面的静态语句块,将Driver ...
- python 三元运算符、推导式、递归、匿名函数、内置函数
三目运算符 # 三目(元)运算符:就是 if...else...语法糖 # 前提:简化if...else...结构,且两个分支有且只有一条语句 # 注:三元运算符的结果不一定要与条件直接性关系 cmd ...