文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

spring-session如何实现

2023-05-30 20:03

关注

小编给大家分享一下spring-session如何实现,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

一:spring-session介绍

1.简介

session一直都是我们做集群时需要解决的一个难题,过去我们可以从serlvet容器上解决,比如开源servlet容器-tomcat提供的tomcat-redis-session-manager、memcached-session-manager。

或者通过nginx之类的负载均衡做ip_hash,路由到特定的服务器上..

但是这两种办法都存在弊端。

spring-session是spring旗下的一个项目,把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题。可简单快速且无缝的集成到我们的应用中。

支持功能

1)轻易把session存储到第三方存储容器,框架提供了redis、jvm的map、mongo、gemfire、hazelcast、jdbc等多种存储session的容器的方式。

2)同一个浏览器同一个网站,支持多个session问题。

3)RestfulAPI,不依赖于cookie。可通过header来传递jessionID

4)WebSocket和spring-session结合,同步生命周期管理。

集成方式

集成方式非常简单,直接看官网的samplesandguide。http://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/

主要分为以下几个集成步骤:

1)引入依赖jar包

2)注解方式或者xml方式配置特定存储容器的存储方式,如redis的xml配置方式

<context:annotation-config/>  <beanclass="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>   <beanclass="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>

3)xml方式配置 web.xml ,配置 springSessionFilter到 filter chain中

