轉:經過Spring Session實現新一代的Session管理

長期以來,session管理就是企業級Java中的一部分,以至於咱們潛意識就認爲它是已經解決的問題,在最近的記憶中,咱們沒有看到這個領域有很大的革新。html

可是,現代的趨勢是微服務以及可水平擴展的原生雲應用(cloud native application),它們會挑戰過去20多年來咱們設計和構建session管理器時的前提假設,而且暴露了現代化session管理器的不足。html5

本文將會闡述最近發佈的Spring Session API如何幫助咱們克服眼下session管理方式中的一些不足,在企業級Java中,傳統上都會採用這種舊的方式。咱們首先會簡單闡述一下當前 session管理中的問題,而後深刻介紹Spring Session是如何解決這些問題的。在文章的最後,將會詳細展現Spring Session是如何運行的,以及在項目中怎樣使用它。java

Spring Session爲企業級Java應用的session管理帶來了革新,使得如下的功能更加容易實現:github

  • 編寫可水平擴展的原生雲應用。
  • 將session所保存的狀態卸載到特定的外部session存儲中,如Redis或Apache Geode中,它們可以以獨立於應用服務器的方式提供高質量的集羣。
  • 當用戶使用WebSocket發送請求的時候,可以保持HttpSession處於活躍狀態。
  • 在非Web請求的處理代碼中,可以訪問session數據,好比在JMS消息的處理代碼中。
  • 支持每一個瀏覽器上使用多個session,從而可以很容易地構建更加豐富的終端用戶體驗。
  • 控制session id如何在客戶端和服務器之間進行交換,這樣的話就能很容易地編寫Restful API,由於它能夠從HTTP 頭信息中獲取session id,而沒必要再依賴於cookie。

須要說明的很重要的一點就是,Spring Session的核心項目並不依賴於Spring框架,因此,咱們甚至可以將其應用於不使用Spring框架的項目中。web

傳統session管理的問題

傳統的JavaEE session管理會有各類問題,這剛好是Spring Session所要試圖解決的。這些問題在下面以樣例的形式進行了闡述。redis

構建可水平擴展的原生雲應用

在原生的雲應用架構中,會假設應用可以進行擴展,這是經過在Linux容器中運行更多的應用程序實例實現的,這些容器會位於一個 大型的虛擬機池中。例如,咱們能夠很容易地將一個「.war」文件部署到位於Cloud Foundry或Heroku的Tomcat中,而後在幾秒鐘的時間內就能擴展到100個應用實例,每一個實例能夠具備1GB RAM。咱們還能夠配置雲平臺,基於用戶的需求自動增長和減小應用實例的數量。spring

在不少的應用服務器中,都會將HTTP session狀態保存在JVM中,這個JVM與運行應用程序代碼的JVM是同一個,由於這樣易於實現,而且速度很快。當新的應用服務器實例加入或離開集 羣時,HTTP session會基於現有的應用服務器實例進行從新平衡。在彈性的雲環境中,咱們會擁有上百個應用服務器實例,而且實例的數量可能在任意時刻增長或減小, 這樣的話,咱們就會遇到一些問題:數據庫

  • 重平衡HTTP session可能會成爲性能瓶頸。
  • 爲了存儲大量的session,會須要很大的堆空間,這會致使垃圾收集,從而對性能產生負面影響。
  • 雲基礎設施一般會禁止TCP多播(multicast),可是session管理器經常會使用這種機制來發現哪個應用服務器實例加入或離開了集羣。

所以,更爲高效的辦法是將HTTP session狀態保存在獨立的數據存儲中,這個存儲位於運行應用程序代碼的JVM以外。例如,咱們能夠將100個Tomcat實例配置爲使用Redis 來存儲session狀態,當Tomcat實例增長或減小的時候,Redis中所存儲的session並不會受到影響。同時,由於Redis是使用C語言 編寫的,因此它可使用上百GB甚至TB級別的RAM,它不會涉及到垃圾收集的問題。apache

對於像Tomcat這樣的開源服務器,很容易找到session管理器的替代方案,這些替代方案可使用外部的數據存儲,如Redis或 Memcached。可是,這些配置過程可能會比較複雜,並且每種應用服務器都有所差異。對於閉源的產品,如WebSphere和Weblogic,尋找 它們的session管理器替代方案不只很是困難,在有些時候,甚至是沒法實現的。

