在Spring里集成Redis高速缓冲

       在Spring里引用Redis访问组件是有版本要求的, 最好在http://mvnrepository.com里面找清楚,本人因为这个问题浪费了不少时间, 这里的Spring为4.2, spring-data-redis为1.6.0,以下为pom.xml增加内容:

    
<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>1.6.0.RELEASE</version>
		</dependency>


然后, 在spring配置里面引用以下关于redis的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.1.xsd 
        http://www.springframework.org/schema/mvc         
        http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-4.0.xsd"
        >

	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
		<property name="locations">
			<list>
				<value>classpath:redis-config.properties</value>
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" />   
	</bean>
	
	<!-- 配置JedisPoolConfig实例 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}" />
        <property name="port" value="${redis.port}" />
        <property name="password" value="${redis.passwd}" />
        <property name="database" value="${redis.dbIndex}" />
        <property name="poolConfig" ref="poolConfig" />
    </bean>
    
    <!-- 定义序列化转换器 -->
    <bean id="commonSerializer" class="org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer">
    	<constructor-arg type="java.lang.Class" value="java.lang.Object" index="0"/>
    </bean>
    
    <bean id="jdkSerializer"
      class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
      

    <!-- 配置RedisTemplate -->
    <bean id="defaultRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <property name="defaultSerializer" ref="commonSerializer" />                  
        <!-- 
        <property name="keySerializer" ref="Jackson2JsonRedisSerializer" />
        <property name="hashKeySerializer" ref="Jackson2JsonRedisSerializer" />
        <property name="valueSerializer" ref="Jackson2JsonRedisSerializer" />
        <property name="valueSerializer" ref="Jackson2JsonRedisSerializer" />
        -->
    </bean>
    <!-- 配置RedisTemplate -->
    <bean id="pageTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />        
        <property name="defaultSerializer" ref="commonSerializer" />
        <property name="valueSerializer" ref="pageSerializer" />
    </bean>
    <!-- spring自己的换管理器,这里定义了两个缓存位置名称 ,既注解中的value -->  
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">  
        <property name="caches">  
            <set>  
            	<bean class="com.freestyle.common.spring.redis.MyRedisCache">
            		<constructor-arg name="name" value="default"></constructor-arg>
            		<constructor-arg name="prefix" value="#{null}"> </constructor-arg>
            		<constructor-arg name="redisOperations" ref="defaultRedisTemplate"></constructor-arg>
            		<constructor-arg name="expiration" value="${redis.expiration}"></constructor-arg>
            	</bean>
            	<bean class="com.freestyle.common.spring.redis.MyRedisCache">
            		<constructor-arg name="name" value="pageCache"></constructor-arg>
            		<constructor-arg name="prefix" value="#{null}"> </constructor-arg>
            		<constructor-arg name="redisOperations" ref="pageTemplate"></constructor-arg>
            		<constructor-arg name="expiration" value="${redis.expiration}"></constructor-arg>
            	</bean>
            	
            </set>  
        </property>  
    </bean>

    
    <!-- 注入redisCachemanager -->
	<cache:annotation-driven cache-manager="cacheManager"/> 
    
    <!-- 配置Jedis Pool -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
    	<constructor-arg name="poolConfig" ref="poolConfig" >    		
    	</constructor-arg>
    	<constructor-arg name="host" value="${redis.host}" >    		
    	</constructor-arg>
    	<constructor-arg name="port" value="${redis.port}" type="int">    		
    	</constructor-arg>
    	<constructor-arg name="timeout" value="2000" type="int">    		
    	</constructor-arg>
    	<constructor-arg name="password" value="${redis.passwd}">    		
    	</constructor-arg>
    </bean>
    <bean id="jRedisUtils" class="com.freestyle.common.utils.JRedisUtils">
    	<constructor-arg ref="jedisPool"></constructor-arg>
    	<property name="databaseIndex" value="${redis.dbIndex}"></property>
    </bean>
    <!-- redis config end -->
    

</beans>


需要说明的是由于本人定义的通用分布查询类Page,用默认的Jackson2JsonRedisSerializer无法还原,会发生不能将linkedhashmap转为..Page之类的异常, 所以特地为此写了一个专用 的pageTemplate和一个名为pageCache的Cache。也就是说, cacheManager管理器里面有两组cache,一组名为default,另一组名为pageCache,是专门用于缓冲Page类型的数据。这里说明一下为什么要弄那么麻烦整两组cache出来, 网上配置spring-redis都没有这么复杂, 因为spring-redis集成组件默认是用JdkSerializationRedisSerializer来进行序列化的,而用默认的序列化是没有问题的,而且能处理任何类的转换。但上一篇测试已经证明jdk内置的序列化性能远不及jason json,所以我比较偏向性能优先。


在src/main/resources下建立Redis连接配置文件redis-config.properties,此文件作为参数被spring读入并以${redis.host}这样的表达式给组装bean时引用。

redis.host=127.0.0.1
redis.port=6379  
redis.passwd=yourpassword
redis.dbIndex=0  
redis.maxIdle=300  
redis.maxActive=600 
redis.maxWait=1000 
redis.testOnBorrow=true
#RedisCacheManager用,到期时间(秒)
redis.expiration=1800

配置器,导出一个:

package com.freestyle.common.spring;

import java.lang.reflect.Method;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class MyCachingConfigurerSupport extends CachingConfigurerSupport {

	public MyCachingConfigurerSupport() {
		// TODO Auto-generated constructor stub
	}
	@Bean
	public PageJsonRedisSerializer pageSerializer() {
		PageJsonRedisSerializer lvRet=new PageJsonRedisSerializer();
		return lvRet;
	}
	@Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
        	@Override
            public Object generate(Object target, Method method, Object... objects) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : objects) {
                    sb.append(obj.toString()+"-");
                }
                return sb.toString();
            }
        };
    }

}

自定义Page相关的PageJsonRedisSerializer,重写deserialize,原来GenericJackson2JsonRedisSerializer默认是Object类型的,上面提及的异常就是由于这个引起民的, 所以这里显式指定为Page:

package com.freestyle.common.spring;

import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.freestyle.common.hibernate.dao.support.Page;

public class PageJsonRedisSerializer extends GenericJackson2JsonRedisSerializer {	
	public PageJsonRedisSerializer() {
		// TODO Auto-generated constructor stub
	}

	public PageJsonRedisSerializer(String classPropertyTypeName) {
		super(classPropertyTypeName);
		// TODO Auto-generated constructor stub
	}

	public PageJsonRedisSerializer(ObjectMapper mapper) {
		super(mapper);
	}	
	@Override
	public Page deserialize(byte[] source) throws SerializationException {
		return super.deserialize(source, Page.class);
	}
}

调用:

扫描二维码关注公众号,回复: 2840114 查看本文章
....
@Service
public class QuotedNoteModule extends QuotedNoteModuleP {
	@Cacheable(value="pageCache",keyGenerator="keyGenerator")
	@Override
	public Page getOrderList(CommonReqInqBean pvReq, String pvLogin,Locale pvLocale,boolean pvHidePrice) throws Exception {
		Page lvPage= super.getOrderList(pvReq, pvLogin, pvLocale, pvHidePrice);
		return lvPage;
	}
....


界面出来:


再翻一下第2页,再清除控制台日志, 然后不断切换1,2页, 再看控制台日志输出,已经没有jdbc数据库访问相关的日志了,也就是说,后面的查询数据来源全部来自redis服务器。


再打开redis desktop manager看下缓存的数据:



猜你喜欢

转载自blog.csdn.net/rocklee/article/details/80959161