<filter>     <filter-name>springSessionRepositoryFilter</filter-name>     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>    </filter>    <filter-mapping>     <filter-name>springSessionRepositoryFilter</filter-name>     <url-pattern>public class SessionRepositoryFilter<S extends ExpiringSession>    extends OncePerRequestFilter {    private final SessionRepository<S> sessionRepository;  private ServletContext servletContext;    private MultiHttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();  public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {    if (sessionRepository == null) {      throw new IllegalArgumentException("sessionRepository cannot be null");    }    this.sessionRepository = sessionRepository;  }  public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {    if (httpSessionStrategy == null) {      throw new IllegalArgumentException("httpSessionStrategy cannot be null");    }        this.httpSessionStrategy = new MultiHttpSessionStrategyAdapter(        httpSessionStrategy);  }  public void setHttpSessionStrategy(MultiHttpSessionStrategy httpSessionStrategy) {    if (httpSessionStrategy == null) {      throw new IllegalArgumentException("httpSessionStrategy cannot be null");    }    this.httpSessionStrategy = httpSessionStrategy;  }     @Override  protected void doFilterInternal(HttpServletRequest request,      HttpServletResponse response, FilterChain filterChain)      throws ServletException, IOException {    request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);            SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(        request, response, this.servletContext);    SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(        wrappedRequest, response);    HttpServletRequest strategyRequest = this.httpSessionStrategy        .wrapRequest(wrappedRequest, wrappedResponse);    HttpServletResponse strategyResponse = this.httpSessionStrategy        .wrapResponse(wrappedRequest, wrappedResponse);    try {              filterChain.doFilter(strategyRequest, strategyResponse);    }    finally {      wrappedRequest.commitSession();    }  }  public void setServletContext(ServletContext servletContext) {    this.servletContext = servletContext;  }    private final class SessionRepositoryResponseWrapper      extends OnCommittedResponseWrapper {    private final SessionRepositoryRequestWrapper request;    SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request,        HttpServletResponse response) {      super(response);      if (request == null) {        throw new IllegalArgumentException("request cannot be null");      }      this.request = request;    }         @Override    protected void onResponseCommitted() {      this.request.commitSession();    }  }    private final class SessionRepositoryRequestWrapper      extends HttpServletRequestWrapper {    private Boolean requestedSessionIdValid;    private boolean requestedSessionInvalidated;    private final HttpServletResponse response;    private final ServletContext servletContext;    private SessionRepositoryRequestWrapper(HttpServletRequest request,        HttpServletResponse response, ServletContext servletContext) {      super(request);      this.response = response;      this.servletContext = servletContext;    }        private void commitSession() {      HttpSessionWrapper wrappedSession = getCurrentSession();      if (wrappedSession == null) {          // session失效,删除cookie或者header        if (isInvalidateClientSession()) {          SessionRepositoryFilter.this.httpSessionStrategy              .onInvalidateSession(this, this.response);        }      }      else {        S session = wrappedSession.getSession();        SessionRepositoryFilter.this.sessionRepository.save(session);        if (!isRequestedSessionIdValid()            || !session.getId().equals(getRequestedSessionId())) {        // 把cookie或者header写回给浏览器保存         SessionRepositoryFilter.this.httpSessionStrategy.onNewSession(session,              this, this.response);        }      }    }    @SuppressWarnings("unchecked")    private HttpSessionWrapper getCurrentSession() {      return (HttpSessionWrapper) getAttribute(CURRENT_SESSION_ATTR);    }    private void setCurrentSession(HttpSessionWrapper currentSession) {      if (currentSession == null) {        removeAttribute(CURRENT_SESSION_ATTR);      }      else {        setAttribute(CURRENT_SESSION_ATTR, currentSession);      }    }    @SuppressWarnings("unused")    public String changeSessionId() {      HttpSession session = getSession(false);      if (session == null) {        throw new IllegalStateException(            "Cannot change session ID. There is no session associated with this request.");      }      // eagerly get session attributes in case implementation lazily loads them      Map<String, Object> attrs = new HashMap<String, Object>();      Enumeration<String> iAttrNames = session.getAttributeNames();      while (iAttrNames.hasMoreElements()) {        String attrName = iAttrNames.nextElement();        Object value = session.getAttribute(attrName);        attrs.put(attrName, value);      }      SessionRepositoryFilter.this.sessionRepository.delete(session.getId());      HttpSessionWrapper original = getCurrentSession();      setCurrentSession(null);      HttpSessionWrapper newSession = getSession();      original.setSession(newSession.getSession());      newSession.setMaxInactiveInterval(session.getMaxInactiveInterval());      for (Map.Entry<String, Object> attr : attrs.entrySet()) {        String attrName = attr.getKey();        Object attrValue = attr.getValue();        newSession.setAttribute(attrName, attrValue);      }      return newSession.getId();    }    // 判断session是否有效    @Override    public boolean isRequestedSessionIdValid() {      if (this.requestedSessionIdValid == null) {        String sessionId = getRequestedSessionId();        S session = sessionId == null ? null : getSession(sessionId);        return isRequestedSessionIdValid(session);      }      return this.requestedSessionIdValid;    }    private boolean isRequestedSessionIdValid(S session) {      if (this.requestedSessionIdValid == null) {        this.requestedSessionIdValid = session != null;      }      return this.requestedSessionIdValid;    }    private boolean isInvalidateClientSession() {      return getCurrentSession() == null && this.requestedSessionInvalidated;    }    private S getSession(String sessionId) {       // 从session存储容器中根据sessionID获取session      S session = SessionRepositoryFilter.this.sessionRepository          .getSession(sessionId);      if (session == null) {        return null;      }      // 设置sesison的最后访问时间,以防过期      session.setLastAccessedTime(System.currentTimeMillis());      return session;    }         @Override    public HttpSessionWrapper getSession(boolean create) {      //快速获取session,可以理解为一级缓存、二级缓存这种关系      HttpSessionWrapper currentSession = getCurrentSession();      if (currentSession != null) {        return currentSession;      }      //从httpSessionStratge里面根据cookie或者header获取sessionID      String requestedSessionId = getRequestedSessionId();      if (requestedSessionId != null          && getAttribute(INVALID_SESSION_ID_ATTR) == null) {                                                   //从存储容器获取session以及设置当次初始化属性                              S session = getSession(requestedSessionId);        if (session != null) {          this.requestedSessionIdValid = true;          currentSession = new HttpSessionWrapper(session, getServletContext());          currentSession.setNew(false);          setCurrentSession(currentSession);          return currentSession;        }        else {          if (SESSION_LOGGER.isDebugEnabled()) {            SESSION_LOGGER.debug(                "No session found by id: Caching result for getSession(false) for this HttpServletRequest.");          }          setAttribute(INVALID_SESSION_ID_ATTR, "true");        }      }      if (!create) {        return null;      }      if (SESSION_LOGGER.isDebugEnabled()) {        SESSION_LOGGER.debug(            "A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "                + SESSION_LOGGER_NAME,            new RuntimeException(                "For debugging purposes only (not an error)"));      }      // 如果该浏览器或者其他http访问者是初次访问服务器,则为他创建个新的session      S session = SessionRepositoryFilter.this.sessionRepository.createSession();      session.setLastAccessedTime(System.currentTimeMillis());      currentSession = new HttpSessionWrapper(session, getServletContext());      setCurrentSession(currentSession);      return currentSession;    }    @Override    public ServletContext getServletContext() {      if (this.servletContext != null) {        return this.servletContext;      }      // Servlet 3.0+      return super.getServletContext();    }    @Override    public HttpSessionWrapper getSession() {      return getSession(true);    }    @Override    public String getRequestedSessionId() {      return SessionRepositoryFilter.this.httpSessionStrategy          .getRequestedSessionId(this);    }        private final class HttpSessionWrapper extends ExpiringSessionHttpSession<S> {      HttpSessionWrapper(S session, ServletContext servletContext) {        super(session, servletContext);      }      @Override      public void invalidate() {        super.invalidate();        SessionRepositoryRequestWrapper.this.requestedSessionInvalidated = true;        setCurrentSession(null);        SessionRepositoryFilter.this.sessionRepository.delete(getId());      }    }  }}

看完了这篇文章,相信你对“spring-session如何实现”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网行业资讯频道,感谢各位的阅读!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