Spring Session 学习记录1
先写些废话
新公司项目是有用到redis,之前老公司使用的缓存框架是ehcache.我redis并不熟悉.看过介绍以后知道是个nosql..既然是个数据库,那我想操作方法和jdbc操作关系数据库应该差不多吧..百度了一些例子以后发现确实差不多...比如注入一个spring的template以后使用template就行了. 比如:

很好理解,使用也蛮简单..就像jdbcTemplate...
一次偶然的调试,我发现了一个有趣的地方(公司用的是自己的框架,封装了springboot...所以启动默认配置了什么bean,很难看出来...)...

我记得session在tomcat启动服务器的时候好像是XXXSessionFacade..这里却是和Redis相关的一个实现类..然后向这个session存进去的东西再redis里也可以找到.
这说明这个session数据存取都是向redis去操作的.
看来一下maven的POM文件发现公司的项目依赖于srping-session-data-redis这个框架.
Spring整合SpringSession
实验了一下,发现其实spring只要额外配置2个bean就可以集成springsession了.
<context:annotation-config />
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
</bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="10.86.87.173" />
<property name="password" value="mesRedis+)" />
</bean>
稍微研究了下发现JedisConnectionFactory这个bean就是配置了Spring怎么通过jedis去连接redis服务器.
RedisHttpSessionConfiguration这个bean是真正和session相关的,它本身类上有注解@Configuration和@EnableScheduling.
@Configuration配合它方法上的@Bean可以配置一些其他的bean,比如SessionRepositoryFilter 就配置了一个bean,对应web.xmlXML里配置的那个filter...
@EnableScheduling这个注解我没用过,估计是要定时做一些事情,比如session过期了要去redis删除数据吧(但是redis好像也有超时删除数据的功能,为啥还要这么做呢..redis和Springsession都是第一次用,不太了解)..
除了上面2个bean,只要在web.xml里配置一个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>
原理
因为第一次用,很多代码都没看过,所以不一定对.我觉得原理是这样的:
1.RedisHttpSessionConfiguration里会配置一个filter
@Bean
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository, ServletContext servletContext) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository);
sessionRepositoryFilter.setServletContext(servletContext);
if(httpSessionStrategy != null) {
sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy);
}
return sessionRepositoryFilter;
}
注入一个sessionRepository.这个repository其实就是redis的repository.只是哪里生成的我并不知道...
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response, servletContext);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response);
HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse);
HttpServletResponse strategyResponse = httpSessionStrategy.wrapResponse(wrappedRequest, wrappedResponse);
try {
filterChain.doFilter(strategyRequest, strategyResponse);
} finally {
wrappedRequest.commitSession();
}
}
这个filter会把request和response外面包装一层,就是装饰着模式.当调用request的getSession的时候
@Override
public HttpSession getSession(boolean create) {
HttpSessionWrapper currentSession = getCurrentSession();
if(currentSession != null) {
return currentSession;
}
String requestedSessionId = getRequestedSessionId();
if(requestedSessionId != null) {
S session = sessionRepository.getSession(requestedSessionId);
if(session != null) {
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(session, getServletContext());
currentSession.setNew(false);
setCurrentSession(currentSession);
return currentSession;
}
}
if(!create) {
return null;
}
S session = sessionRepository.createSession();
currentSession = new HttpSessionWrapper(session, getServletContext());
setCurrentSession(currentSession);
return currentSession;
}
其实是从sessionRepository里去拿session的.所以我们使用的HttpSession的实现类应该是 HttpSessionWrapper 里面包裹着 RedisSession.
private RedisSession getSession(String id, boolean allowExpired) {
Map<Object, Object> entries = getSessionBoundHashOperations(id).entries();
if(entries.isEmpty()) {
return null;
}
MapSession loaded = new MapSession();
loaded.setId(id);
for(Map.Entry<Object,Object> entry : entries.entrySet()) {
String key = (String) entry.getKey();
if(CREATION_TIME_ATTR.equals(key)) {
loaded.setCreationTime((Long) entry.getValue());
} else if(MAX_INACTIVE_ATTR.equals(key)) {
loaded.setMaxInactiveIntervalInSeconds((Integer) entry.getValue());
} else if(LAST_ACCESSED_ATTR.equals(key)) {
loaded.setLastAccessedTime((Long) entry.getValue());
} else if(key.startsWith(SESSION_ATTR_PREFIX)) {
loaded.setAttribute(key.substring(SESSION_ATTR_PREFIX.length()), entry.getValue());
}
}
if(!allowExpired && loaded.isExpired()) {
return null;
}
RedisSession result = new RedisSession(loaded);
result.originalLastAccessTime = loaded.getLastAccessedTime() + TimeUnit.SECONDS.toMillis(loaded.getMaxInactiveIntervalInSeconds());
result.setLastAccessedTime(System.currentTimeMillis());
return result;
}
@Override
public HttpSession getSession(boolean create) {
HttpSessionWrapper currentSession = getCurrentSession();
if(currentSession != null) {
return currentSession;
}
String requestedSessionId = getRequestedSessionId();
if(requestedSessionId != null) {
S session = sessionRepository.getSession(requestedSessionId);
if(session != null) {
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(session, getServletContext());
currentSession.setNew(false);
setCurrentSession(currentSession);
return currentSession;
}
}
if(!create) {
return null;
}
S session = sessionRepository.createSession();
currentSession = new HttpSessionWrapper(session, getServletContext());
setCurrentSession(currentSession);
return currentSession;
}

