Session管理是企業級Java中的一部分。隨着如今的趨勢朝着微服務以及可水平擴展的原生雲應用發展,傳統的session管理逐漸暴露出本身的不足。java
本文闡述spring session API如何革新過去的session管理的不足。先闡述一下當前session管理中的問題,而後深刻介紹Spring session如何解決這些問題的。最後,將會詳細展現Spring session如何運行的,及在項目中怎樣使用它。linux
Spring session帶來的新功能以下,使得以下功能更加容易實現:web
1. 編寫可水平擴展的原生雲應用。redis
2. 將session所保存的狀態卸載到特定的外部session存儲中,如redis或apache geode中,它們可以以獨立於應用服務器的方式提供高質量的集羣。spring
3. 當用戶使用websocket發送請求的時候,可以保持HttpSession處於活躍狀態。數據庫
4. 在非Web請求的處理代碼中,可以訪問session數據,好比在非JMS消息的處理代碼中。apache
5. 支持每一個瀏覽器上使用多個session, 從而可以很容易地構建更加豐富的終端用戶體驗。後端
6. 控制session id如何在客戶端和服務器之間進行交換,這樣的話就能很容易地編寫Restful API, 由於它 能夠從HTTP頭信息中獲取session id, 而沒必要在依賴於cookie。瀏覽器
7. 須要說明的很重要的一點是,spring session的核心項目並不依賴於spring框架,因此,咱們甚至可以將其應用於不使用spring框架的項目中。tomcat
1、傳統session管理的問題
傳統的javaEE Session管理會有各類問題,下面以樣例的形式進行闡述。
構建可水平擴展的原生雲應用
在原生雲應用架構中,會假設應用可以進行擴展,這是經過在linux容器中運行更多的應用程序實例實現的,這些容器會位於一個大型的虛擬機池中。例如,咱們能夠很容易地將一個".war「文件部署到位於Cloud Foundry或Heroku的tomcat中,而後在幾秒鐘的時間內就能擴展到100個應用實例,每一個實例能夠有1GB RAM. 咱們還能夠配置雲平臺,基於用戶的需求自動增長和減小應用實例的數量。
在不少的應用服務器中,都會將http session狀態保存在jvm中,這個jvm與運行應用程序代碼的jvm是同一個,由於這樣易於實現,而且速度很快。當新的應用服務器實例加入或離開集羣時,http session會基於現有的應用服務器實例進行從新平衡。在彈性的雲環境中,咱們會用友上百個應用服務器實例,切實例的數量可能在任意時刻增長或減小,這樣的話,咱們就會遇到一些問題:
重平衡http session可能會成爲性能評頸。
爲了存儲大量的session,會須要很大的堆空間,這會致使垃圾收集,從而對性能產生負面影響。
雲基礎設施一般會禁止TCP多播,可是session管理器經常會使用這種機制來發現哪個應用服務器實例加入或離開了集羣。
所以,更爲高效的辦法是將http session狀態保存在獨立的數據存儲中,這個存儲位於運行應用程序代碼的jvm以外。例如,咱們能夠將100 個tomcat實例配置爲使用redis來存儲session狀態,當tomcat實例增長或減小的時候,redis中所存儲的session並不會受到影響。同時,由於redis是使用C語言編寫的,全部它 可使用上百GB甚至TB 級別的RAM,它不會涉及到垃圾收集的問題。
對於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可能會有兩個帳戶thedude@example.com, jeff@example.com。 和其餘java Web應用同樣,咱們會使用httpsession來跟蹤應用的狀態,如當前登陸的用戶。因此,當用戶但願從thedude@example.com切換到jeff@example.com時,他必需要首先退出,而後再從新登錄回來。
藉助spring session,爲每一個用戶配置多個http session會很是容易,這樣用戶在兩個帳戶之間切換的時候,就不須要退出和從新登陸了。
多級別的安全預覽
假設咱們正在構建的web應用有一個複雜、自定義的權限功能,其中應用的UI會基於用戶所授予的角色和權限實現自適應。
例如,假設應用有4個安全級別:public、confidential、secret和top secret. 當用戶登陸應用以後,系統會判斷用戶所具備的最高安全級別而且只會顯示該級別和該級別之下的數據。因此,具備public權限的用戶只能看到public級別的文檔,具備secret權限的用戶可以看到public、confidentail和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應用,那麼他們可使用H5上的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, 因此咱們必需要以一種自定義的方案來獲取httpsession中的數據,這要經過自定義的機制來實現。
經過使用Spring Session,只要咱們可以知道session的id,就能夠在應用的任意線程中訪問Spring Session。所以,Spring Session具有比Servlet HTTP session管理器更爲豐富的API,只要知道了session id,咱們就能獲取任意特定的session。例如,在一個傳入的消息中可能會包含用戶id的header信息,藉助它,咱們就能夠直接獲取session了。
2、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接口以及兩個默認實現,即CookieHttpSessionStrategy和HeaderHttpSessionStrategy,其中前者使用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.HttpServletRequest的getSession()方法時,都會返回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();
}
}
每一個瀏覽器多個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[也稱之爲password]
* 得到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。
-------------------------------------