如何使用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);
MapallAttribute=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){
Mapmap=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,MapallAttribute){
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
publicEnumerationgetAttributeNames(){
Setset=allAttribute.keySet();
Iteratoriterator=set.iterator();
returnnewMyEnumeration(iterator);
}
privateclassMyEnumerationimplementsEnumeration{
Iteratoriterator;
publicMyEnumeration(Iteratoriterator){
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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。