1. 程式人生 > >Spring-session+mongodb實現session共享

Spring-session+mongodb實現session共享

pom.xml配置

首先需要引入依賴包,直接在pom.xml中新增以下程式碼即可。

		<!-- spring-session整合mongodb -->
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-data-mongo</artifactId>
			<version>1.3.3.RELEASE</version>
		</dependency>

這裡使用spring 4.x進行了專案的構建,這裡說明一下,本專案使用spring 4.x進行構建,5.x的配置方式改變,請繞行。根據mavean的官方描述,該引用包含spring-session以及spring-data-mongo,一次性引入

web.xml配置

第一步使用spring-session攔截session,再web.xml中配置攔截器,特別注意,這個攔截器一般來說應該是優先順序最高的,一定放到開頭,攔截配置如下

	<!-- spring-session 注意我的位置,一定要非常靠前-->
	<filter>
		<filter-name>springSessionRepositoryFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</
filter-class
>
</filter> <filter-mapping> <filter-name>springSessionRepositoryFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring-session 結束-->
  1. 還是特別注意 ,一定要配置的很靠前,尤其系統內有使用者登入session校驗的,一定要在其後;

applicationContext.xml 核心配置檔案

首先在檔案頭我們增加mongodb的引用 頭部增加

    xmlns:mongo="http://www.springframework.org/schema/data/mongo"

xsi:schemaLocation中增加

    http://www.springframework.org/schema/data/mongo 
    http://www.springframework.org/schema/data/mongo/spring-mongo.xsd

完整程式碼–我這裡引用了其他的,無視就好

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    	xsi:schemaLocation="
    	http://www.springframework.org/schema/data/mongo 
    	http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-4.0.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

增加mongodb的配置 注意一下這裡Host port等各種引數應該在外部配置檔案中,直接介紹圖方便直接寫在了配置檔案中

    <!-- mongodb資料來源 -->
    <mongo:mongo id="mongo" host="你的mongo的ip地址" port="你的mongo的埠">
    	<mongo:options connections-per-host="8" threads-allowed-to-block-for-connection-multiplier="4"
    		connect-timeout="1000" max-wait-time="1500" auto-connect-retry="true" socket-keep-alive="true" socket-timeout="1500"
    		slave-ok="true" write-number="1" write-timeout="0" write-fsync="true" />
    </mongo:mongo>
    
    <!-- mongo的工廠,通過它來取得mongo例項,testmongo為mongodb的資料庫名,沒有的話會自動建立 -->
    <mongo:db-factory id="mongoDbFactory" dbname="testmongo" mongo-ref="mongo" />
    
    <!-- mongodb的主要操作物件,所有對mongodb的增刪改查的操作都是通過它完成 -->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    	<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    </bean>

增加mongodb對session的託管

    <!-- 將session放入mongo -->
    <bean id="mongoHttpSessionConfiguration"
    	class="org.springframework.session.data.mongo.config.annotation.web.http.MongoHttpSessionConfiguration">
    	<property name="maxInactiveIntervalInSeconds" value="1800" />
    </bean>

在系統中使用session

以上已經配置完畢,我們啟動專案以後登入,會在剛才配置的mongo中自動建立一個名為sesssions的表,使用該語法檢視

db.sessions.find();

在這裡插入圖片描述

session正常已經正常存入了mongo,存入後,接下來涉及系統使用。我們都知道,再獲取session內物件的時候,我們使用session.getAttribute("")方法,如果此時session中僅是存的簡單的key-value格式,那麼到此為止,全部工作已經完成,但是如果session中存放了比較複雜的物件,存了key-object這種,在我們直接通過session.get獲取到內容以後,你會發現他是一個dbobject型別,結構為{aaa=123,bbb=456,ccc=789},這個內容無法直接強制轉換為我們想要的java物件。接下來就要藉助gson先將dbobject轉為jsonstr,再將jsonstr轉為obj

為了方便以後我們對session儲存複雜物件的時候進行操作,我們封裝一個工具類,用於獲取session物件

package com.easternie.newframe.util;

import java.text.DateFormat;
import java.util.Date;

import javax.servlet.http.HttpSession;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * SessionUtil 用於處理是否使用mongodb作為session的快取
 * @author ZhangQiang
 * 注意=如果使用mongo進行seesion共享需要進行以下操作。
 * 1、再pom.xml引入spring-session-data-mongo
 * 2、applicationcontext中引入mongo的jdbc 並將mongo注入session
 * 3、web.xml中增加spring-session的攔截-注意往前放,作為第一道攔截
 */
public class SessionUtils {
	//設定是否開啟Mongo儲存session 如果為true 從mongo中處理,false直接返回session的內容本身
	static Boolean DOMONGOTRACE = true;
	
	public static <T> T getMongoSession(HttpSession session,Class<?> t) {
		return getMongoSession(session,t,null);
	}
	/**
	 * 
	 * @param session - httpsession
	 * @param t - xxx.class
	 * @param className - 注意全字母大寫,session的key理論上裝載以後就要全部大寫
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getMongoSession(HttpSession session,Class<?> t,String className) {
		className = className == null? t.getSimpleName().toUpperCase() : className;
		if(DOMONGOTRACE) {
			Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer()).setDateFormat(DateFormat.LONG).create();
			return (T) gson.fromJson(gson.toJson(session.getAttribute(className)), t);
		}else {
			return (T) session.getAttribute(className);
		}
    	
	}
}

在需要獲取session中的物件的時候我們使用

    User user = SessionUtils.getMongoSession(session, User.class);

這樣就可以輕易獲取到我們存入到session中的物件,注意一下封裝了兩個方法,無className的會自動根據t找名字,另外養成習慣我們插入session中的資料,全部大寫。這樣方便使用t直接找到。如果t的類名和存入session的key值不一致的時候,使用第二個方法。

細心的可能發現,在使用gson處理資料的時候,因為mongodb本身日期型別是和javascript的日期型別保持一致的,所以當我們直接存入java的date型別的時候,資料庫中對直接轉換為long型別的時間戳。那麼在gson進行轉換的時候,發現Longl型別的時間戳轉換為date的時候,就會報錯。 再gson轉換之前,我們先解決一下Long轉date的問題 新建DateDeserializer重寫deserialize方法,程式碼如下

package com.easternie.newframe.util;

import java.lang.reflect.Type;
import java.util.Date;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

/** gson轉換的時候對於Long時間戳型別進行特殊處理
 * @author ZhangQiang
 * @date 2018年10月30日15:02:46
 */
public class DateDeserializer implements JsonDeserializer<Date> {
	@Override
	public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
			throws JsonParseException {
		return new java.util.Date(json.getAsJsonPrimitive().getAsLong());
	}
}

這樣在sessionutils中進行轉換的時候使用該方法進行處理,就不會異常了

Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer()).setDateFormat(DateFormat.LONG).create();

該方法同樣適用於對於前臺js傳過來的某些個別的時間戳型別的日期資料。