Spring Session的理解

問題描述

於學期末有一個大實驗,要求使用Java相關技術,計劃採用AngularJSSpringBoot開發。html

爲了提升開發效率,特意在後臺啓用Spring Data REST,少寫了不少增刪改查,不得不感嘆SpringBoot是真的厲害,只在配置文件中加入如下的配置,而後就在配置的url上生成了相應實體的增刪改查、分頁排序接口。前端

spring:
  data:
    rest:
      base-path: /data

除了基礎的代碼以外,登陸也是一大問題,先後臺分離如何進行用戶認證呢?java

用戶認證

學習了潘老師的教程以後,對Springsession管理也是有了必定了解。git

HTTP

HTTP is stateless: But while the core of HTTP itself is stateless, HTTP cookies allow the use of stateful sessions. Using header extensibility, HTTP Cookies are added to the workflow, allowing session creation on each HTTP request to share the same context, or the same state.web

HTTP是無狀態的,雖然HTTP自身是無狀態的,可是cookie容許有狀態session的使用。經過使用Header的擴展,cookie被添加到工做流中,這些cookie容許在每個HTTP請求建立會話,去共享上下文,或共享狀態。正則表達式

瀏覽器有cookie,服務器有sessionspring

Session

SpringBoot中,咱們使用依賴注入自動裝配HttpSession,用於管理session數據庫

clipboard.png

可是,Spring的全部組件,包括ControllerServiceComponent默認都是單例模式,那當多用戶請求時,是如何保證這個session,就是當前用戶的session呢?瀏覽器

Servlet

知其然,知其因此然。安全

框架只是咱們提高開發效率的一種方式,沒了框架,咱們同樣能夠寫,只是會造重複的輪子。

Java進入web領域時,全部的開發都是基於Servlet接口的,而咱們常說的Tomcat是一個Servlet容器。

由於經過HTTP協議進行數據通訊,因此經常使用的是HttpServlet抽象類。

clipboard.png

在全部的會話跟蹤技術中,HttpSession對象是最強大和最通用的。

HttpSession對象在用戶第一次訪問網站的時候自動被建立,能夠經過調用HttpServletRequestgetSession方法獲取該對象。

HttpSession getSession();

能夠經過HttpSessionsetAttribute方法將值放入HttpSession,該值存儲在內存中,因此不要往HttpSession中放入太多數據。

void setAttribute(String name, Object value);

login

因此,最原始的寫法就像下面這樣,從HttpServletRequest中獲取HttpSession,並設置屬性。

request.getSession.setAttribute(CommonService.UserId, user.getId());

Apache Tomcat的官方文檔中找到了下面一句話。

public interface HttpSession

Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user.

公共接口 HttpSession

提供一種認證跨頁面或瀏覽Web站點的用戶並存儲用戶相關信息的方式。

因此,我猜測,從cookiesession的綁定,應該是Tomcat爲咱們處理的。

若是請求中沒有cookie,在getSession時建立一個新的session給我。

若是請求中有cookie,在getSession時查詢已有的session,而後把當前cookie對應的session給我。

SpringMVC

SpringMVC中,請求的分發是經過org.springframework.web.servlet.DispatcherServlet完成的。

[dɪˈspætʃə(r)] ['sɜ:vlet]
Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers or HTTP-based remote service exporters. Dispatches to registered handlers for processing a web request, providing convenient mapping and exception handling facilities.

HTTP請求的前端控制器,爲了web ui控制器或者基於HTTP的其餘服務,它爲一個web請求註冊handler,提供了方便的映射與異常處理工具。

由於控制器的方法是被DispatcherServlet所調度的,DispatcherServlet持有請求與響應對象。

因此能夠直接在控制器中注入相關對象。

Spring 參考文檔

能夠直接注入HttpServletRequestHttpSession等對象。

相似下面:

@PostMapping("/test")
public void test(HttpServletRequest request, HttpSession session) {
}

固然,由於request中就有session,因此也能夠在request中獲取session

以上方法確定沒問題,直接在參數列表中注入,確定線程安全。

若是改爲以下寫法,它仍是線程安全的嗎?

@Autowired
private HttpServletRequest request;
@Autowired
private HttpSession session;

@PostMapping("/test")
public void test() {
}

Spring 中獲取 request 的幾種方法,及其線程安全性分析

經測試,是的。Controller是單例,可是Controller是線程安全的。

由於Spring容器在啓動的時候,建立Controller實例,可是HttpServletRequestHttpSession注入的是代理對象,每次請求經過代理對象獲取當前請求的requestsession

因此單例Controller能保證不一樣請求有不一樣的session,而且是線程安全的。

官方是更加推薦使用@Autowired注入HttpSession,由於這樣注入的方式不侷限於控制器內,若是Service中也想用當前的session,也能注入進來。

附加

記得以前對實體中某個屬性設置not null,發現有@Column(nullable = false)@NotNull兩種方法。

今天在看《SpringMVC初學指南時》明白了第二種寫法。

第一種是Hibernate中的,是在插入數據庫時進行驗證。

第二種是SpringMVC支持的JSR(Java規範請求,Java Specification Requests)中的,用於對控制器中接收的對象進行驗證。

因此實際符合需求的是@Column(nullable = false)

@PostMapping("/test")
public void test(@Valid @RequestBody Teacher teacher) {
}

JSR規範約束表

屬性 描述
@AssertFalse boolean屬性必須爲false
@AssertTrue boolean屬性必須爲true
@DecimalMax 該屬性值必須小於等於指定的小數
@DecimalMin 該屬性值必須大於等於指定的小數
@Digits 應用於BigDecimal,約束最大整數與最大小數。
@Future 必須是將來的一個日期
@Past 必須是過去的一個日期
@Max 最大值
@Min 最小值
@NotNull 不爲Null
@Null 必須爲Null
@Pattern 必須匹配該正則表達式
@Size 必須在指定範圍內

總結

書籍,舉世之寶!
感謝河北工業大學的圖書館,有各類於開發有益的書籍,受益良多。
Facebook的全棧工程師,在遇到一個問題時,在亞馬遜上買一本相關書籍,通讀一晚上,而後解決問題。一塊兒加油!
相關文章
相關標籤/搜索