如何使用Spring+redis实现对session的分布式管理
程序员文章站
2023-12-19 22:50:46
在spring中实现分布式 session管理
本文主要是在spring中实现分布式session,采用redis对session进行持久化管理,这样当应用部署的时候...
在spring中实现分布式 session管理
本文主要是在spring中实现分布式session,采用redis对session进行持久化管理,这样当应用部署的时候,不需要在resin、tomcat等容器里面进行分布式配置,方便加入新的节点服务器进行集群扩容,session不依赖各节点的服务器,可直接从redis获取。下面是功能的核心代码:
一、首先在web.xml里面配置
加入拦截器:
<!-- 分布式session start --> <filter> <filter-name>distributedsessionfilter</filter-name> <filter-class>distributedsessionfilter</filter-class> <init-param> <!-- 必填,密钥.2种方式,1对应为bean,格式为bean:key。2字符串,格式如:afffrfgv--> <param-name>key</param-name> <param-value>xxxxxxxx</param-value> </init-param> <init-param> <!-- 必填,redis对应的bean,格式为bean:xx--> <param-name>cachebean</param-name> <param-value>bean:redispersistent</param-value>//distributedbaseinterface,对应于此接口,进行session的持久化操作 </init-param> <init-param> <!-- 必填, --> <param-name>cookiename</param-name> <param-value>testsessionid</param-value> </init-param> </filter> <filter-mapping> <filter-name>distributedsessionfilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <!-- 分布式session end -->
二、拦截器的实现,核心代码如下
主要有以下的几个类:
- distributedsessionfilter,
- distributedsessionmanager,
- distributedhttpsessionwrapper,
- distributedhttpservletrequestwrapper
1、distributedsessionfilter实现filter:
import java.io.ioexception; import java.util.hashmap; import java.util.map; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.springframework.web.context.webapplicationcontext; import org.springframework.web.context.support.webapplicationcontextutils; public class distributedsessionfilter implements filter { private static final logger log = loggerfactory.getlogger(distributedsessionfilter.class); private string cookiename; //主要是对session进行管理的操作 private distributedsessionmanager distributedsessionmanager; private string key; }
容器启动时候的初始化方法:
@override public void init(filterconfig config) throws servletexception { webapplicationcontext wac = webapplicationcontextutils.getrequiredwebapplicationcontext(config .getservletcontext()); string key = config.getinitparameter("key"); string cookiename = config.getinitparameter("cookiename"); string cachebean = config.getinitparameter("cachebean"); // 获取bean的名称,配置是"bean:" string redisbeanstr = cachebean.substring(5); distributedbaseinterface distributedcache = (distributedbaseinterface) wac.getbean(redisbeanstr); // 获取key,有2种配置方式,1对应为bean,格式为bean:key。2字符串 if (key.startswith("bean:")) { this.key = (string) wac.getbean(key.substring(5)); } else { this.key = key; } this.cookiename = cookiename; this.distributedsessionmanager = distributedsessionmanager.getinstance(distributedcache); //异常处理省略。。。 }
进行实际的请求拦截:
@override public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws servletexception, ioexception { distributedhttpservletrequestwrapper distreq = null; try { //请求处理 distreq = createdistributedrequest(servletrequest, servletresponse); filterchain.dofilter(distreq, servletresponse); } catch (throwable e) { //省略。。。 } finally { if (distreq != null) { try { //处理完成request后,处理session(主要是保存session会话) dealsessionafterrequest(distreq.getsession()); } catch (throwable e2) { //省略。。。 } } } } //分布式请求 private distributedhttpservletrequestwrapper createdistributedrequest(servletrequest servletrequest, servletresponse servletresponse) throws ioexception, servletexception { httpservletrequest request = (httpservletrequest) servletrequest; httpservletresponse response = (httpservletresponse) servletresponse; string usersid = cookieutil.getcookie(cookiename, request); string actualsid = distributedsessionmanager.getactualsid(usersid, request, key); if (stringutil.isblank(actualsid)) { if (stringutil.isnotblank(usersid)) { log.info("usersid[{}]验证不通过", usersid); } // 写cookie string[] usersidarr = distributedsessionmanager.createusersid(request, key); usersid = usersidarr[0]; cookieutil.setcookie(cookiename, usersid, request, response); actualsid = usersidarr[1]; } actualsid = "sid:" + actualsid; distributedhttpsessionwrapper distsession = null; try { map<string, object> allattribute = distributedsessionmanager.getsession(actualsid, request.getsession() .getmaxinactiveinterval()); distsession = new distributedhttpsessionwrapper(actualsid, request.getsession(), allattribute); } catch (throwable e) { // 出错,删掉缓存数据 log.error(e.getmessage(), e); map<string, object> allattribute = new hashmap<string, object>(); distsession = new distributedhttpsessionwrapper(actualsid, request.getsession(), allattribute); distributedsessionmanager.removesession(distsession); } distributedhttpservletrequestwrapper requestwrapper = new distributedhttpservletrequestwrapper(request, distsession); return requestwrapper; } // request处理完时操作session private void dealsessionafterrequest(distributedhttpsessionwrapper session) { if (session == null) { return; } if (session.changed) { distributedsessionmanager.savesession(session); } else if (session.invalidated) { distributedsessionmanager.removesession(session); } else { distributedsessionmanager.expire(session); } }
2、distributedsessionmanager,主要处理分布式session,核心代码:
class distributedsessionmanager { protected static final logger log = loggerfactory.getlogger(distributedsessionmanager.class); private static distributedsessionmanager instance = null; //redis处理session的接口,自己根据情况实现 private distributedbaseinterface distributedbaseinterface; private static byte[] lock = new byte[1]; private distributedsessionmanager(distributedbaseinterface distributedbaseinterface) { this.distributedbaseinterface = distributedbaseinterface; } public static distributedsessionmanager getinstance(distributedbaseinterface redis) { if (instance == null) { synchronized (lock) { if (instance == null) { instance = new distributedsessionmanager(redis); } } } return instance; } //获取session public map<string, object> getsession(string sid,int second) { string json = this.distributedbaseinterface.get(sid,second); if (stringutil.isnotblank(json)) { return jsonutil.unserializemap(json); } return new hashmap<string, object>(1); } //保存session public void savesession(distributedhttpsessionwrapper session) { map<string, object> map=session.allattribute; if(maputil.isempty(map)){ return; } string json = jsonutil.serializemap(map); this.distributedbaseinterface.set(session.getid(), json, session.getmaxinactiveinterval()); } //删除session public void removesession(distributedhttpsessionwrapper session) { distributedbaseinterface.del(session.getid()); } public void expire(distributedhttpsessionwrapper session) { distributedbaseinterface.expire(session.getid(), session.getmaxinactiveinterval()); } /** * 创建cookie的sid */ public string[] createusersid(httpservletrequest request, string key) { //... } public string getactualsid(string usersid, httpservletrequest request, string key) { //... } }
3、distributedhttpsessionwrapper 实现了 httpsession,进行分布式session包装,核心代码:
public class distributedhttpsessionwrapper implements httpsession { private httpsession orgisession; private string sid; boolean changed = false; boolean invalidated = false; map<string, object> allattribute; public distributedhttpsessionwrapper(string sid, httpsession session, map<string, object> allattribute) { this.orgisession = session; this.sid = sid; this.allattribute = allattribute; } @override public string getid() { return this.sid; } @override public void setattribute(string name, object value) { changed = true; allattribute.put(name, value); } @override public object getattribute(string name) { return allattribute.get(name); } @override public enumeration<string> getattributenames() { set<string> set = allattribute.keyset(); iterator<string> iterator = set.iterator(); return new myenumeration<string>(iterator); } private class myenumeration<t> implements enumeration<t> { iterator<t> iterator; public myenumeration(iterator<t> iterator) { super(); this.iterator = iterator; } @override public boolean hasmoreelements() { return iterator.hasnext(); } @override public t nextelement() { return iterator.next(); } } @override public void invalidate() { this.invalidated = true; } @override public void removeattribute(string name) { changed = true; allattribute.remove(name); } @override public long getcreationtime() { return orgisession.getcreationtime(); } @override public long getlastaccessedtime() { return orgisession.getlastaccessedtime(); } @override public int getmaxinactiveinterval() { return orgisession.getmaxinactiveinterval(); } @override public servletcontext getservletcontext() { return orgisession.getservletcontext(); } @override public object getvalue(string arg0) { return orgisession.getvalue(arg0); } @override public string[] getvaluenames() { return orgisession.getvaluenames(); } @override public boolean isnew() { return orgisession.isnew(); } @override public void putvalue(string arg0, object arg1) { orgisession.putvalue(arg0, arg1); } @override public void removevalue(string arg0) { orgisession.removevalue(arg0); } @override public void setmaxinactiveinterval(int arg0) { orgisession.setmaxinactiveinterval(arg0); } @override public httpsessioncontext getsessioncontext() { return orgisession.getsessioncontext(); }
4、distributedhttpservletrequestwrapper 实现了 httpservletrequestwrapper,包装处理过的session和原始request,核心代码:
public class distributedhttpservletrequestwrapper extends javax.servlet.http.httpservletrequestwrapper { private httpservletrequest orgirequest; private distributedhttpsessionwrapper session; public distributedhttpservletrequestwrapper(httpservletrequest request, distributedhttpsessionwrapper session) { super(request); if (session == null){ //异常处理。。 } if (request == null){ //异常处理。。 } this.orgirequest = request; this.session = session; } public distributedhttpsessionwrapper getsession(boolean create) { orgirequest.getsession(create); return session; } public distributedhttpsessionwrapper getsession() { return session; } }
5、另外,定义distributedbaseinterface接口,用来处理session入redis进行持久化操作:
public interface distributedbaseinterface { /** * 根据key获取缓存数据 * @param key * @param seconds */ public string get(string key,int seconds); /** * 更新缓存数据 * @param key * @param json * @param seconds */ public void set(string key, string json,int seconds); /** * 删除缓存 * @param key */ public void del(string key); /** * 设置过期数据 * @param key * @param seconds */ public void expire(string key,int seconds);
注:本文只是在spring中采用redis的方式对session进行管理,还有其他诸多的实现方式,比如在容器里面配置等,设计路由算法让session依赖于集群中的各个节点服务器,,,,,,但redis这种方式在实际应用中还是比较广泛的,lz公司主要就是采用此方式。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
如何使用Spring+redis实现对session的分布式管理
-
IPAD平板电脑如何连接PC电脑方便实现对平板电脑的管理
-
如何在ASP.Net Core使用分布式缓存的实现
-
Redis实现分布式Session管理的机制详解
-
IPAD平板电脑如何连接PC电脑方便实现对平板电脑的管理
-
使用 doctrine orm 如何在程序逻辑上实现在一张表完成两个外键的设置(或则说一个实体完成两个多对一的关系)?
-
Redis实践:使用Pub/Sub实现对服务器群的管理监控
-
Laravel的多对多关系模型如何在分布式的情况下使用,比如用户表在另一台服务器?
-
如何在ASP.Net Core使用分布式缓存的实现
-
使用redis来实现tornado session的分布式存储