Spring Session 学习记录1的更多相关文章
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题
Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...
- Spring Boot学习记录(二)–thymeleaf模板
自从来公司后都没用过jsp当界面渲染了,因为前后端分离不是很好,反而模板引擎用的比较多,thymeleaf最大的优势后缀为html,就是只需要浏览器就可以展现页面了,还有就是thymeleaf可以很好 ...
- spring aop学习记录
许多AOP框架,比较常用的是Spring AOP 与AspectJ.这里主要学习的Spring AOP. 关于AOP 日志.事务.安全验证这些通用的.散步在系统各处的需要在实现业务逻辑时关注的事情称为 ...
- AOP和spring AOP学习记录
AOP基本概念的理解 面向切面AOP主要是在编译期或运行时,对程序进行织入,实现代理, 对原代码毫无侵入性,不破坏主要业务逻辑,减少程序的耦合度. 主要应用范围: 日志记录,性能统计,安全控制,事务处 ...
- 我的Spring Boot学习记录(一):自动配置的大致调用过程
1. 背景 Spring Boot通过包管理工具引入starter包就可以轻松使用,省去了配置的繁琐工作,这里简要的通过个人的理解说下Spring Boot启动过程中如何去自动加载配置. 本文中使用的 ...
- 2019-04-05 Spring Boot学习记录
1. 使用步骤 ① 在pom.xml 增加父级依赖(spring-boot-starter-parent) ② 增加项目起步依赖,如spring-boot-starter-web ③ 配置JDK版本插 ...
- Spring Security 学习记录
一.核心拦截器详细说明 1.WebAsyncManagerIntegrationFilter 根据请求封装获取WebAsyncManager 从WebAsyncManager获取/注册Security ...
- 【转载】Spring boot学习记录(二)-配置文件解析
前言:本系列文章非本人原创,转自:http://tengj.top/2017/04/24/springboot0/ 正文 Spring Boot使用了一个全局的配置文件application.prop ...
随机推荐
- linux自学(七)之开始ccentos学习,安装jdk
上一篇:linux自学(六)之开始centos学习,更换yum源 如果你认真跟着前面操作那么一定都完成相关配置及下载,我们的目的是部署Javaweb项目,需要jdk,mysql,tomcat.那么接下 ...
- BZOJ3083 遥远的国度 【树链剖分】
BZOJ3083 遥远的国度 Description zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcw ...
- iOS保存数据的4种方式
在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyed ...
- php7+Redis+Windows7安装 (phpstudy)
1.首先去github网站上下载https://github.com/dmajkic/redis/downloads: 2.根据实际情况,将64bit的内容cp到自定义盘符目录,如D:\Redis; ...
- WPF自定义组件,自定义属性(依赖属性)
正常定义的以来属性,在XAML里设置值得时候是不触发Setter的,只能在code中用. 监听PropertyChangedCallback事件可以感知XAML里的设置,这样才能code和XAML配合 ...
- nginx 获取请求头,URL参数
获取url参数 在 ngx_lua 中访问 Nginx 内置变量 ngx.var.arg_PARAMETER 即可获得GET参数PARAMETER的内容. 在 nginx配置中,通过$arg_PARA ...
- drill 数据库查询方式简单说明
1. mysql select * from mysql-storage.mysqldb.mysqltable 2. oracle select * from oracle-storag ...
- 使用ILMerge将源DLL合并到目标EXE(.NET4.6.2)
本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 本文主要是使用微软的ILMerge工具将源DLL合并到目标EXE,因此,需要下载以下工具: https://www.micro ...
- MySQL 8 连接时出现 1251 和 2059 错误
MySQL 8 连接时出现 1251 和 2059 错误 原因是MySQL 8 改了密码加密算法.1 原来是:mysql_native_password MySQL8 改成了 caching_sha2 ...
- (转)完美解决 Android WebView 文本框获取焦点后自动放大有关问题
完美解决 Android WebView 文本框获取焦点后自动放大问题 前几天在写一个项目时,要求在项目中嵌入一个WebView 本来很快就完成了,测试也没有问题.但发给新加坡时,他们测试都会出现文本 ...