如何使用Spring+redis实现对session的分布式管理
在Spring中实现分布式session管理
本文主要是在Spring中实现分布式session,采用redis对session进行持久化管理,这样当应用部署的时候,不需要在Resin、Tomcat等容器里面进行分布式配置,方便加入新的节点服务器进行集群扩容,session不依赖各节点的服务器,可直接从redis获取。下面是功能的核心代码:
一、首先在web.xml里面配置
加入拦截器:
distributedSessionFilter DistributedSessionFilter key xxxxxxxx cacheBean bean:redisPersistent //DistributedBaseInterFace,对应于此接口,进行session的持久化操作cookieName TESTSESSIONID distributedSessionFilter *.do
二、拦截器的实现,核心代码如下
主要有以下的几个类:
- DistributedSessionFilter,
- DistributedSessionManager,
- DistributedHttpSessionWrapper,
- DistributedHttpServletRequestWrapper
1、DistributedSessionFilter实现Filter:
importjava.io.IOException; importjava.util.HashMap; importjava.util.Map; importjavax.servlet.Filter; importjavax.servlet.FilterChain; importjavax.servlet.FilterConfig; importjavax.servlet.ServletException; importjavax.servlet.ServletRequest; importjavax.servlet.ServletResponse; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importorg.springframework.web.context.WebApplicationContext; importorg.springframework.web.context.support.WebApplicationContextUtils; publicclassDistributedSessionFilterimplementsFilter{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(DistributedSessionFilter.class); privateStringcookieName; //主要是对session进行管理的操作 privateDistributedSessionManagerdistributedSessionManager; privateStringkey; }
容器启动时候的初始化方法:
@Override publicvoidinit(FilterConfigconfig)throwsServletException{ WebApplicationContextwac=WebApplicationContextUtils.getRequiredWebApplicationContext(config .getServletContext()); Stringkey=config.getInitParameter("key"); StringcookieName=config.getInitParameter("cookieName"); StringcacheBean=config.getInitParameter("cacheBean"); //获取bean的名称,配置是"bean:" StringredisBeanStr=cacheBean.substring(5); DistributedBaseInterFacedistributedCache=(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 publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain) throwsServletException,IOException{ DistributedHttpServletRequestWrapperdistReq=null; try{ //请求处理 distReq=createDistributedRequest(servletRequest,servletResponse); filterChain.doFilter(distReq,servletResponse); }catch(Throwablee){ //省略。。。 }finally{ if(distReq!=null){ try{ //处理完成request后,处理session(主要是保存session会话) dealSessionAfterRequest(distReq.getSession()); }catch(Throwablee2){ //省略。。。 } } } } //分布式请求 privateDistributedHttpServletRequestWrappercreateDistributedRequest(ServletRequestservletRequest, ServletResponseservletResponse)throwsIOException,ServletException{ HttpServletRequestrequest=(HttpServletRequest)servletRequest; HttpServletResponseresponse=(HttpServletResponse)servletResponse; StringuserSid=CookieUtil.getCookie(cookieName,request); StringactualSid=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; DistributedHttpSessionWrapperdistSession=null; try{ MapallAttribute=distributedSessionManager.getSession(actualSid,request.getSession() .getMaxInactiveInterval()); distSession=newDistributedHttpSessionWrapper(actualSid,request.getSession(),allAttribute); }catch(Throwablee){ //出错,删掉缓存数据 log.error(e.getMessage(),e); Map allAttribute=newHashMap (); distSession=newDistributedHttpSessionWrapper(actualSid,request.getSession(),allAttribute); distributedSessionManager.removeSession(distSession); } DistributedHttpServletRequestWrapperrequestWrapper=newDistributedHttpServletRequestWrapper(request, distSession); returnrequestWrapper; } //request处理完时操作session privatevoiddealSessionAfterRequest(DistributedHttpSessionWrappersession){ if(session==null){ return; } if(session.changed){ distributedSessionManager.saveSession(session); }elseif(session.invalidated){ distributedSessionManager.removeSession(session); }else{ distributedSessionManager.expire(session); } }
2、DistributedSessionManager,主要处理分布式session,核心代码:
classDistributedSessionManager{ protectedstaticfinalLoggerlog=LoggerFactory.getLogger(DistributedSessionManager.class); privatestaticDistributedSessionManagerinstance=null; //redis处理session的接口,自己根据情况实现 privateDistributedBaseInterFacedistributedBaseInterFace; privatestaticbyte[]lock=newbyte[1]; privateDistributedSessionManager(DistributedBaseInterFacedistributedBaseInterFace){ this.distributedBaseInterFace=distributedBaseInterFace; } publicstaticDistributedSessionManagergetInstance(DistributedBaseInterFaceredis){ if(instance==null){ synchronized(lock){ if(instance==null){ instance=newDistributedSessionManager(redis); } } } returninstance; } //获取session publicMapgetSession(Stringsid,intsecond){ Stringjson=this.distributedBaseInterFace.get(sid,second); if(StringUtil.isNotBlank(json)){ returnJsonUtil.unserializeMap(json); } returnnewHashMap (1); } //保存session publicvoidsaveSession(DistributedHttpSessionWrappersession){ Map map=session.allAttribute; if(MapUtil.isEmpty(map)){ return; } Stringjson=JsonUtil.serializeMap(map); this.distributedBaseInterFace.set(session.getId(),json,session.getMaxInactiveInterval()); } //删除session publicvoidremoveSession(DistributedHttpSessionWrappersession){ distributedBaseInterFace.del(session.getId()); } publicvoidexpire(DistributedHttpSessionWrappersession){ distributedBaseInterFace.expire(session.getId(),session.getMaxInactiveInterval()); } /** *创建cookie的sid */ publicString[]createUserSid(HttpServletRequestrequest,Stringkey){ //... } publicStringgetActualSid(StringuserSid,HttpServletRequestrequest,Stringkey){ //... } }
3、DistributedHttpSessionWrapper实现了HttpSession,进行分布式session包装,核心代码:
publicclassDistributedHttpSessionWrapperimplementsHttpSession{ privateHttpSessionorgiSession; privateStringsid; booleanchanged=false; booleaninvalidated=false; MapallAttribute; publicDistributedHttpSessionWrapper(Stringsid,HttpSessionsession,Map allAttribute){ this.orgiSession=session; this.sid=sid; this.allAttribute=allAttribute; } @Override publicStringgetId(){ returnthis.sid; } @Override publicvoidsetAttribute(Stringname,Objectvalue){ changed=true; allAttribute.put(name,value); } @Override publicObjectgetAttribute(Stringname){ returnallAttribute.get(name); } @Override publicEnumeration getAttributeNames(){ Set set=allAttribute.keySet(); Iterator iterator=set.iterator(); returnnewMyEnumeration (iterator); } privateclassMyEnumeration implementsEnumeration { Iterator iterator; publicMyEnumeration(Iterator iterator){ super(); this.iterator=iterator; } @Override publicbooleanhasMoreElements(){ returniterator.hasNext(); } @Override publicTnextElement(){ returniterator.next(); } } @Override publicvoidinvalidate(){ this.invalidated=true; } @Override publicvoidremoveAttribute(Stringname){ changed=true; allAttribute.remove(name); } @Override publiclonggetCreationTime(){ returnorgiSession.getCreationTime(); } @Override publiclonggetLastAccessedTime(){ returnorgiSession.getLastAccessedTime(); } @Override publicintgetMaxInactiveInterval(){ returnorgiSession.getMaxInactiveInterval(); } @Override publicServletContextgetServletContext(){ returnorgiSession.getServletContext(); } @Override publicObjectgetValue(Stringarg0){ returnorgiSession.getValue(arg0); } @Override publicString[]getValueNames(){ returnorgiSession.getValueNames(); } @Override publicbooleanisNew(){ returnorgiSession.isNew(); } @Override publicvoidputValue(Stringarg0,Objectarg1){ orgiSession.putValue(arg0,arg1); } @Override publicvoidremoveValue(Stringarg0){ orgiSession.removeValue(arg0); } @Override publicvoidsetMaxInactiveInterval(intarg0){ orgiSession.setMaxInactiveInterval(arg0); } @Override publicHttpSessionContextgetSessionContext(){ returnorgiSession.getSessionContext(); }
4、DistributedHttpServletRequestWrapper实现了HttpServletRequestWrapper,包装处理过的session和原始request,核心代码:
publicclassDistributedHttpServletRequestWrapperextendsjavax.servlet.http.HttpServletRequestWrapper{ privateHttpServletRequestorgiRequest; privateDistributedHttpSessionWrappersession; publicDistributedHttpServletRequestWrapper(HttpServletRequestrequest,DistributedHttpSessionWrappersession){ super(request); if(session==null){ //异常处理。。 } if(request==null){ //异常处理。。 } this.orgiRequest=request; this.session=session; } publicDistributedHttpSessionWrappergetSession(booleancreate){ orgiRequest.getSession(create); returnsession; } publicDistributedHttpSessionWrappergetSession(){ returnsession; } }
5、另外,定义DistributedBaseInterFace接口,用来处理session入redis进行持久化操作:
publicinterfaceDistributedBaseInterFace{ /** *根据key获取缓存数据 *@paramkey *@paramseconds */ publicStringget(Stringkey,intseconds); /** *更新缓存数据 *@paramkey *@paramjson *@paramseconds */ publicvoidset(Stringkey,Stringjson,intseconds); /** *删除缓存 *@paramkey */ publicvoiddel(Stringkey); /** *设置过期数据 *@paramkey *@paramseconds */ publicvoidexpire(Stringkey,intseconds);
注:本文只是在Spring中采用redis的方式对session进行管理,还有其他诸多的实现方式,比如在容器里面配置等,设计路由算法让session依赖于集群中的各个节点服务器,,,,,,但redis这种方式在实际应用中还是比较广泛的,LZ公司主要就是采用此方式。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。