久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Redis整合Spring結(jié)合使用緩存實(shí)例

 spzproot 2016-12-17

摘要:本文介紹了如何在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)僅用于持久性,。
(2)相比許多鍵值數(shù)據(jù)存儲(chǔ),Redis擁有一套較為豐富的數(shù)據(jù)類型,。
(3)Redis可以將數(shù)據(jù)復(fù)制到任意數(shù)量的從服務(wù)器。

Redis 優(yōu)勢(shì),?

(1)異??焖伲篟edis的速度非常快,,每秒能執(zhí)行約11萬(wàn)集合,,每秒約81000+條記錄。
(2)支持豐富的數(shù)據(jù)類型:Redis支持最大多數(shù)開(kāi)發(fā)人員已經(jīng)知道像列表,,集合,,有序集合,散列數(shù)據(jù)類型,。這使得它非常容易解決各種各樣的問(wèn)題,,因?yàn)槲覀冎滥男﹩?wèn)題是可以處理通過(guò)它的數(shù)據(jù)類型更好,。
(3)操作都是原子性:所有Redis操作是原子的,這保證了如果兩個(gè)客戶端同時(shí)訪問(wèn)的Redis服務(wù)器將獲得更新后的值,。
(4)多功能實(shí)用工具:Redis是一個(gè)多實(shí)用的工具,,可以在多個(gè)用例如緩存,消息,,隊(duì)列使用(Redis原生支持發(fā)布/訂閱),,任何短暫的數(shù)據(jù),應(yīng)用程序,,如Web應(yīng)用程序會(huì)話,,網(wǎng)頁(yè)命中計(jì)數(shù)等。

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 redisTemplate; /** * 批量刪除對(duì)應(yīng)的value * * @param keys */ public void remove(final String... keys) { for (String key : keys) { remove(key); } } /** * 批量刪除key * * @param pattern */ public void removePattern(final String pattern) { Set keys = redisTemplate.keys(pattern); if (keys.size() > 0) redisTemplate.delete(keys); } /** * 刪除對(duì)應(yīng)的value * * @param key */ public void remove(final String key) { if (exists(key)) { redisTemplate.delete(key); } } /** * 判斷緩存中是否有對(duì)應(yīng)的value * * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 讀取緩存 * * @param key * @return */ public Object get(final String key) { Object result = null; ValueOperations operations = redisTemplate .opsForValue(); result = operations.get(key); return result; } /** * 寫(xiě)入緩存 * * @param key * @param value * @return */ public boolean set(final String key, Object value) { boolean result = false; try { ValueOperations operations = redisTemplate .opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 寫(xiě)入緩存 * * @param key * @param value * @return */ public boolean set(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations operations = redisTemplate .opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public void setRedisTemplate( RedisTemplate redisTemplate) { this.redisTemplate = 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 targetNamesList; // 不加入緩存的service名稱 private List methodNamesList; // 不加入緩存的方法名稱 private Long defaultCacheExpireTime; // 緩存默認(rèn)的過(guò)期時(shí)間 private Long xxxRecordManagerTime; // private Long xxxSetRecordManagerTime; // /** * 初始化讀取不需要加入緩存的類名和方法名稱 */ public MethodCacheInterceptor() { try { File f = new File('D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties'); //配置文件位置直接被寫(xiě)死,,有需要自己修改下 InputStream in = new FileInputStream(f); // InputStream in = getClass().getClassLoader().getResourceAsStream(// 'D:\\lunaJee-workspace\\msm\\msm_core\\src\\main\\java\\com\\mucfc\\msm\\common\\cacheConf.properties'); Properties p = new Properties(); p.load(in); // 分割字符串 String[] targetNames = p.getProperty('targetNames').split(','); String[] methodNames = p.getProperty('methodNames').split(','); // 加載過(guò)期時(shí)間設(shè)置 defaultCacheExpireTime = Long.valueOf(p.getProperty('defaultCacheExpireTime')); xxxRecordManagerTime = Long.valueOf(p.getProperty('com.service.impl.xxxRecordManager')); xxxSetRecordManagerTime = Long.valueOf(p.getProperty('com.service.impl.xxxSetRecordManager')); // 創(chuàng)建list targetNamesList = new ArrayList(targetNames.length); methodNamesList = new ArrayList(methodNames.length); Integer maxLen = targetNames.length > methodNames.length ? targetNames.length : methodNames.length; // 將不需要緩存的類名和方法名添加到list中 for (int i = 0; i < maxlen;="" i++)="" {="">if (i < targetnames.length)="" {="" targetnameslist.add(targetnames[i]);="" }="">if (i < methodnames.length)="" {="" methodnameslist.add(methodnames[i]);="" }="" }="" }="">catch (Exception e) { e.printStackTrace(); } } @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object value = null; String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); // 不需要緩存的內(nèi)容 //if (!isAddCache(StringUtil.subStrForLastDot(targetName), methodName)) { if (!isAddCache(targetName, methodName)) { // 執(zhí)行方法返回結(jié)果 return invocation.proceed(); } Object[] arguments = invocation.getArguments(); String key = getCacheKey(targetName, methodName, arguments); System.out.println(key); try { // 判斷是否有緩存 if (redisUtil.exists(key)) { return redisUtil.get(key); } // 寫(xiě)入緩存 value = invocation.proceed(); if (value != null) { final String tkey = key; final Object tvalue = value; new Thread(new Runnable() { @Override public void run() { if (tkey.startsWith('com.service.impl.xxxRecordManager')) { redisUtil.set(tkey, tvalue, xxxRecordManagerTime); } else if (tkey.startsWith('com.service.impl.xxxSetRecordManager')) { redisUtil.set(tkey, tvalue, xxxSetRecordManagerTime); } else { redisUtil.set(tkey, tvalue, defaultCacheExpireTime); } } }).start(); } } catch (Exception e) { e.printStackTrace(); if (value == null) { return invocation.proceed(); } } return value; } /** * 是否加入緩存 * * @return */ private boolean isAddCache(String targetName, String methodName) { boolean flag = true; if (targetNamesList.contains(targetName) || methodNamesList.contains(methodName)) { flag = false; } return flag; } /** * 創(chuàng)建緩存key * * @param targetName * @param methodName * @param arguments */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuffer sbu = new StringBuffer(); sbu.append(targetName).append('_').append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length;="" i++)="" {="">'_').append(arguments[i]); } } return sbu.toString(); } public void setRedisUtil(RedisUtil redisUtil) { this.redisUtil = redisUtil; }}

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)可以看到,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多