总体思想:
掉用的时候直接调用代理实例对象获取即可,用拦截器,或者直接把HttpServletRequestWrapper替换掉
package com.houbank.session.filter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.util.logging.resources.logging;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j2;
import com.houbank.session.manager.RedisTemplateDelegate;
import com.houbank.session.manager.WebSession;
import com.houbank.session.manager.WebSessionManager;
类1
/**
*
* <p>通过继承HttpServletRequestWrapper 来实现</p>
* @author houzhanshan
* @version $Id: RemoteSessionRequest.java, v 0.1 2017年5月26日 下午11:40:51 houzhanshan Exp $
*/
public class RemoteSessionRequest extends HttpServletRequestWrapper {
public RemoteSessionRequest(HttpServletRequest request) {
super(request);
}
//复写getSession方法,外界使用的方法,每次用到session的时候,拿到系统自带的session,建立自己的代理session
@Override
public HttpSession getSession() {
return RemoteSessionHandler.getInstance(super.getSession());
}
}
类2
动态代理session
@Log4j2
class RemoteSessionHandler implements InvocationHandler {
// 模拟远程Session服务器,Key表示SessionId,Value表示该Session的内容
private static Map<String, Map<String, Object>> map = new ConcurrentHashMap<String, Map<String, Object>>();
private static Logger log= LoggerFactory.getLogger(RedisTemplateDelegate.class);
private HttpSession session = null;
private RemoteSessionHandler(HttpSession httpSession) {
this.session = httpSession;
};
//静态方法
//获取实例代理实例,调用代理
public static HttpSession getInstance(HttpSession httpSession) {
//获取代理处理器实例
InvocationHandler handler = new RemoteSessionHandler(httpSession);
//调用代理
return (HttpSession) Proxy.newProxyInstance(httpSession.getClass().getClassLoader(), httpSession.getClass().getInterfaces(), handler);
}
//切入方法点
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("setAttribute".equals(method.getName())) {
String id = session.getId();
Map<String, Object> m = map.get(id);
if (m == null) {
m = new HashMap<String, Object>();
}
WebSession webSession=WebSessionManager.getInstance().getSession(id);
if(webSession==null){
webSession=WebSessionManager.getInstance().createSession(id);
}else{
webSession=WebSessionManager.getInstance().getSession(id);
}
webSession.setAttribute((String) args[0], args[1]);
log.info("[存入]key:" + args[0] + ",value:" + args[1]);
return null;
} else if ("getAttribute".equals(method.getName())) {
String id = session.getId();
WebSession webSession= WebSessionManager.getInstance().getSession(id);
if(webSession==null){
return null;
}
Object result = webSession.getAttribute((String) args[0]);
log.info("[取出]key:" + args[0] + ",value:" + result);
return result;
}
return method.invoke(session, args);
}
}
每次请求的时候重置里面的request,改变拿到request的具体对象,从而改变拿到的session,改变拿值的地方
都有这么一个链,加入过滤器链,不管在哪个顺序,总是在调用资源之前,此时的就都做了,也就在具体资源要用之前就被过滤了(替换成自定义)
@WebFilter("/*")
public class SessionFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//chain就是过滤器链,dofilter就是向下一个链执行
chain.doFilter(new RemoteSessionRequest((HttpServletRequest) request), response);
}
此时需要
HttpServletRequest request1 = (HttpServletRequest) request;
HttpSession session = request1.getSession();
代理HttpSession生成RemoteSessionRequest.java
用这个方法就弄好了session的拦截处理
过滤器:
chain.doFilter(request,response)
一般filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一起
request -> filter1 -> filter2 ->filter3 -> .... -> request resource.
可以提前跳转后return null,也可
附件说明:
core.session.filter
core.session.manager
core.monitor 拦截器
RemoteSessionRequest.java 包装session
SessionFilter.java拦截把包装好的request放入代替原有的request(代替requset用过滤器)(实现redis的单点登录内存session共享),代替框架中的实现类用回调机制,
这样可以代替一切
core.session.filter 代换requset 通过WebSessionManager用自己的session
core.session.manager 代换的里面用的redis(具体换requset的点)
WebUtils.java 获取bean
WebSessionManager.java 管理session
WebSessionManager.java session的具体构造
RedisTemplateDelegate.java 用的redis模板
WebSession.java
也就是存每个用户session,及每个用户session拥有的属性,这样模拟了sso
public void setAttribute(String name, Object value) {
this.attributes.put(name, value);k-v
storageSet(this.storageId, this.attributes); sessionid-v redis中存sessionid 和map对象(装初始k-y和后面增加的k-v)
} 存在内存中,存在redis中
一个用户一个WebSession对象(一个sessionid一个对象),即自定义session,每个session操作更新attributes,保存redis
获取session--->通过sessionid 获取 attributes然后组装成session对象WebSession
后期修改通过sessionid,获取本session,之后调用session内部的操作attributes方法处理本session
相关推荐
springboot +shiro+redis实现session共享(方案二)1
使用说明:请严格按照资源内的readme文档来说明部署,不要搞错版本,完美支持Tomcat8和Tomcat9等新版本Tomcat,仅支持JDK8以上版本JDK。
tomcat-redis实现session共享
今天用了一天来搞定了ssm+redis集成和nginx实现负载均衡,这里只有ssm+redis简单d集成demo,希望大家一起来讨论
ssm+redis+nginx实现session共享和负载均衡,大家一起来研究吧
包含的jar包如下: commons-pool2-2.0.jar jedis-2.5.2.jar tomcat-juli-adapters.jar tomcat-juli.jar tomcat-redis-session-manager1.2.jar
Spring Session + redis实现session共享
集群session共享jar包之tomcat8。集群插件,redis方式实现session共享插件
redis+session共享,redis+session共享,redis+session共享,redis+session共享redis+session共享,redis+session共享,redis+session共享,redis+session共享,redis+session共享
通过本代码,可以搭建springboot + redis实现session共享。利用redis特性可以进行分布式session共享。
自己实现httpSession,在getSession中获取cookie,从cookie中读取sessionId, 如果没有sessionId就新创建session,如果有sessionId,就去redis中查看是否有此id的记录,如果没有就新建session,如果有,还是新建...
SpringBoot+MyBatis+SpringSession+Redis实现session共享及单点登录开发实例
Spring Boot 使用 Redis 进行配置 Session 共享(Ajax 跨域) 源码下载。
linux.tomcat-session共享.redis.安装包
tomcat用redis共享session需要的jar
很好用,使用也很简单,把其中的三个Jar包拷贝到你的tomcat中的...tomcat8、8.5、9与redis实现session共享,并可以通过修改源码可自定义session键,访问地址:http://blog.csdn.net/fackyou200/article/details/78929008
Session共享 tomcat7+redis的session共享实现,无需重新打包,直接放入tomcat lib中就可以使用,记得修改tomcat的content.xml
session共享方案(tomcat8+redis共享session) 一步一步详细指引
Session共享 tomcat8+redis的session共享实现,支持tomcat8
tomcat-redis-session-manager-2.0.0.jar包,不用自己打包了,tomcat共享session到redis中,解决分布式应用的状态问题。