Redis实现分布式session功能的共享
来源:互联网 发布:华为怎样隐藏软件 编辑:程序博客网 时间:2024/06/05 14:37
最近项目设计集群,实现了一下session的共享功能,其原理是将session保存到分布式缓存数据库中如:redis, memcache等,然后多个服务器tomcat每次请求都通过NoSql数据库查询,如果存在,则获取值;反之存放值。我是通过redis来实现session的共享,其主要有一下两种方法:1、通过tomcat服务器的拓展功能实现 这种方式比较简单,主要是通过继承session的ManagerBase类,实现重写session相关的方法,这种比较简单, 参考源码链接(http://download.csdn.net/detail/fengshizty/9417242)。2、通过filter拦截request请求实现 下面主要介绍这样实现方式: (1)写HttpSessionWrapper实现HttpSession接口,实现里面session相关的方法。 (2)写HttpServletRequestWrapper继承javax.servlet.http.HttpServletRequestWrapper类,重写对于session 相关的方法。 (3)写SessionFilter拦截配置的请求url,过去cookie中 的sessionId,如果为空,对此次请求重写生成一个新的sessionId,在sessionId构造新的HttpServletRequestWrapper对象。 (4)写SessionService实现session到redis的保存和过去,其key为sessionId,value为session对于的Map。3、代码实现 (1)HttpSessionWrapper
/** * 创建时间:2016年1月21日 下午7:55:41 * * @author andy * @version 2.2 */public class HttpSessionWrapper implements HttpSession { private String sid = ""; private HttpSession session; private HttpServletRequest request; private HttpServletResponse response; private Map<String, Object> map = null; private SessionService sessionService = (SessionService) SpringContextHolder.getBean("sessionService"); public HttpSessionWrapper() { } public HttpSessionWrapper(HttpSession session) { this.session = session; } public HttpSessionWrapper(String sid, HttpSession session) { this(session); this.sid = sid; } public HttpSessionWrapper(String sid, HttpSession session, HttpServletRequest request, HttpServletResponse response) { this(sid, session); this.request = request; this.response = response; } private Map<String, Object> getSessionMap() { if (this.map == null) { this.map = sessionService.getSession(this.sid); } return this.map; } @Override public Object getAttribute(String name) { if (this.getSessionMap() != null) { Object value = this.getSessionMap().get(name); return value; } return null; } @Override public void setAttribute(String name, Object value) { this.getSessionMap().put(name, value); sessionService.saveSession(this.sid, this.getSessionMap()); } @Override public void invalidate() { this.getSessionMap().clear(); sessionService.removeSession(this.sid); CookieUtil.removeCookieValue(this.request,this.response, GlobalConstant.JSESSIONID); } @Override public void removeAttribute(String name) { this.getSessionMap().remove(name); sessionService.saveSession(this.sid, this.getSessionMap()); } @Override public Object getValue(String name) { return this.session.getValue(name); } @SuppressWarnings("unchecked") @Override public Enumeration getAttributeNames() { return (new Enumerator(this.getSessionMap().keySet(), true)); } @Override public String[] getValueNames() { return this.session.getValueNames(); } @Override public void putValue(String name, Object value) { this.session.putValue(name, value); } @Override public void removeValue(String name) { this.session.removeValue(name); } @Override public long getCreationTime() { return this.session.getCreationTime(); } @Override public String getId() { return this.sid; } @Override public long getLastAccessedTime() { return this.session.getLastAccessedTime(); } @Override public ServletContext getServletContext() { return this.session.getServletContext(); } @Override public void setMaxInactiveInterval(int interval) { this.session.setMaxInactiveInterval(interval); } @Override public int getMaxInactiveInterval() { return this.session.getMaxInactiveInterval(); } @Override public HttpSessionContext getSessionContext() { return this.session.getSessionContext(); } @Override public boolean isNew() { return this.session.isNew(); }}
(2)HttpServletRequestWrapper实现
/** * 创建时间:2016年1月22日 下午7:52:29 * * @author andy * @version 2.2 */public class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper { private HttpSession session; private HttpServletRequest request; private HttpServletResponse response; private String sid = ""; public HttpServletRequestWrapper(HttpServletRequest request) { super(request); } public HttpServletRequestWrapper(String sid, HttpServletRequest request) { super(request); this.sid = sid; } public HttpServletRequestWrapper(String sid, HttpServletRequest request, HttpServletResponse response) { super(request); this.request = request; this.response = response; this.sid = sid; if (this.session == null) { this.session = new HttpSessionWrapper(sid, super.getSession(false), request, response); } } @Override public HttpSession getSession(boolean create) { if (this.session == null) { if (create) { this.session = new HttpSessionWrapper(this.sid, super.getSession(create), this.request, this.response); return this.session; } else { return null; } } return this.session; } @Override public HttpSession getSession() { if (this.session == null) { this.session = new HttpSessionWrapper(this.sid, super.getSession(), this.request, this.response); } return this.session; }}
(3)SessionFilter拦截器的实现
public class SessionFilter extends OncePerRequestFilter implements Filter { private static final Logger LOG = Logger.getLogger(SessionFilter.class); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { //从cookie中获取sessionId,如果此次请求没有sessionId,重写为这次请求设置一个sessionId String sid = CookieUtil.getCookieValue(request, GlobalConstant.JSESSIONID); if(StringUtils.isEmpty(sid) || sid.length() != 36){ sid = StringUtil.getUuid(); CookieUtil.setCookie(request, response, GlobalConstant.JSESSIONID, sid, 60 * 60); } //交给自定义的HttpServletRequestWrapper处理 filterChain.doFilter(new HttpServletRequestWrapper(sid, request, response), response); }}
(4)SessionService实现session从redis的读写存储
public class SessionService { private final static Logger LOG = Logger.getLogger(SessionService.class); private JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(); @Autowired private RedisTemplate<Serializable, Serializable> redisTemplate; @SuppressWarnings("unchecked") public Map<String, Object> getSession(String sid) { Map<String, Object> session = new HashMap<String, Object>(); try { Object obj = redisTemplate.opsForValue() .get(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid); if(obj != null){ obj = jdkSerializer.deserialize((byte[])obj); session = (Map<String, Object>) obj; } } catch (Exception e) { LOG.error("Redis获取session异常" + e.getMessage(), e.getCause()); } return session; } public void saveSession(String sid, Map<String, Object> session) { try { redisTemplates.opsForValue() .set(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid, jdkSerializer.serialize(session), RedisKeyUtil.SESSION_TIMEOUT, TimeUnit.MINUTES); } catch (Exception e) { LOG.error("Redis保存session异常" + e.getMessage(), e.getCause()); } } public void removeSession(String sid) { try { redisTemplates.delete( RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid); } catch (Exception e) { LOG.error("Redis删除session异常" + e.getMessage(), e.getCause()); } }}
(5)Session的拦截配置,一般的我们只需要拦截我们定义的拦截请求拦截,而不需要所有的都需要拦截。在web.xml中配置SessionFilter。
<filter> <filter-name>sessionFilter</filter-name> <filter-class>org.andy.shop.session.SessionFilter</filter-class> </filter> <filter-mapping> <filter-name>sessionFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
附:设计到的工具类
1、StringUtil工具类
/** * String工具类 * * @author andy * @date 2015-5-16 下午4:04:22 * */public class StringUtil { private StringUtil() { super(); } /** * 出去null和"" * @param src * @return */ public static String formatNull(String src) { return (src == null || "null".equals(src)) ? "" : src; } /** * 判断字符串是否为空的正则表达式,空白字符对应的unicode编码 */ private static final String EMPTY_REGEX = "[\\s\\u00a0\\u2007\\u202f\\u0009-\\u000d\\u001c-\\u001f]+"; /** * 验证字符串是否为空 * * @param input * @return */ public static boolean isEmpty(String input) { return input == null || input.equals("") || input.matches(EMPTY_REGEX); } public static boolean isNotEmpty(String input){ return !isEmpty(input); } public static String getUuid() { return UUID.randomUUID().toString(); }}
2、Cookie管理CookieUtil工具类
/** * 创建时间:2016年1月22日 下午8:33:56 * * @author andy * @version 2.2 */public class CookieUtil { private static final String KEY = "jkdflsffff()kldkjapfdY=::$B+DUOWAN"; private HttpServletRequest request; private HttpServletResponse response; private static String domain = "andy.com"; public CookieUtil(HttpServletRequest request, HttpServletResponse response) { this.request = request; this.response = response; } /** * 保存cookie * @param request * @param response * @param name cookie名称 * @param value cookie值 * @param seconds 过期时间(单位秒) -1代表关闭浏览器时cookie即过期 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, int seconds) { if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) return; Cookie cookie = new Cookie(name, value); //cookie.setDomain(domain); cookie.setMaxAge(seconds); cookie.setPath("/"); response.setHeader("P3P", "CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'"); response.addCookie(cookie); } /** * 过去cookie中保存的值 * @param name * @return * @throws UnsupportedEncodingException */ public String getCookieValue(String name) throws UnsupportedEncodingException { Cookie cookies[] = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (name.equalsIgnoreCase(cookies[i].getName())) { return cookies[i].getValue(); } } } return ""; } /** * 设置加密的cookie * @param name cookie名称 * @param value cookie值 * @param seconds 过期时间 -1代表关闭浏览器时cookie即过期 */ public void setCheckCodeCookie(String name, String value, int seconds) { if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) { return; } String md5Value = MD5Utils.getMD5(KEY + value); Cookie cookie = new Cookie(name, md5Value); //cookie.setDomain(domain); cookie.setMaxAge(seconds); cookie.setPath("/"); response.addCookie(cookie); } /** * 校验加密的cookie * @param name * @param value * @return */ public boolean checkCodeCookie(String name, String value) { if (StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) { return false; } boolean result = false; String cookieValue = getCookieValue(request, name); if (MD5Utils.getMD5(KEY + value).equalsIgnoreCase( cookieValue)) { result = true; } return result; } /** * 获取cookie值 * @param request * @param name * @return */ public static String getCookieValue(HttpServletRequest request, String name) { try { Cookie cookies[] = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (name.equalsIgnoreCase(cookies[i].getName())) { return cookies[i].getValue(); } } } } catch (Exception e) { } return ""; } /** * 移除客户端的cookie * @param request * @param response * @param name */ public static void removeCookieValue(HttpServletRequest request, HttpServletResponse response, String name) { try { Cookie cookies[] = request.getCookies(); if (cookies != null && cookies.length > 0) { for (Cookie cookie : cookies) { if (name.equalsIgnoreCase(cookie.getName())) { cookie = new Cookie(name, null); cookie.setMaxAge(0); cookie.setPath("/"); //cookie.setDomain(domain); response.addCookie(cookie); break; } } } } catch (Exception e) { e.printStackTrace(); } }}
3、redis键key设置类RedisKeyUtil
/** * 创建时间:2015年9月22日 下午4:51:11 * * @author andy * @version 2.2 */public class RedisKeyUtil { public static final String SESSION_DISTRIBUTED_SESSIONID = "session:distributed:"; //分布式session sessionid -- sessionvalue public static final Integer SESSION_TIMEOUT = 2; //session 失效时间2小时}
4、分布式session常量设置类GlobalConstant
/** * 创建时间:2016年1月23日 上午11:16:56 * * 分布式session常量 * * @author andy * @version 2.2 */public class GlobalConstant { public static final String USER_SESSION_KEY = "user_session_key";//用户session信息 public static final String JSESSIONID = "YHMJSESSIONID"; //jsessionid}
分布式session在redis执行结果:
0 0
- Redis实现分布式session功能的共享
- Redis实现分布式session功能的共享
- Redis实现分布式session功能的共享
- Redis实现分布式session功能的共享
- Redis实现分布式session功能的共享
- Redis实现分布式session功能的共享 [转]
- redis实现分布式session共享
- redis实现分布式session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- Spring Session + Redis实现分布式Session共享
- java中的引用和GC
- 使用汇编语言编写程序,设计一个用8051单片机控制的循环彩灯控制系统
- WebService 写对外接口
- 8个LED依次循环发光,3种显示效果,要求通过按钮切换
- 做个15路输出的彩灯
- Redis实现分布式session功能的共享
- 设计程序,用数码管显示按键编号
- 腾讯公司将为您检测密码强度,防止QQ被盗,请您输入密码
- android自定义view实现流式布局(FlowLayout)和热门标签
- 关于单片机测量信号频率的精度问题
- 用汇编语言编八路彩灯控制系统(流水灯)
- android自定义checkBox样式
- 计时秒表程序设计
- MCS-51单片机中断测试系统设计