Spring Session提供了一種獨立於應用服務器的方案,這種方案可以在Servlet規範以內配置可插拔的session數據存儲,不依賴於任何應用服務器的 特定API。這就意味着Spring Session可以用於實現了servlet規範的全部應用服務器之中(Tomcat、Jetty、 WebSphere、WebLogic、JBoss等),它可以很是便利地在全部應用服務器中以徹底相同的方式進行配置。咱們還能夠選擇任意最適應需求的 外部session數據存儲。這使得Spring Session成爲一個很理想的遷移工具,幫助咱們將傳統的JavaEE應用轉移到雲中,使其成爲知足 12-factor的應用

每一個用戶有多個帳號

假設咱們在example.com上運行面向公衆的Web應用,在這個應用中有些用戶會建立多個帳號。例如,用戶Jeff Lebowski可能會有兩個帳戶thedude@example.com和lebowski@example.com。和其餘Java Web應用同樣,咱們會使用HttpSession來跟蹤應用的狀態,如當前登陸的用戶。因此,當用戶但願從thedude@example.com切換到lebowski@example.com時,他必需要首先退出,而後再從新登陸回來。

藉助Spring Session,爲每一個用戶配置多個HTTP session會很是容易,這樣用戶在thedude@example.com和lebowski@example.com之間切換的時候,就不須要退出和從新登陸了。

多級別的安全預覽

假設咱們正在構建的Web應用有一個複雜、自定義的權限功能,其中應用的UI會基於用戶所授予的角色和權限實現自適應。

例如,假設應用有四個安全級別:public、confidential、secret和top secret。當用戶登陸應用以後,系統會判斷用戶所具備的最高安全級別而且只會顯示該級別和該級別之下的數據。因此,具備public權限的用戶只能看 到public級別的文檔,具備secret權限的用戶可以看到public、confidential和secret級別的文檔,諸如此類。爲了保證用 戶界面更加友好,應用程序應該容許用戶預覽在較低的安全級別條件下頁面是什麼樣子的。例如,top secret權限的用戶可以將應用從top secret模式切換到secret模式,這樣就能站在具備secret權限用戶的視角上,查看應用是什麼樣子的。

典型的Web應用會將當前用戶的標識及其角色保存在HTTP session中,但由於在Web應用中,每一個登陸的用戶只能有一個session,所以除了用戶退出並從新登陸進來,咱們並無辦法在角色之間進行切換,除非咱們爲每一個用戶自行實現多個session的功能。

藉助Spring Session,能夠很容易地爲每一個登陸用戶建立多個session,這些session之間是徹底獨立的,所以實現上述的預覽功能是很是容易的。例如, 當前用戶以top secret角色進行了登陸,那麼應用能夠建立一個新的session,這個session的最高安全角色是secret而不是top secret,這樣的話,用戶就能夠在secret模式預覽應用了。

當使用Web Socket的時候保持登陸狀態

假設用戶登陸了example.com上的Web應用,那麼他們可使用HTML5的chat客戶端實現聊天的功能,這個客戶端構建在 websocket之上。按照servlet規範,經過websocket傳入的請求並不能保持HTTP session處於活躍狀態,因此當用戶在聊天的過程當中,HTTP session的倒數計時器會在不斷地流逝。即使站在用戶的立場上,他們一直在使用應用程序,HTTP session最終也可能會出現過時。當HTTP session過時時,websocket鏈接將會關閉。

藉助Spring Session,對於系統中的用戶,咱們可以很容易地實現websocket請求和常規的HTTP請求都能保持HTTP session處於活躍狀態。

非Web請求訪問Session數據

假設咱們的應用提供了兩種訪問方式:一種使用基於HTTP的REST API,而另外一種使用基於RabbitMQ的AMQP消息。執行消息處理代碼的線程將沒法訪問應用服務器的HttpSession,因此咱們必需要以一種 自定義的方案來獲取HTTP session中的數據,這要經過自定義的機制來實現。

經過使用Spring Session,只要咱們可以知道session的id,就能夠在應用的任意線程中訪問Spring Session。所以,Spring Session具有比Servlet HTTP session管理器更爲豐富的API,只要知道了session id,咱們就能獲取任意特定的session。例如,在一個傳入的消息中可能會包含用戶id的header信息,藉助它,咱們就能夠直接獲取 session了。

Spring Session是如何運行的

咱們已經討論了在傳統的應用服務器中,HTTP session管理存在不足的各類場景,接下來看一下Spring Session是如何解決這些問題的。

Spring Session的架構

