最近项目中用到了redis实现session共享和缓存存储,那么实现这两点并不难,网上也有大量的例子,那么问题在于两者如何能够分别保存在不同的redis中,以方便管理呢。


首先先说如何实现session共享和缓存存储


1.引入架包

<dependency>
				<groupId>redis.clients</groupId>
				<artifactId>jedis</artifactId>
				<version>2.7.3</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.data</groupId>
				<artifactId>spring-data-redis</artifactId>
				<version>1.6.0.RELEASE</version>
			</dependency>



2.添加配置文件


添加数据源和连接工厂,这里我用了集群


<!-- 连接池相关配置信息 -->
	<bean id="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.pool.maxTotal}" />
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<property name="minIdle" value="${redis.pool.minIdle}" />
		<property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}" />
		<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
		<property name="testOnReturn" value="${redis.pool.testOnReturn}" />
	</bean>

	<!-- Sentinel配置信息 -->
	<bean id="redisSentinelConf"
		class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
		<property name="master">
			<bean class="org.springframework.data.redis.connection.RedisNode">
				<property name="name" value="myMaster" />
			</bean>
		</property>
		<property name="sentinels">
			<set>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel.01.host}" />
					<constructor-arg name="port" value="${redis.sentinel.01.port}" />
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel.02.host}" />
					<constructor-arg name="port" value="${redis.sentinel.02.port}" />
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel.03.host}" />
					<constructor-arg name="port" value="${redis.sentinel.03.port}" />
				</bean>
				<bean class="org.springframework.data.redis.connection.RedisNode">
					<constructor-arg name="host" value="${redis.sentinel.04.host}" />
					<constructor-arg name="port" value="${redis.sentinel.04.port}" />
				</bean>
			</set>
		</property>
	</bean>

	<!-- redis连接工厂配置 -->
	<bean id="redisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<constructor-arg name="sentinelConfig" ref="redisSentinelConf" />
		<constructor-arg name="poolConfig" ref="redisPoolConfig" />
		<property name="usePool" value="true" />
		<property name="password" value="${redis.password}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="database" value="${redis.default.db}" />
	</bean>

	<!-- redis模板配置,默认key和value均为stringSerializer序列化方式 -->
	<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
		<property name="connectionFactory" ref="redisConnectionFactory" />
		<!-- 事务配置,设置为true支持绑定连接执行事务内的命令 -->
		<property name="enableTransactionSupport" value="false" />
	</bean>



3.将session交给redis管理


<bean
		class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
		<property name="maxInactiveIntervalInSeconds" value="1800" />
	</bean>

配置以上几步就可以实现将session存放在redis中,实现session共享了


4.缓存存储



需要自定义一个工具类



@qualifier()中为我们在上面配置redis模板bean的id



@Qualifier("redisTemplate")
	public RedisTemplate redisTemplate;
/**
	 * 缓存基本的对象,Integer、String、实体类等
	 * 
	 * @param key
	 *            缓存的键值
	 * @param value
	 *            缓存的值
	 * @return 缓存的对象
	 */
	public <T> ValueOperations<String, T> setCacheObject(String key, T value) {

		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value);
		return operation;
	}

	/**
	 * 获得缓存的基本对象。
	 * 
	 * @param key
	 *            缓存键值
	 * @param operation
	 * @return 缓存键值对应的数据
	 */
	public <T> T getCacheObject(String key/* ,ValueOperations<String,T> operation */) {
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		return operation.get(key);
	}

具体可根据自己需求写。











以上就是全部配置,但是经过测试发现session和我们写入的数据会保存在一起,这样并不方便我们进行管理,那么解决的方法就是再配置一个数据源,让session和缓存保存在不同的数据源中。



5.配置多数据源


配置第二个连接工厂,用于存储session,我这里只有一个redis服务器,所以只好换个database


<bean id="sessionredisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<constructor-arg name="sentinelConfig" ref="redisSentinelConf" />
		<constructor-arg name="poolConfig" ref="redisPoolConfig" />
		<property name="usePool" value="true" />
		<property name="password" value="${redis.password}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="database" value="1" />
	</bean>



使用@EnableRedisHttpSession


@Configuration
@EnableRedisHttpSession
public class SessionConfig {
	private static final Logger logger=LoggerFactory.getLogger(SessionConfig.class);
	
	@Bean
	public JedisConnectionFactory connectionFactory(@Qualifier("sessionredisConnectionFactory") JedisConnectionFactory factory)
	{
		JedisConnectionFactory connection = new JedisConnectionFactory();
		connection=factory;
		if(connection!=null){
			logger.info("session_jedisConnectionFactory加载成功.........");
		}
		return connection;
	}
	
}



在这个方法中我们用@Qualifier指定了redis连接工厂,这样session就是找到指定的数据源实现存储,



当然第三步中的配置就要删掉了



再将这个类引入配置文件中,当然如果用了包扫描那就不用引入了。



还有另外一种方法,不使用@EnableRedisHttpSession标签


我们在第三步中配置的

<bean
		class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
		<property name="maxInactiveIntervalInSeconds" value="1800" />
	</bean>

无法使用多数据源是因为这个类中没有为其指定连接工厂和模板

那么我们只需要重写这个类中的部分方法,同样用@Qualifier指定连接工厂和模板,然后将其引入到配置文件中即可