spring session
文章目錄
1. Cookie
主要分析服務端 Spring 工程是如何使用 Cookie 的,有讀、寫兩種操作
1.1 讀Cookie
為 Control
HttpServletRequest
引數,通過request.getCookies()
取得cookie
陣列,然後再迴圈遍歷陣列即可系統會自動傳入方法引數所需要的的
HttpServletRequest
物件
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@RestController
public class SongListControl {
//從配置檔案中讀取自定義的配置項
@Value("${song.author}")
private String songAuthor;
@RequestMapping("/songlist")
public Map index(HttpServletRequest request) {
Map returnData = new HashMap();
returnData.put("result", "this is song list");
returnData.put("author", songAuthor);
Cookie[] cookies = request.getCookies ();
returnData.put("cookies", cookies);
return returnData;
}
}
1.2 使用註解讀取 Cookie
必須要知道 cookie 的名字,才可以使用。
為control
類的方法增加一個@CookieValue("xxxx") String xxxx
引數即可,系統會自動解析並傳入同名的 cookie
import org.springframework.web.bind.annotation.CookieValue;
******(省略)******
@RequestMapping("/songlist")
public Map index(@CookieValue("JSESSIONID") String jSessionId) {
Map returnData = new HashMap();
returnData.put("result", "this is song list");
returnData.put("JSESSIONID", jSessionId);
return returnData;
}
如果系統解析不到指定名字的 Cookie,使用此註解就會報錯
1.3 寫 Cookie
為control
類的方法增加一個HttpServletResponse
引數,呼叫response.addCookie()
方法新增Cookie
例項物件。
系統會自動傳入方法引數所需要的HttpServletResponse
物件
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/songlist")
public Map index(HttpServletResponse response) {
Cookie cookie = new Cookie("sessionId", "CookieTestInfo");
//設定的是 cookie 的域名,就是會在哪個域名下生成 cookie 值
cookie.setDomain("*****");
//設定的是 cookie 的路徑,一般就是寫到 / ,不會寫其他路徑的
cookie.setPath("/");
//設定 cookie 的最大存活時間,-1代表隨瀏覽器的有效期
cookie.setMaxAge(-1);
//設定是否只能伺服器修改,瀏覽器端不能修改
cookie.setHttpOnly(false);
response.addCookie(cookie);
return new HashMap();
}
2. Spring Session API
採用 Session 會話機制將使用者ID、登入狀態等重要資訊放在服務端,避免安全隱患
使用會話機制時,Cookie 作為 session id 的載體與客戶端通訊。上面文章中的程式碼中,Cookie 中的 JSESSIONID就是這個作用。
名字為 JSESSIONID 的cookie,是專門用來記錄使用者 session 的。JSESSIONID 是標準的、通用的名字
2.1 讀操作
從HttpServletRequest
物件中取得HttpSession
物件,使用的語句是request.getSession()
。返回的不是陣列而是物件。在 attribute
屬性中用 key --> value
的形式儲存多個數據。
假設儲存登入資訊的資料 key
是userLoginInfo
,那麼語句就是session.getAttribute("userLoginInfo")
。
登入資訊類:
登入資訊例項物件因為要在網路上傳輸,就必須實現序列介面Serializable
,否則會報錯
import java.io.Serializable;
public class UserLoginInfo implements Serializable {
private String userId;
private String userName;
//get、set方法省略
}
操作程式碼
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/songlist")
public Map index(HttpServletRequest request, HttpServletResponse response) {
Map returnData = new HashMap();
//取得 HTTPSession 物件
HttpSession session = request.getSession();
//讀取登入資訊(取出來的為Object型別,要進行強制轉換)
UserLoginInfo userLoginInfo = (UserLoginInfo) session.getAttribute("userLoginInfo");
if (userLoginInfo == null) {
//未登入
} else {
//已登入
}
return new HashMap();
}
2.2 寫操作
假設登入成功,如何記錄登入資訊到 Session 呢?
寫入資訊用setAttribute()
方法
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/loginmock")
public Map loginMock(HttpServletRequest request, HttpServletResponse response) {
UserLoginInfo userLoginInfo = new UserLoginInfo();
userLoginInfo.setUserId("12345");
userLoginInfo.setUserName("hahah");
//取得 HttpSession 物件
HttpSession session = request.getSession();
//寫入登入資訊
session.setAttribute("userLoginInfo", userLoginInfo);
return new HashMap();
}
3. Spring Session 配置
上面程式碼中,沒有涉及 cookie,系統會自動把預設的JSESSIONID
放在預設的cookie
中。但 Cookie 作為 session id 的載體,也可以修改屬性
配置
application.properties
是SpringBoot
的標準配置檔案,配置一些簡單的屬性,同時,Spring Boot
也提供了程式設計式的配置方式,主要用於配置Bean
。
基本格式:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringHttpSessionConfig {
@Bean
public TestBean testBean() {
return new TestBean();
}
}
在類上新增@Configuration
註解,就表示這是一個配置類,系統會自動掃描並處理,在方法上新增@Bean
註解,表示把此方法返回的物件例項註冊成Bean
3.1 Session 配置
3.1.1 依賴庫
<!-- spring session 支援 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
3.1.2 配置類
在類上額外加一個註解:@EnableSpringHttpSession
,開啟session
。然後,註冊兩個Bean
:
CookieSerializer
:讀寫 Cookies 中的 SessionId 資訊MapSessionRepository
:Session 資訊在伺服器上的儲存倉庫
import org.springframework.session.MapSessionRepository;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
import java.util.concurrent.ConcurrentHashMap;
@Configuration
@EnableSpringHttpSession
public class SpringHttpSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("JSESSIONID");
//用正則表示式配置匹配的域名,可以相容 localhost、127.0.0.1 等各種場景
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
serializer.setCookiePath("/");
serializer.setUseHttpOnlyCookie(false);
//最大生命週期的單位是分鐘
serializer.setCookieMaxAge(24*60*60);
return serializer;
}
@Bean
public MapSessionRepository sessionRepository() {
return new MapSessionRepository(new ConcurrentHashMap<>());
}
}
4. Spring Request 攔截器
大量的頁面功能是需要判斷使用者是否登入了
4.1 建立攔截器
攔截器必須實現HandlerInterceptor
介面
三個攔截點:
Controller
方法執行之前。例如是否登入的驗證就是在preHandler()
方法中處理Controller
方法執行之後。例如記錄日誌、統計方法、執行時間等,就要在postHandler
方法中處理- 整個請求完成後。例如統計整個請求的執行時間在
afterCompletion
方法中處理
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class UserInterceptor implements HandlerInterceptor {
//Controller方法執行之前
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//只有返回 true 才會繼續向下執行,返回 false 取消當前請求
return true;
}
//Controller方法執行之後
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//整個請求完成後(包括 Thymeleaf 渲染完畢)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
4.2 實現 WebMvcConfigurer
建立一個類實現WebMvcConfigurer
, 並實現addInterceptors()
方法,,這個步驟用於管理攔截器。
實現類上要加上@Configuration
註解,讓框架能自動掃描並處理
管理攔截器,比較重要的是攔截設定攔截範圍,常用addPathPatterns("/**")
表示攔截所有的 URL,可以呼叫excludePathPatterns()
方法排除某些 URL,例如登入頁本身就不需要登入,需要排除。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfigurerDemo implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptoryRegistry registry) {
//多個攔截器組成一個攔截器鏈
registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**");
}
}