當實現session管理器的時候,有兩個必需要解決的核心問題。首先,如何建立集羣環境下高可用的session,要求可以可靠並高效地存儲數 據。其次,無論請求是HTTP、WebSocket、AMQP仍是其餘的協議,對於傳入的請求該如何肯定該用哪一個session實例。實質上,關鍵問題在 於:在發起請求的協議上,session id該如何進行傳輸?

Spring Session認爲第一個問題,也就是在高可用可擴展的集羣中存儲數據已經經過各類數據存儲方案獲得瞭解決,如Redis、GemFire以及 Apache Geode等等,所以,Spring Session定義了一組標準的接口,能夠經過實現這些接口間接訪問底層的數據存儲。Spring Session定義了以下核心接口:Session、ExpiringSession以及SessionRepository,針對不一樣的數據存儲,它們須要分別實現。

  • org.springframework.session.Session接口定義了session的基本功能,如設置和移除屬性。這個接口並不關心底層技術,所以可以比servlet HttpSession適用於更爲普遍的場景中。
  • org.springframework.session.ExpiringSession擴展了Session接口,它提供了判斷session是否過時的屬性。RedisSession是這個接口的一個樣例實現。
  • org.springframework.session.SessionRepository定義了建立、保存、 刪除以及檢索session的方法。將Session實例真正保存到數據存儲的邏輯是在這個接口的實現中編碼完成的。例 如,RedisOperationsSessionRepository就是這個接口的一個實現,它會在Redis中建立、存儲和刪除session。

Spring Session認爲將請求與特定的session實例關聯起來的問題是與協議相關的,由於在請求/響應週期中,客戶端和服務器之間須要協商贊成一種傳遞 session id的方式。例如,若是請求是經過HTTP傳遞進來的,那麼session能夠經過HTTP cookie或HTTP Header信息與請求進行關聯。若是使用HTTPS的話,那麼能夠藉助SSL session id實現請求與session的關聯。若是使用JMS的話,那麼JMS的Header信息可以用來存儲請求和響應之間的session id。

對於HTTP協議來講,Spring Session定義了HttpSessionStrategy接口以及兩個默認實現,即CookieHttpSessionStrategyHeaderHttpSessionStrategy,其中前者使用HTTP cookie將請求與session id關聯,然後者使用HTTP header將請求與session關聯。

以下的章節詳細闡述了Spring Session使用HTTP協議的細節。

在撰寫本文的時候,在當前的Spring Session 1.0.2 GA發佈版本中,包含了Spring Session使用Redis的實現,以及基於Map的實現,這個實現支持任意的分佈式Map,如Hazelcast。讓Spring Session支持某種數據存儲是至關容易的,如今有支持各類數據存儲的社區實現。

Spring Session對HTTP的支持

Spring Session對HTTP的支持是經過標準的servlet filter來實現的,這個filter必需要配置爲攔截全部的web應用請求,而且它應該是filter鏈中的第一個filter。Spring Session filter會確保隨後調用javax.servlet.http.HttpServletRequestgetSession()方法時,都會返回Spring Session的HttpSession實例,而不是應用服務器默認的HttpSession。

若是要理解它的話,最簡單的方式就是查看Spring Session實際所使用的源碼。首先,咱們瞭解一下標準servlet擴展點的一些背景知識,在實現Spring Session的時候會使用這些知識。

在2001年,Servlet 2.3規範引入了ServletRequestWrapper它的javadoc文檔這樣寫道ServletRequestWrapper「提供了ServletRequest接 口的便利實現,開發人員若是但願將請求適配到Servlet的話,能夠編寫它的子類。這個類實現了包裝(Wrapper)或者說是裝飾 (Decorator)模式。對方法的調用默認會經過包裝的請求對象來執行」。以下的代碼樣例抽取自Tomcat,展示了 ServletRequestWrapper是如何實現的。

