於學期末有一個大實驗,要求使用Java
相關技術,計劃採用AngularJS
與SpringBoot
開發。html
爲了提升開發效率,特意在後臺啓用Spring Data REST
,少寫了不少增刪改查,不得不感嘆SpringBoot
是真的厲害,只在配置文件中加入如下的配置,而後就在配置的url
上生成了相應實體的增刪改查、分頁排序接口。前端
spring: data: rest: base-path: /data
除了基礎的代碼以外,登陸也是一大問題,先後臺分離如何進行用戶認證呢?java
學習了潘老師的教程以後,對Spring
的session
管理也是有了必定了解。git
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
,服務器有session
。spring
在SpringBoot
中,咱們使用依賴注入自動裝配HttpSession
,用於管理session
。數據庫
可是,Spring
的全部組件,包括Controller
、Service
、Component
默認都是單例模式,那當多用戶請求時,是如何保證這個session
,就是當前用戶的session
呢?瀏覽器
知其然,知其因此然。安全
框架只是咱們提高開發效率的一種方式,沒了框架,咱們同樣能夠寫,只是會造重複的輪子。
在Java
進入web
領域時,全部的開發都是基於Servlet
接口的,而咱們常說的Tomcat
是一個Servlet
容器。
由於經過HTTP
協議進行數據通訊,因此經常使用的是HttpServlet
抽象類。
在全部的會話跟蹤技術中,HttpSession
對象是最強大和最通用的。
HttpSession
對象在用戶第一次訪問網站的時候自動被建立,能夠經過調用HttpServletRequest
的getSession
方法獲取該對象。
HttpSession getSession();
能夠經過HttpSession
的setAttribute
方法將值放入HttpSession
,該值存儲在內存中,因此不要往HttpSession
中放入太多數據。
void setAttribute(String name, Object value);
因此,最原始的寫法就像下面這樣,從HttpServletRequest
中獲取HttpSession
,並設置屬性。
request.getSession.setAttribute(CommonService.UserId, user.getId());
在Apache Tomcat
的官方文檔中找到了下面一句話。
public interface HttpSessionProvides 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
站點的用戶並存儲用戶相關信息的方式。
因此,我猜測,從cookie
到session
的綁定,應該是Tomcat
爲咱們處理的。
若是請求中沒有cookie
,在getSession
時建立一個新的session
給我。
若是請求中有cookie
,在getSession
時查詢已有的session
,而後把當前cookie
對應的session
給我。
在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
持有請求與響應對象。
因此能夠直接在控制器中注入相關對象。
能夠直接注入HttpServletRequest
、HttpSession
等對象。
相似下面:
@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
實例,可是HttpServletRequest
和HttpSession
注入的是代理對象,每次請求經過代理對象獲取當前請求的request
或session
。
因此單例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 |
必須在指定範圍內 |
書籍,舉世之寶!
感謝河北工業大學的圖書館,有各類於開發有益的書籍,受益良多。