摘要:本文介紹了如何在Spring中配置redis,,并通過(guò)Spring中AOP的思想,將緩存的方法切入到有需要進(jìn)入緩存的類或方法前面,。 一,、Redis介紹什么是Redis? redis是一個(gè)key-value存儲(chǔ)系統(tǒng),。和Memcached類似,,它支持存儲(chǔ)的value類型相對(duì)更多,包括string(字符串),、list(鏈表),、set(集合)、zset(sorted set –有序集合)和hash(哈希類型),。這些數(shù)據(jù)類型都支持push/pop,、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的,。在此基礎(chǔ)上,,redis支持各種不同方式的排序。與memcached一樣,,為了保證效率,,數(shù)據(jù)都是緩存在內(nèi)存中。區(qū)別的是redis會(huì)周期性的把更新的數(shù)據(jù)寫(xiě)入磁盤(pán)或者把修改操作寫(xiě)入追加的記錄文件,,并且在此基礎(chǔ)上實(shí)現(xiàn)了master-slave(主從)同步,。 它有什么特點(diǎn)? (1)Redis數(shù)據(jù)庫(kù)完全在內(nèi)存中,,使用磁盤(pán)僅用于持久性,。 Redis 優(yōu)勢(shì),? (1)異??焖伲篟edis的速度非常快,,每秒能執(zhí)行約11萬(wàn)集合,,每秒約81000+條記錄。 Redis 缺點(diǎn),? (1)單線程 (2)耗內(nèi)存 二,、使用實(shí)例本文使用maven+eclipse+sping 1、引入jar包 dependency> groupId>org.springframework.datagroupId> artifactId>spring-data-redisartifactId> version>1.6.1.RELEASEversion> dependency> dependency> groupId>redis.clientsgroupId> artifactId>jedisartifactId> version>2.7.3version> dependency> 2,、配置bean 在application.xml加入如下配置 bean id='poolConfig' class='redis.clients.jedis.JedisPoolConfig' > property name='maxIdle' value='${redis.maxIdle}' /> property name='maxWaitMillis' value='${redis.maxWait}' /> property name='testOnBorrow' value='${redis.testOnBorrow}' /> bean > bean id='connectionFactory' class='org.springframework.data.redis.connection.jedis.JedisConnectionFactory' > property name='poolConfig' ref='poolConfig' /> property name='port' value='${redis.port}' /> property name='hostName' value='${redis.host}' /> property name='password' value='${redis.password}' /> property name='timeout' value='${redis.timeout}' >property> bean > bean id='redisTemplate' class='org.springframework.data.redis.core.RedisTemplate' > property name='connectionFactory' ref='connectionFactory' /> property name='keySerializer' > bean class='org.springframework.data.redis.serializer.StringRedisSerializer' /> property> property name='valueSerializer' > bean class='org.springframework.data.redis.serializer.JdkSerializationRedisSerializer' /> property> bean > bean id='methodCacheInterceptor' class='com.mucfc.msm.common.MethodCacheInterceptor' > property name='redisUtil' ref='redisUtil' /> bean > bean id='redisUtil' class='com.mucfc.msm.common.RedisUtil' > property name='redisTemplate' ref='redisTemplate' /> bean > 其中配置文件redis一些配置數(shù)據(jù)redis.properties如下: #redis中心redis.host=10.75.202.11redis.port=6379redis.password=123456redis.maxIdle=100redis.maxActive=300redis.maxWait=1000redis.testOnBorrow=trueredis.timeout=100000# 不需要加入緩存的類targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager# 不需要緩存的方法methodNames=#設(shè)置緩存失效時(shí)間com.service.impl.xxxRecordManager= 60com.service.impl.xxxSetRecordManager= 60defaultCacheExpireTime=3600fep.local.cache.capacity =10000 要掃這些properties文件,,在application.xml加入如下配置 bean id='propertyConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'> property name='locations'> list> value>classpath:properties/*.propertiesvalue> list> property> bean> 3,、一些工具類 (1)RedisUtil 上面的bean中,,RedisUtil是用來(lái)緩存和去除數(shù)據(jù)的實(shí)例 package com.mucfc.msm.common;import java.io.Serializable;import java.util.Set;import java.util.concurrent.TimeUnit;import org.apache.log4j.Logger;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;/** * redis cache 工具類 * */public final class RedisUtil { private Logger logger = Logger.getLogger(RedisUtil.class); private RedisTemplate (2)MethodCacheInterceptor 切面MethodCacheInterceptor,這是用來(lái)給不同的方法來(lái)加入判斷如果緩存存在數(shù)據(jù),,從緩存取數(shù)據(jù),。否則第一次從數(shù)據(jù)庫(kù)取,并將結(jié)果保存到緩存 中去,。 package com.mucfc.msm.common;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import java.util.Properties;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.apache.log4j.Logger;public class MethodCacheInterceptor implements MethodInterceptor { private Logger logger = Logger.getLogger(MethodCacheInterceptor.class); private RedisUtil redisUtil; private List 4、配置需要緩存的類或方法 在application.xml加入如下配置,,有多個(gè)類或方法可以配置多個(gè) bean id='methodCachePointCut' class='org.springframework.aop.support.RegexpMethodPointcutAdvisor' > property name='advice' > ref local='methodCacheInterceptor' /> property> property name='patterns' > list> value>com\.mucfc\.msm\.service\.impl\...*ServiceImpl.*value > list> property> bean > 5,、執(zhí)行結(jié)果: 寫(xiě)了一個(gè)簡(jiǎn)單的單元測(cè)試如下: @Test public void getSettUnitBySettUnitIdTest() { String systemId = 'CES'; String merchantId = '133'; SettUnit configSettUnit = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, 'ESP'); SettUnit configSettUnit1 = settUnitService.getSettUnitBySettUnitId(systemId, merchantId, 'ESP'); boolean flag= (configSettUnit == configSettUnit1); System.out.println(configSettUnit); logger.info('查找結(jié)果' + configSettUnit.getBusinessType()); // localSecondFIFOCache.put('configSettUnit', configSettUnit.getBusinessType()); // String string = localSecondFIFOCache.get('configSettUnit');// logger.info('查找結(jié)果' + string); } 這是第一次執(zhí)行單元測(cè)試的過(guò)程: MethodCacheInterceptor這個(gè)類中打了斷點(diǎn),然后每次查詢前都會(huì)先進(jìn)入這個(gè)方法 依次運(yùn)行,,發(fā)現(xiàn)沒(méi)有緩存,,所以會(huì)直接去查數(shù)據(jù)庫(kù) 打印了出來(lái)的SQL語(yǔ)句: 第二次執(zhí)行: 因?yàn)榈谝淮螆?zhí)行時(shí),已經(jīng)寫(xiě)入緩存了,。所以第二次直接從緩存中取數(shù)據(jù) 3,、取兩次的結(jié)果進(jìn)行地址的對(duì)比: 發(fā)現(xiàn)兩個(gè)不是同一個(gè)對(duì)象,沒(méi)錯(cuò),,是對(duì)的,。如果是使用Ehcache的話,那么二者的內(nèi)存地址會(huì)是一樣的。那是因?yàn)閞edis和ehcache使用的緩存機(jī)制是不一樣的,。ehcache是基于本地電腦的內(nèi)存使用緩存,,所以使用緩存取數(shù)據(jù)時(shí)直接在本地電腦上取。轉(zhuǎn)換成java對(duì)象就會(huì)是同一個(gè)內(nèi)存地址,,而redis它是在裝有redis服務(wù)的電腦上(一般是另一臺(tái)電腦),,所以取數(shù)據(jù)時(shí)經(jīng)過(guò)傳輸?shù)奖镜兀瑫?huì)對(duì)應(yīng)到不同的內(nèi)存地址,,所以用==來(lái)比較會(huì)返回false,。但是它確實(shí)是從緩存中去取的,這點(diǎn)我們從上面的斷點(diǎn)可以看到,。 |
|