public class ServletRequestWrapper implements ServletRequest { private ServletRequest request; /** * 建立ServletRequest適配器,它包裝了給定的請求對象。 * @throws java.lang.IllegalArgumentException if the request is null */ public ServletRequestWrapper(ServletRequest request) { if (request == null) { throw new IllegalArgumentException("Request cannot be null"); } this.request = request; } public ServletRequest getRequest() { return this.request; } public Object getAttribute(String name) { return this.request.getAttribute(name); } // 爲了保證可讀性,其餘的方法刪減掉了 } 

Servlet 2.3規範還定義了HttpServletRequestWrapper,它是ServletRequestWrapper的子類,可以快速提供HttpServletRequest的自定義實現,以下的代碼是從Tomcat抽取出來的,展示了HttpServletRequesWrapper類是如何運行的。

public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest { public HttpServletRequestWrapper(HttpServletRequest request) { super(request); } private HttpServletRequest _getHttpServletRequest() { return (HttpServletRequest) super.getRequest(); } public HttpSession getSession(boolean create) { return this._getHttpServletRequest().getSession(create); } public HttpSession getSession() { return this._getHttpServletRequest().getSession(); } // 爲了保證可讀性,其餘的方法刪減掉了 } 

因此,藉助這些包裝類就能編寫代碼來擴展HttpServletRequest,重載返回HttpSession的方法,讓它返回由外部存儲所提供的實現。以下的代碼是從Spring Session項目中提取出來的,可是我將原來的註釋替換爲我本身的註釋,用來在本文中解釋代碼,因此在閱讀下面的代碼片斷時,請留意註釋。

/* * 注意,Spring Session項目定義了擴展自 * 標準HttpServletRequestWrapper的類,用來重載 * HttpServletRequest中與session相關的方法。 */ private final class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper { private HttpSessionWrapper currentSession; private Boolean requestedSessionIdValid; private boolean requestedSessionInvalidated; private final HttpServletResponse response; private final ServletContext servletContext; /* * 注意,這個構造器很是簡單,它接受稍後會用到的參數, * 而且委託給它所擴展的HttpServletRequestWrapper */ private SessionRepositoryRequestWrapper( HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) { super(request); this.response = response; this.servletContext = servletContext; } /* * 在這裏,Spring Session項目再也不將調用委託給 * 應用服務器,而是實現本身的邏輯, * 返回由外部數據存儲做爲支撐的HttpSession實例。 * * 基本的實現是,先檢查是否是已經有session了。若是有的話, * 就將其返回,不然的話,它會檢查當前的請求中是否有session id。 * 若是有的話,將會根據這個session id,從它的SessionRepository中加載session。 * 若是session repository中沒有session,或者在當前請求中, * 沒有當前session id與請求關聯的話, * 那麼它會建立一個新的session,並將其持久化到session repository中。 */ @Override public HttpSession getSession(boolean create) { if(currentSession != null) { return currentSession; } String requestedSessionId = getRequestedSessionId(); if(requestedSessionId != null) { S session = sessionRepository.getSession(requestedSessionId); if(session != null) { this.requestedSessionIdValid = true; currentSession = new HttpSessionWrapper(session, getServletContext()); currentSession.setNew(false); return currentSession; } } if(!create) { return null; } S session = sessionRepository.createSession(); currentSession = new HttpSessionWrapper(session, getServletContext()); return currentSession; } @Override public HttpSession getSession() { return getSession(true); } }

Spring Session定義了SessionRepositoryFilter,它實現了 Servlet Filter接口。我抽取了這個filter的關鍵部分,將其列在下面的代碼片斷中,我還添加了一些註釋,用來在本文中闡述這些代碼,因此,一樣的,請閱讀下面代碼的註釋部分。

/* * SessionRepositoryFilter只是一個標準的ServletFilter, * 它的實現擴展了一個helper基類。 */ public class SessionRepositoryFilter < S extends ExpiringSession > extends OncePerRequestFilter { /* * 這個方法是魔力真正發揮做用的地方。這個方法建立了 * 咱們上文所述的封裝請求對象和 * 一個封裝的響應對象,而後調用其他的filter鏈。 * 這裏,關鍵在於當這個filter後面的應用代碼執行時, * 若是要得到session的話,獲得的將會是Spring Session的 * HttpServletSession實例,它是由後端的外部數據存儲做爲支撐的。 */ protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository); SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request,response,servletContext); SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest, response); HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse); HttpServletResponse strategyResponse = httpSessionStrategy.wrapResponse(wrappedRequest, wrappedResponse); try { filterChain.doFilter(strategyRequest, strategyResponse); } finally { wrappedRequest.commitSession(); } } } 

咱們從這一章節獲得的關鍵信息是,Spring Session對HTTP的支持所依靠的是一個簡單老式的ServletFilter,藉助servlet規範中標準的特性來實現Spring Session的功能。所以,咱們可以讓已有的war文件使用Spring Session的功能,而無需修改已有的代碼,固然若是你使用javax.servlet.http.HttpSessionListener的話,就另當別論了。Spring Session 1.0並不支持HttpSessionListener ,可是Spring Session 1.1 M1發佈版本已經添加了對它的支持,你能夠經過該地址瞭解更多細節信息。

