1. 程式人生 > 其它 >spring session

spring session

技術標籤:Javajavaspring

文章目錄

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 的形式儲存多個數據。
假設儲存登入資訊的資料 keyuserLoginInfo,那麼語句就是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.propertiesSpringBoot的標準配置檔案,配置一些簡單的屬性,同時,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("/**");
	}
}