中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Spring+redis實現對session的分布式管理

發布時間:2020-08-23 08:45:29 來源:腳本之家 閱讀:174 作者:幢一幢 欄目:編程語言

在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公司主要就是采用此方式。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

民勤县| 鄂州市| 中山市| 汉中市| 察哈| 什邡市| 南昌县| 房山区| 南部县| 栾城县| 安福县| 靖边县| 浮梁县| 兴安县| 桃园县| 垣曲县| 宾阳县| 宁明县| 申扎县| 合水县| 白沙| 化德县| 宿迁市| 大田县| 宁国市| 徐州市| 罗源县| 甘南县| 阜康市| 玉树县| 大埔县| 灌南县| 阿克| 洪雅县| 金寨县| 乌海市| 新营市| 平邑县| 石景山区| 新干县| 古蔺县|