配置Spring Session

在Web項目中配置Spring Session分爲四步:

  • 搭建用於Spring Session的數據存儲
  • 將Spring Session的jar文件添加到web應用中
  • 將Spring Session filter添加到web應用的配置中
  • 配置Spring Session如何選擇session數據存儲的鏈接

Spring Session自帶了對Redis的支持。搭建和安裝redis的細節能夠參考該地址

有兩種常見的方式可以完成上述的Spring Session配置步驟。第一種方式是使用Spring Boot來自動配置Spring Session。第二種配置Spring Session的方式是手動完成上述的每個配置步驟。

藉助像Maven或Gradle這樣的依賴管理器,將Spring Session添加應用中是很容易的。若是你使用Maven和Spring Boot的話,那麼能夠在pom.xml中使用以下的依賴:

<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> 

其中,spring-boot-starter-redis依賴可以確保使用redis所需的全部jar都會包含在應用中,因此它們能夠藉助Spring Boot進行自動裝配。spring-session依賴將會引入 Spring Session的jar。

至於Spring Session Servlet filter的配置,能夠經過Spring Boot的自動配置來實現,這隻須要在Spring Boot的配置類上使用 @EnableRedisHttpSession註解就能夠了,以下面的代碼片斷所示。

@SpringBootApplication
@EnableRedisHttpSession
public class ExampleApplication { public static void main(String[] args) { SpringApplication.run(ExampleApplication.class, args); } } 

至於Spring Session到Redis鏈接的配置,能夠添加以下配置到Spring Boot的application.properties文件中:

spring.redis.host=localhost spring.redis.password=secret spring.redis.port=6379 

Spring Boot提供了大量的基礎設施用來配置到Redis的鏈接,定義到Redis數據庫鏈接的各類方式均可以用在這裏。你能夠參考該地址的逐步操做指南,來了解如何使用Spring Session和Spring Boot。

在傳統的web應用中,能夠參考該指南來了解如何經過web.xml來使用Spring Session。

在傳統的war文件中,能夠參考該指南來了解如何不使用web.xml進行配置。

默認狀況下,Spring Session會使用HTTP cookie來存儲session id,可是咱們也能夠配置Spring Session使用自定義的HTTP header信息,如x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3,當構建REST API的時候,這種方式是頗有用的。完整的指南能夠參考該地址

使用Spring Session

Spring Session配置完成以後,咱們就可使用標準的Servlet API與之交互了。例如,以下的代碼定義了一個servlet,它使用標準的Servlet session API來訪問session。

@WebServlet("/example") public class Example extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 使用正常的servlet API獲取session,在底層, // session是經過Spring Session獲得的,而且會存儲到Redis或 // 其餘你所選擇的數據源中 HttpSession session = request.getSession(); String value = session.getAttribute(“someAttribute”); } }

每一個瀏覽器多個Session

Spring Session會爲每一個用戶保留多個session,這是經過使用名爲「_s」的session別名參數實現的。例如,若是到達的請求爲http://example.com/doSomething?_s=0 ,那麼Spring Session將會讀取「_s」參數的值,並經過它肯定這個請求所使用的是默認session。

若是到達的請求是http://example.com/doSomething?_s=1的話,那麼Spring Session就能知道這個請求所要使用的session別名爲1.若是請求沒有指定「_s」參數的話,例如http://example.com/doSomething,那麼Spring Session將其視爲使用默認的session,也就是說_s=0

要爲某個瀏覽器建立新的session,只須要調用javax.servlet.http.HttpServletRequest.getSession()就能夠了,就像咱們一般所作的那樣,Spring Session將會返回正確的session或者按照標準Servlet規範的語義建立一個新的session。下面的表格描述了針對同一個瀏覽器窗口,getSession()面對不一樣url時的行爲。

HTTP請求URL

Session別名

getSession()的行爲

example.com/resource

0

若是存在session與別名0關聯的話,就返回該session,不然的話建立一個新的session並將其與別名0關聯。

example.com/resource?_s=1

1

若是存在session與別名1關聯的話,就返回該session,不然的話建立一個新的session並將其與別名1關聯。

example.com/resource?_s=0

0

若是存在session與別名0關聯的話,就返回該session,不然的話建立一個新的session並將其與別名0關聯。

example.com/resource?_s=abc

