首页 > 开发 > Java > 正文

如何使用Spring+redis实现对session的分布式管理

2024-07-14 08:41:24
字体:
来源:转载
供稿:网友

在Spring中实现分布式 session管理

本文主要是在Spring中实现分布式session,采用redis对session进行持久化管理,这样当应用部署的时候,不需要在Resin、Tomcat等容器里面进行分布式配置,方便加入新的节点服务器进行集群扩容,session不依赖各节点的服务器,可直接从redis获取。下面是功能的核心代码:

一、首先在web.xml里面配置

加入拦截器:

<!-- 分布式session start -->  <filter>    <filter-name>distributedSessionFilter</filter-name>    <filter-class>DistributedSessionFilter</filter-class>    <init-param>      <!-- 必填,密钥.2种方式,1对应为bean,格式为bean:key。2字符串,格式如:afffrfgv-->      <param-name>key</param-name>      <param-value>xxxxxxxx</param-value>    </init-param>    <init-param>      <!-- 必填,redis对应的bean,格式为bean:xx-->      <param-name>cacheBean</param-name>      <param-value>bean:redisPersistent</param-value>//DistributedBaseInterFace,对应于此接口,进行session的持久化操作    </init-param>    <init-param>      <!-- 必填, -->      <param-name>cookieName</param-name>      <param-value>TESTSESSIONID</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>distributedSessionFilter</filter-name>    <url-pattern>*.do</url-pattern>  </filter-mapping>  <!-- 分布式session end -->

二、拦截器的实现,核心代码如下

主要有以下的几个类:

  1. DistributedSessionFilter,
  2. DistributedSessionManager,
  3. DistributedHttpSessionWrapper,
  4. DistributedHttpServletRequestWrapper

1、DistributedSessionFilter实现Filter:

import java.io.IOException;import java.util.HashMap;import java.util.Map;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.support.WebApplicationContextUtils;public class DistributedSessionFilter implements Filter {  private static final Logger log = LoggerFactory.getLogger(DistributedSessionFilter.class);  private String cookieName;  //主要是对session进行管理的操作  private DistributedSessionManager distributedSessionManager;  private String key;}

容器启动时候的初始化方法:

@Override  public void init(FilterConfig config) throws ServletException {    WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(config        .getServletContext());    String key = config.getInitParameter("key");    String cookieName = config.getInitParameter("cookieName");    String cacheBean = config.getInitParameter("cacheBean");    // 获取bean的名称,配置是"bean:"    String redisBeanStr = cacheBean.substring(5);    DistributedBaseInterFace distributedCache = (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  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)      throws ServletException, IOException {    DistributedHttpServletRequestWrapper distReq = null;    try {      //请求处理      distReq = createDistributedRequest(servletRequest, servletResponse);      filterChain.doFilter(distReq, servletResponse);    } catch (Throwable e) {      //省略。。。    } finally {      if (distReq != null) {        try {          //处理完成request后,处理session(主要是保存session会话)          dealSessionAfterRequest(distReq.getSession());        } catch (Throwable e2) {          //省略。。。        }      }    }  }  //分布式请求  private DistributedHttpServletRequestWrapper createDistributedRequest(ServletRequest servletRequest,      ServletResponse servletResponse) throws IOException, ServletException {    HttpServletRequest request = (HttpServletRequest) servletRequest;    HttpServletResponse response = (HttpServletResponse) servletResponse;    String userSid = CookieUtil.getCookie(cookieName, request);    String actualSid = 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;    DistributedHttpSessionWrapper distSession = null;    try {      Map<String, Object> allAttribute = distributedSessionManager.getSession(actualSid, request.getSession()          .getMaxInactiveInterval());      distSession = new DistributedHttpSessionWrapper(actualSid, request.getSession(), allAttribute);    } catch (Throwable e) {      // 出错,删掉缓存数据      log.error(e.getMessage(), e);      Map<String, Object> allAttribute = new HashMap<String, Object>();      distSession = new DistributedHttpSessionWrapper(actualSid, request.getSession(), allAttribute);      distributedSessionManager.removeSession(distSession);    }    DistributedHttpServletRequestWrapper requestWrapper = new DistributedHttpServletRequestWrapper(request,        distSession);    return requestWrapper;  }  // request处理完时操作session  private void dealSessionAfterRequest(DistributedHttpSessionWrapper session) {    if (session == null) {      return;    }    if (session.changed) {      distributedSessionManager.saveSession(session);    } else if (session.invalidated) {      distributedSessionManager.removeSession(session);    } else {      distributedSessionManager.expire(session);    }  }

 2、DistributedSessionManager,主要处理分布式session,核心代码:

class DistributedSessionManager {  protected static final Logger log = LoggerFactory.getLogger(DistributedSessionManager.class);  private static DistributedSessionManager instance = null;  //redis处理session的接口,自己根据情况实现  private DistributedBaseInterFace distributedBaseInterFace;  private static byte[] lock = new byte[1];  private DistributedSessionManager(DistributedBaseInterFace distributedBaseInterFace) {    this.distributedBaseInterFace = distributedBaseInterFace;  }  public static DistributedSessionManager getInstance(DistributedBaseInterFace redis) {    if (instance == null) {      synchronized (lock) {        if (instance == null) {          instance = new DistributedSessionManager(redis);        }      }    }    return instance;  }  //获取session  public Map<String, Object> getSession(String sid,int second) {    String json = this.distributedBaseInterFace.get(sid,second);    if (StringUtil.isNotBlank(json)) {      return JsonUtil.unserializeMap(json);    }    return new HashMap<String, Object>(1);  }  //保存session  public void saveSession(DistributedHttpSessionWrapper session) {    Map<String, Object> map=session.allAttribute;    if(MapUtil.isEmpty(map)){      return;    }    String json = JsonUtil.serializeMap(map);    this.distributedBaseInterFace.set(session.getId(), json, session.getMaxInactiveInterval());  }  //删除session  public void removeSession(DistributedHttpSessionWrapper session) {    distributedBaseInterFace.del(session.getId());  }  public void expire(DistributedHttpSessionWrapper session) {    distributedBaseInterFace.expire(session.getId(), session.getMaxInactiveInterval());  }  /**   * 创建cookie的sid   */  public String[] createUserSid(HttpServletRequest request, String key) {    //...  }  public String getActualSid(String userSid, HttpServletRequest request, String key) {    //...  }}

3、DistributedHttpSessionWrapper 实现了 HttpSession,进行分布式session包装,核心代码:

public class DistributedHttpSessionWrapper implements HttpSession {  private HttpSession orgiSession;  private String sid;  boolean changed = false;  boolean invalidated = false;  Map<String, Object> allAttribute;  public DistributedHttpSessionWrapper(String sid, HttpSession session, Map<String, Object> allAttribute) {    this.orgiSession = session;    this.sid = sid;    this.allAttribute = allAttribute;  }  @Override  public String getId() {    return this.sid;  }  @Override  public void setAttribute(String name, Object value) {    changed = true;    allAttribute.put(name, value);  }  @Override  public Object getAttribute(String name) {    return allAttribute.get(name);  }  @Override  public Enumeration<String> getAttributeNames() {    Set<String> set = allAttribute.keySet();    Iterator<String> iterator = set.iterator();    return new MyEnumeration<String>(iterator);  }  private class MyEnumeration<T> implements Enumeration<T> {    Iterator<T> iterator;    public MyEnumeration(Iterator<T> iterator) {      super();      this.iterator = iterator;    }    @Override    public boolean hasMoreElements() {      return iterator.hasNext();    }    @Override    public T nextElement() {      return iterator.next();    }  }  @Override  public void invalidate() {    this.invalidated = true;  }  @Override  public void removeAttribute(String name) {    changed = true;    allAttribute.remove(name);  }  @Override  public long getCreationTime() {    return orgiSession.getCreationTime();  }  @Override  public long getLastAccessedTime() {    return orgiSession.getLastAccessedTime();  }  @Override  public int getMaxInactiveInterval() {    return orgiSession.getMaxInactiveInterval();  }  @Override  public ServletContext getServletContext() {    return orgiSession.getServletContext();  }  @Override  public Object getValue(String arg0) {    return orgiSession.getValue(arg0);  }  @Override  public String[] getValueNames() {    return orgiSession.getValueNames();  }  @Override  public boolean isNew() {    return orgiSession.isNew();  }  @Override  public void putValue(String arg0, Object arg1) {    orgiSession.putValue(arg0, arg1);  }  @Override  public void removeValue(String arg0) {    orgiSession.removeValue(arg0);  }  @Override  public void setMaxInactiveInterval(int arg0) {    orgiSession.setMaxInactiveInterval(arg0);  }  @Override  public HttpSessionContext getSessionContext() {    return orgiSession.getSessionContext();  }

4、DistributedHttpServletRequestWrapper 实现了 HttpServletRequestWrapper,包装处理过的session和原始request,核心代码:

public class DistributedHttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {  private HttpServletRequest orgiRequest;  private DistributedHttpSessionWrapper session;  public DistributedHttpServletRequestWrapper(HttpServletRequest request, DistributedHttpSessionWrapper session) {    super(request);    if (session == null){      //异常处理。。    }    if (request == null){      //异常处理。。    }    this.orgiRequest = request;    this.session = session;  }  public DistributedHttpSessionWrapper getSession(boolean create) {    orgiRequest.getSession(create);    return session;  }  public DistributedHttpSessionWrapper getSession() {    return session;  }}

5、另外,定义DistributedBaseInterFace接口,用来处理session入redis进行持久化操作:

public interface DistributedBaseInterFace {  /**   * 根据key获取缓存数据   * @param key     * @param seconds     */  public String get(String key,int seconds);  /**   * 更新缓存数据   * @param key     * @param json   * @param seconds   */  public void set(String key, String json,int seconds);  /**   * 删除缓存   * @param key   */  public void del(String key);  /**   * 设置过期数据   * @param key   * @param seconds   */  public void expire(String key,int seconds);

注:本文只是在Spring中采用redis的方式对session进行管理,还有其他诸多的实现方式,比如在容器里面配置等,设计路由算法让session依赖于集群中的各个节点服务器,,,,,,但redis这种方式在实际应用中还是比较广泛的,LZ公司主要就是采用此方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表