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传过来的某些个别的时间戳类型的日期数据。

通过以上设置,我们程序就是支持分布式部署的了,对于分布式部署的方式,可以参考我的其他文章,Nginx+tomcat实现分布式架构及,或者随便搜一下随手一大堆。 在程序通过以上改造后,我们配置分布式系统,无需配置iphash,直接进行轮训访问即可,能够更合理的利用负载,均衡访问资源。

发布了15 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Himly_Zhang/article/details/83543331