abc

若是存在session與別名abc關聯的話,就返回該session,不然的話建立一個新的session並將其與別名abc關聯。

如上面的表格所示,session別名不必定必須是整型,它只須要區別於其餘分配給用戶的session別名就能夠了。可是,整型的session別名多是最易於使用的,Spring Session提供了HttpSessionManager接口,這個接口包含了一些使用session別名的工具方法。

咱們能夠在HttpServletRequest中,經過名爲「org.springframework.session.web.http.HttpSessionManager」的屬性獲取當前的HttpSessionManager。以下的樣例代碼闡述瞭如何獲得HttpSessionManager,而且在樣例註釋中描述了其關鍵方法的行爲。

@WebServlet("/example") public class Example extends HttpServlet { @Override protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { /* * 在請求中,根據名爲org.springframework.session.web.http.HttpSessionManager的key * 得到Spring Session session管理器的引用 */ HttpSessionManager sessionManager=(HttpSessionManager)request.getAttribute( "org.springframework.session.web.http.HttpSessionManager"); /* * 使用session管理器找出所請求session的別名。 * 默認狀況下,session別名會包含在url中,而且請求參數的名稱爲「_s」。 * 例如,http://localhost:8080/example?_s=1 * 將會使以下的代碼打印出「Requested Session Alias is: 1」 */ String requestedSessionAlias=sessionManager.getCurrentSessionAlias(request); System.out.println("Requested Session Alias is: " + requestedSessionAlias); /* 返回一個惟一的session別名id,這個別名目前沒有被瀏覽器用來發送請求。 * 這個方法並不會建立新的session, * 咱們須要調用request.getSession()來建立新session。 */ String newSessionAlias = sessionManager.getNewSessionAlias(request); /* 使用新建立的session別名來創建URL,這個URL將會包含 * 「_s」參數。例如,若是newSessionAlias的值爲2的話, * 那麼以下的方法將會返回「/inbox?_s=2」 */ String encodedURL = sessionManager.encodeURL("/inbox", newSessionAlias); System.out.println(encodedURL); /* 返回session別名與session id所組成的Map, * 它們是由瀏覽器發送請求所造成的。 */ Map < String, String > sessionIds = sessionManager.getSessionIds(request); } }

結論

Spring Session爲企業級Java的session管理帶來了革新,使得以下的任務變得更加容易:

  • 編寫可水平擴展的原生雲應用。
  • 將session所保存的狀態卸載到特定的外部session存儲中,如Redis或Apache Geode中,它們可以以獨立於應用服務器的方式提供高質量的集羣。
  • 當用戶使用WebSocket發送請求的時候,可以保持HttpSession處於活躍狀態。
  • 在非Web請求的處理代碼中,可以訪問session數據,好比在JMS消息的處理代碼中。
  • 支持每一個瀏覽器上使用多個session,這樣就能夠很容易地構建更加豐富的終端用戶體驗。
  • 控制客戶端和服務器端之間如何進行session id的交換,這樣更加易於編寫Restful API,由於它能夠從HTTP 頭信息中獲取session id,而沒必要再依賴於cookie。

若是你想拋棄傳統的重量級應用服務器,但受制於已經使用了這些應用服務器的session集羣特性,那麼Spring Session將是幫助你邁向更加輕量級容器的重要一步,這些輕量級的容器包括Tomcat、Jetty或Undertow。

參考資料

Spring Session項目

Spring Session使用指南

Websocket / HttpSession超時的交互

Webinar播放地址:Introducing Spring Session​

關於做者

Adib Saikali是 Pivotal的高級現場工程師(Senior Field Engineer),對技術和創業充滿熱情,所工做的內容包括組裝JavaScript代碼,給風險資本家撥打不通過預定的電話等等不一而足。在過去的十 多年中,Adib一直使用Spring和Java構建解決方案,目前致力於幫助客戶藉助大數據、PaaS以及敏捷方法論的做用,構建優秀的產品和服務。你 能夠經過twitter聯繫到Adib,他的帳號是@asaikali

查看英文原文Next Generation Session Management with Spring Session

【ArchSummit北京2016】100+研發案例,一塊兒見證60+互聯網公司業務架構年終總結:微軟Sam、領英Kartik、阿里巴巴研究員小邪將展現變革世界的技術,Facebook侯瀟瀟、滴滴技術研究員許令波等大牛將爲咱們演繹高可用架構之道,當即查看詳情>>
相關文章
相關標籤/搜索