简单的session共享的封装
目的
session存储在缓存服务器上(各种缓存服务器上均可,本文以memcached为例),但对开发者来说,他不用关注,只需要调用request.getSession()方法即可获取到session,然后对session的属性进行操作。
面临的问题
1. session获取,不是从application的服务器上获取,要从memcached上获取。
2. session属性的获取及设置,不是设置到application服务器上,而是操作memcached获取或者设置。
解决问题的方法
1. 使用一个HttpServletRequestWrapper的实现类,重写getSession()方法,然后使用filter,来过滤每个请求,使request变为requestWrapper。
2. 使用一个HttpSessionAttributeListener的实现类,重写attributeAdded()、attributeRemoved()、attributeReplaced()方法,当属性发生改变时需要通知memcached中的session发生改变
另外:为解决各个异构系统因语言不通可能发生的兼容问题,session以json字符串存储。
具体代码如下:
wrapper类
import java.io.IOException;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession; import org.springframework.util.StringUtils; import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.javacodegeeks.util.JacksonMapUtil;
import com.javacodegeeks.util.MemcachedUtil; public class GetSessionWrapper extends HttpServletRequestWrapper{
private String sessionId=null;
public GetSessionWrapper(HttpServletRequest request) {
super(request);
}
public GetSessionWrapper(HttpServletRequest request,String sessionId) {
super(request);
this.setSessionId(sessionId);
} @Override
public HttpSession getSession() {
HttpSession httpSession=super.getSession();
//id-->sessionId;
String id="davidwang456";
String json=MemcachedUtil.getValue(id);
if(StringUtils.isEmpty(json)){
return httpSession;
}
httpSession.setAttribute("JPHPSESSID", id);
// 读取JSON数据
Map<String, Object> userData;
try {
userData = JacksonMapUtil.getMapper().readValue(json, Map.class);
for(Map.Entry<String, Object> entry:userData.entrySet()){
httpSession.setAttribute(entry.getKey(), entry.getValue());
}
} catch (JsonParseException e) {
System.out.println("json字符串不能解析成功!");
} catch (JsonMappingException e) {
System.out.println("json字符串不能映射到Map!");
} catch (IOException e) {
System.out.println("io异常!");
}
return httpSession;
} @Override
public HttpSession getSession(boolean create) {
HttpSession httpSession=super.getSession(create);
return httpSession;
}
public static void main(String[] args) {
String sessionId="davidwang456";
String json=MemcachedUtil.getValue(sessionId);
System.out.println(json);
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
}
filter类
import java.io.IOException; import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import org.springframework.web.util.WebUtils; public class FetchSession implements javax.servlet.Filter{
private static final String regex=".*(css|html|ico|html|jpg|jpeg|png|gif|js)";
@Override
public void init(FilterConfig filterConfig) throws ServletException { } private static String getSessionId(ServletRequest request){
HttpServletRequest httpRequest=(HttpServletRequest)request;
String sessionId="";
Cookie cookie =WebUtils.getCookie(httpRequest, "PHPSESSID");
if(cookie!=null){
return cookie.getValue();
}
cookie =WebUtils.getCookie(httpRequest, "JSESSIONID");
if(cookie!=null){
sessionId= cookie.getValue();
}
return sessionId;
} @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String sessionId=getSessionId(request);
HttpServletRequest httpRequest=(HttpServletRequest)request;
String requestedUri=httpRequest.getRequestURL().toString();
System.out.println(requestedUri);
if(requestedUri.matches(regex)){
chain.doFilter(request, response);
return;
}
GetSessionWrapper wrapperRequest=new GetSessionWrapper(httpRequest,sessionId);
//HttpSession httpSession=wrapperRequest.getSession();
chain.doFilter(wrapperRequest, response);
} @Override
public void destroy() {
}
}
属性监听器
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent; import org.springframework.util.StringUtils; import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javacodegeeks.util.JacksonMapUtil;
import com.javacodegeeks.util.MemcachedUtil; public class MySessionAttributeListener
implements HttpSessionAttributeListener {
private static AtomicInteger count=new AtomicInteger(0);
private static AtomicInteger countU=new AtomicInteger(0); @Override
public void attributeAdded(HttpSessionBindingEvent event) {
int ss=count.incrementAndGet();
HttpSession session=event.getSession();
//String sessionId=(String) session.getAttribute("JPHPSESSID");
String sessionId="davidwang456";
String attributeName = event.getName();
Object attributeValue = event.getValue();
System.out.println("Attribute add " + attributeName + " : " + attributeValue+",ss="+ss);
String json=MemcachedUtil.getValue(sessionId);
if(StringUtils.isEmpty(json)){
return ;
}
String json_new;
try {
json_new = attributeAddOrUpdate(json,attributeName,attributeValue);
MemcachedUtil.setValue(sessionId, json_new);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private String attributeAddOrUpdate(String json,String key,Object value)
throws JsonParseException, JsonMappingException, IOException{
ObjectMapper mapper=JacksonMapUtil.getMapper();
@SuppressWarnings("unchecked")
Map<String,Object> userData = mapper.readValue(json, Map.class);
Boolean flag=String.class.isAssignableFrom(value.getClass());
if(!flag){
Map<String, Object> map = mapper.convertValue(value, Map.class);
userData.putAll(map);
}else{
userData.put(key, value);
}
return mapper.writeValueAsString(userData);
} private String attributeDel(String json, String key)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = JacksonMapUtil.getMapper();
@SuppressWarnings("unchecked")
Map<String, Object> userData = mapper.readValue(json, Map.class);
userData.remove(key);
return mapper.writeValueAsString(userData);
} @Override
public void attributeRemoved(HttpSessionBindingEvent event) {
HttpSession session=event.getSession();
//String sessionId=(String) session.getAttribute("JPHPSESSID");
String sessionId="davidwang456";
String attributeName = event.getName();
System.out.println("Attribute del : " + attributeName);
String json=MemcachedUtil.getValue(sessionId);
if(StringUtils.isEmpty(json)){
return ;
}
String json_new;
try {
json_new = attributeDel(json,attributeName);
MemcachedUtil.setValue(sessionId, json_new);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} @Override
public void attributeReplaced(HttpSessionBindingEvent event) { int ssu=countU.incrementAndGet();
HttpSession session=event.getSession();
//String sessionId=(String) session.getAttribute("JPHPSESSID");
String sessionId="davidwang456";
String attributeName = event.getName();
Object attributeValue = event.getValue();
System.out.println("Attribute update " + attributeName + " : " + attributeValue+",ss="+ssu);
String json=MemcachedUtil.getValue(sessionId);
if(StringUtils.isEmpty(json)){
return ;
}
String json_new;
try {
json_new = attributeAddOrUpdate(json,attributeName,attributeValue);
MemcachedUtil.setValue(sessionId, json_new);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
pom.xml依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.12.0</version>
</dependency>
注意:上面代码仅为demo代码,实际应用需重构代码。
简单的session共享的封装的更多相关文章
- nginx+tomcat9+redisson+redis+jdk1.8简单实现session共享
一.环境安装 由于资源限制,在虚拟机中模拟测试,一台虚拟机,所有软件均安装到该虚拟机内 安装系统:CentOS Linux release 7.4.1708 (Core) CentOS安装选择版本:B ...
- 设计模式之装饰模式,session共享的底层原理
前言 还记得当初写spring-session实现分布式集群session的共享的时候,里面有说到利用filter和HttpServletRequestWrapper可以定制自己的getSession ...
- Tomcat通过Memcached实现session共享的完整部署记录
对于web应用集群的技术实现而言,最大的难点就是:如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块.要实现这一点, 大体上有两种方式:一种是把所有Ses ...
- Session共享的简单总结
1.同服务器.同一域名.不同应用(端口.虚拟目录等) 这种很简单,把sessionState保存到SQLServer,aspnet_regsql之后,修改存储过程TempGetAppID,把 SET ...
- Spring Boot 一个依赖搞定 session 共享,没有比这更简单的方案了!
有的人可能会觉得题目有点夸张,其实不夸张,题目没有使用任何修辞手法!认真读完本文,你就知道松哥说的是对的了! 在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是 ...
- 分布式集群Session共享 简单多tomcat8+redis的session共享实现
; i++) { str = str + session.getAttribute("name" + i) + "<br>"; } response ...
- Tomcat中session共享问题的简单解决办法
tomcat-redis-session-manager 使用redis配置tomcat共享session 结构图: 分析: 分布式web server集群部署后需要实现session共享,针对 to ...
- 分布式中使用Redis实现Session共享(二)
上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的session开始,刚好也重新学习一遍session的实现原理.在阅读之前假设你已经会使用nginx+i ...
- 分布式中使用Redis实现Session共享(一)
上一篇介绍了如何使用nginx+iis部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是"如何解决多站点下Session共享".这篇文章将会介绍如何使用Redis,下一篇 ...
随机推荐
- 12套swift学习资源分享
虽然objective-c编程语言在过去很长一段时间都是iOS应用开发的基础语言,且很多iOS开发者对其也深爱有佳,但是随着swift编程语言的问世,迅速发展为开发者追捧的语言.且今年伴随着swift ...
- Chkdsk scan needed on volume
After we extended the volume in storage array, in Failover cluster, it shows the volume is of 30.0 T ...
- SSD性能对比
SSD性能测试顺序写 16k iops 85061.08顺序写 8k iops 146250.93顺序写 4k iops 239816.69顺序写 2k iops 294540.87顺序写 1k io ...
- 声色贴生成图片总结 Imagick
2014-08-24 都是按以前的程序进行了,但去年8月都可以用Imagick正常生成CMYK的图片,但今天就是不行. 经过一切测试方法及思路,解决方法如下. 问题主要出现在: 生成的二维码是RGB格 ...
- Codeforces Round #379 (Div. 2) B. Anton and Digits 水题
B. Anton and Digits 题目连接: http://codeforces.com/contest/734/problem/B Description Recently Anton fou ...
- dapper 操作类封装
using System; using System.Collections.Generic; using System.Data; using System.Data.SQLite; using S ...
- UVA12130 Summits(BFS + 贪心)
UVA12130 Summits(BFS + 贪心) 题目链接 题目大意: 给你一个h ∗ w 的矩阵,矩阵的每一个元素都有一个值,代表这个位置的高度. 题目要求你找出这个图中有多少个位置是峰值点.从 ...
- GitHub上排名前100的iOS开源库介绍(来自github)
主要对当前 GitHub 排名前 100 的项目做一个简单的简介,方便初学者快速了解到当前 Objective-C 在 GitHub 的情况. 若有任何疑问可通过微博@李锦发联系我 项目名称 项目信息 ...
- 日暮·第一章·决斗
日暮 第一章 决斗 泉州府,位于帝国的东南沿海,在数百年前,这里已是帝国最大的通商口岸之一,其一城之繁荣喧哗足以与异邦小国的都城相媲美,无数的人曾经来到这里,追逐财富,梦想,女人以及所有他们认为可 ...
- 让IE8支持HTML5及canvas功能!
微软出的IE9支持HTML5,但因为不支持XP系统,暂时我还用不了. 即使能用,现阶段如果开发HTML5页面,并考虑到兼容性问题的话,恐怕也得让自己的界面支持IE6-8吧. 首先,需要让IE支持HTM ...