天天看點

Spring Boot 解決方案 - 會話

Spring Boot 解決方案 - 會話

連接配接無狀态

使用 HTTP 的連接配接是無狀态的,是以為了應對需要狀态的服務例如使用者登入,誕生了适合儲存狀态的設計-會話(session),本文就來探讨一下會話。

會話的使用

Spring Mvc 中使用會話很簡單,在控制器類的方法參數清單中,直接編寫 HttpSession 類型的參數,或者參數清單中編寫 HttpServletRequest 類,然後使用 getSession() 方法擷取會話。

下面是使用會話的簡單例子,第一次通路時會建立一個無資料的會話,是以擷取到的 access 屬性為 null ,而當不是第一次通路時,由于屬性不為 null 會得到 "NOT THE FIRST TIME ACCESS" 。

@RestController

public class DemoController {

private static final String ACCESS = "access";
@RequestMapping("/")
public String index(HttpSession session) { // or `index(HttpServletRequest req)`
    // then `HttpSession session = request.getSession();`
    if (session.getAttribute(ACCESS) == null) {
        session.setAttribute(ACCESS, true);
        return "FIRST TIME ACCESS";
    }
    return "NOT THE FIRST TIME ACCESS";
}           

}

注意:由于用 Mock Mvc 測試擷取不到第一次請求 Cookies,是以無法模拟得到正确結果,請使用浏覽器或者請求工具測試。

常用方法

上面例子展示了會話的簡單使用,其中 HttpSession 接口是 servlet 的标準,而 Spring Mvc 中的會話預設使用 Tomcat 的實作。下面來介紹幾個常用方法,更多方法使用請參考這篇文章。

Object getAttribute(String) 方法用來擷取會話的屬性,若不存在則傳回 null

void setAttribute(String, Object) 方法用來設定會話的屬性

void removeAttribute(String) 方法用來删除會話的屬性

void setMaxInactiveInterval(int) 方法用來設定會話失效時間,機關為秒,設定小于等于零的數則會話永不過期

void invalidate() 手動使會話失效并清理會話資料

會話監聽器

會話的生命周期分别為建立、失效和建立與失效之間,而會話監聽器是為了滿足會話生命周期中觸發相應事件的需要,HttpSessionListener 和 HttpSessionBindingListener 兩個監聽器接口分别滿足了會話的各個生命周期。使用監聽器隻需實作這些接口然後标注 @WebListener 注解即可,下面會有實作的例子。

針對會話的監聽器

HttpSessionListener 接口可以算是針對會話的監聽器接口,因為它的兩個方法分别在會話建立和失效時調用,下面為一個簡單的例子,參數清單中 HttpSessionEvent 類可以用 getSession 擷取會話。

@WebListener

public class SessionListener implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent event) {
    // ...
}
public void sessionDestroyed(HttpSessionEvent event) {
    // ...
}           

針對會話屬性的監聽器

與 HttpSessionListener 監聽器接口接管會話生命周期的建立與失效不同,HttpSessionBindingListener 監聽器接口負責會話屬性的建立與銷毀,下面為該監聽器的簡單例子,參數清單中 HttpSessionBindingEvent 類除了可以用 getSession 擷取會話,最主要的是可用 getName 和 getValue 分别擷取屬性的名字和值。

public class SessionListener implements HttpSessionBindingListener {

public void valueBound(HttpSessionBindingEvent event) {
    // ...
}

public void valueUnbound(HttpSessionBindingEvent event) {
    // ...
}           

使監聽器生效

上面的例子隻是編寫了監聽器的實作,為了使得監聽器在項目裡生效,還必須在啟動類或者配置類上标注 @ServletComponentScan 來掃描這些屬于 servlet 元件的監聽器,例如下面在配置類上啟動 servlet 元件掃描。

@Configuration

@ServletComponentScan // enable scan servlet component

public class ApplicationConf {

// ...           

分布式會話

若是有多台 Web 伺服器提供不同的服務,且要求屬于同一會話,上面的單機會話例子就無法滿足要求,于是就有了分布式會話即可以共享會話資料。

利用 Spring Session 就可以實作分布式會話,而 Spring Session 的實作可依賴關系資料庫或記憶體資料庫,下面例子為 Spring Boot 中導入基于 Redis 實作的 Spring Session 的依賴。

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>           
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>           
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>           

接着在 Spring Boot 的屬性配置檔案中,添加如下的屬性即可,而對于會話的使用和單機會話操作是一樣的。

spring:

session:

store-type: redis           

redis:

host: 127.0.0.1
port: 6379           

會話安全問題

關于會話安全問題,由于了解知識尚淺,暫且不做探讨,後續會補充該部分。

原文位址

https://www.cnblogs.com/linzhehuang/p/10624634.html