javascript
使用Spring Session和JDBC DataStore进行会话管理
在Web應用程序中,用戶會話管理對于管理用戶狀態至關重要。 在本文中,我們將學習在集群環境中管理用戶會話所遵循的方法,以及如何使用Spring Session以更加簡單和可擴展的方式實現它。
通常在生產環境中,我們將有多個服務器節點,并在它們前面有一個負載平衡器,并且所有客戶端流量都將通過負載平衡器到達其中一個服務器節點。 因此,我們需要某種機制來使用戶會話數據可用于集群環境中的每個客戶端。
傳統上,我們一直使用以下技術來管理會話:
讓我們簡要地看一下這些方法。
1.單節點服務器
如果您的應用程序不是對企業至關重要的服務,那么并發用戶不會太多,并且可以接受一些停機時間,那么我們可以進行單節點服務器部署,如下所示:
在此模型中,對于每個瀏覽器客戶端,將在服務器上創建會話對象(對于Java,則為HttpSession ),并且SESSION_ID將被設置為瀏覽器上的cookie,以標識會話對象。 但是對于大多數應用程序來說,這種單服務器節點部署是不可接受的,因為如果服務器關閉,服務將完全關閉。
2.具有粘性會話的多節點服務器
為了使我們的應用程序高度可用并滿足更多用戶,我們可以在負載均衡器后面有多個服務器節點。 在“粘性會話”方法中,我們將負載均衡器配置為將所有請求從同一客戶端路由到同一節點。
在此模型中,將在服務器節點中的任何一個上創建用戶會話,并將來自該客戶端的所有其他請求發送到該相同節點。 但是這種方法的問題是,如果服務器節點出現故障,那么該服務器上的所有用戶會話都將消失。
3.具有會話復制的多節點服務器
在此模型中,用戶會話數據將在所有服務器節點上復制,以便可以將任何請求路由到任何服務器節點。 即使一個節點發生故障,客戶端請求也可以由另一節點服務。
但是會話復制需要更好的硬件支持,并涉及某些服務器特定的配置。
4.具有持久數據存儲區中的會話數據的多節點服務器
在此模型中,用戶會話數據將不保存在服務器的內存中,而是將其持久保存到數據存儲中并將其與SESSION_ID關聯。
此解決方案將獨立于服務器,但是每當用戶向其會話中添加一些信息時,我們可能都需要編寫自定義代碼以將會話數據透明地存儲在Persistent數據存儲區中。
這是Spring Session出現的地方。
Spring會議
Spring Session是方法4的實現,它是將會話數據存儲在持久數據存儲區中。 Spring Session支持RDBMS,Redis,HazelCast,MongoDB等多個數據存儲,以透明地保存使用會話數據。 與往常一樣,將Spring Session與Spring Boot一起使用就像添加依賴項和配置少量屬性一樣簡單。
讓我們看看如何在Spring Boot應用程序中將Spring Session與JDBC后端存儲一起使用。
https://github.com/sivaprasadreddy/spring-session-samples
步驟1:創建Spring Boot應用程序
使用具有Web , Thymeleaf , JPA , H2和Session starters的最新版本(撰寫時為2.0.0.RC1 )創建SpringBoot應用程序。
默認情況下,Session入門程序將添加org.springframework.session:spring-session-core依賴項 ,讓我們在使用JDBC后端時將其更改為spring-session- jdbc 。
步驟2:配置Spring Session屬性
我們可以在application.properties使用spring.session.store類型的屬性配置Spring會議后端數據存儲的類型。
spring.session.store-type=jdbc當我們使用H2內存數據庫時,Spring Session將創建以下表,這些表是通過腳本spring-session- jdbc -2.0.1.RELEASE.jar!/ org / springframework / session / jdbc / schema自動存儲會話數據所需的。 -h2.sql 。
CREATE TABLE SPRING_SESSION (PRIMARY_ID CHAR(36) NOT NULL,SESSION_ID CHAR(36) NOT NULL,CREATION_TIME BIGINT NOT NULL,LAST_ACCESS_TIME BIGINT NOT NULL,MAX_INACTIVE_INTERVAL INT NOT NULL,EXPIRY_TIME BIGINT NOT NULL,PRINCIPAL_NAME VARCHAR(100),CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) );CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);CREATE TABLE SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID CHAR(36) NOT NULL,ATTRIBUTE_NAME VARCHAR(200) NOT NULL,ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE );CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_PRIMARY_ID);但是,如果我們要使用其他RDBMS(例如MySQL),則可以進行如下配置:
添加MySQL Maven依賴項。
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId> </dependency>為MySQL配置數據源屬性:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/demo spring.datasource.username=root spring.datasource.password=admin使用spring.session.jdbc.initialize-schema屬性啟用Spring Session表創建。
spring.session.jdbc.initialize-schema=always有了這個屬性,Spring Session將嘗試使用腳本“ classpath:org / springframework / session / jdbc / schema-@@ platform @@。sql”創建表,因此在本例中,它將使用schema-mysql.sql 。
步驟3:將資料新增至HttpSession
現在,在src / main / resources / templates / index.html中創建一個簡單的表單。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head><meta charset="UTF-8"><title>Spring Session + JDBC Demo</title> </head> <body><div><form th:action="@{/messages}" method="post"><textarea name="msg" cols="40" rows="4"></textarea><input type="submit" value="Save"/> </form></div><div><h2>Messages</h2><ul th:each="m : ${messages}"><li th:text="${m}">msg</li></ul></div></body> </html>讓我們實現一個Controller,以將消息添加到HttpSession并顯示它們。
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.*;@Controller public class MessagesController {@GetMapping("/")public String index(Model model, HttpSession session) {List<String> msgs = (List<String>) session.getAttribute("MY_MESSAGES");if(msgs == null) {msgs = new ArrayList<>();}model.addAttribute("messages", msgs);return "index";}@PostMapping("/messages")public String saveMessage(@RequestParam("msg") String msg, HttpServletRequest request) {List<String> msgs = (List<String>) request.getSession().getAttribute("MY_MESSAGES");if(msgs == null) {msgs = new ArrayList<>();request.getSession().setAttribute("MY_MESSAGES", msgs);}msgs.add(msg);return "redirect:/";} }現在,您可以啟動應用程序并將一些消息添加到HttpSession中,并且可以看到SPRING_SESSION , SPRING_SESSION_ATTRIBUTES表中的行。 默認情況下,Spring Session將我們嘗試添加到HttpSession的對象轉換為ByteArray并將其存儲在表中。
Spring SecuritySpring會議
由于SpringBoot的自動配置, Spring Session與Spring Security無縫集成。
讓我們將Spring Security添加到我們的應用程序中。
在application.properties中添加默認用戶憑據,如下所示:
spring.security.user.name=admin spring.security.user.password=secret 現在,如果您嘗試訪問http:// localhost:8080 /,您將被重定向到自動生成的登錄頁面。
登錄并查看SPRING_SESSION表中的數據后,您可以看到登錄用戶名存儲在PRINCIPAL_NAME列中。
Spring Session如何工作?
Spring Session提供了HttpServletRequest和HttpSession的實現,分別是SessionRepositoryRequestWrapper和HttpSessionWrapper 。 Spring Session提供SessionRepositoryFilter來攔截所有請求,并將HttpServletRequest包裝在SessionRepositoryRequestWrapper中 。
在SessionRepositoryRequestWrapper.getSession(boolean)中,它被重寫以返回HttpSessionWrapper對象,而不是默認的HttpSession服務器實現。 HttpSessionWrapper使用SessionRepository將會話信息保存在數據存儲中。
SessionRepository接口具有多種管理會話的方法。
public interface SessionRepository<S extends Session> {S createSession();void save(S session);S findById(String id);void deleteById(String id); }這個SessionRepository接口由各種類根據我們使用的后端類型實現。 在本例中,我們使用的是spring-session-jdbc提供的JdbcOperationsSessionRepository 。
結論
如您可能已經觀察到的,由于Spring Boot的自動配置,我們可以通過使用Spring Session進行非常少的配置來有效地管理用戶會話。 如果由于某種原因我們想將后端從JDBC更改為Redis或Hazelcast等,那只是簡單的配置更改,因為我們不直接依賴于任何Spring Session類。
您可以在https://github.com/sivaprasadreddy/spring-session-samples中找到本文的源代碼。
翻譯自: https://www.javacodegeeks.com/2018/02/session-management-using-spring-session-jdbc-datastore.html
總結
以上是生活随笔為你收集整理的使用Spring Session和JDBC DataStore进行会话管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外星人台式电脑显卡型号(外星人台式机的显
- 下一篇: 跑来跑去:假人与AWS Lambda的第