亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Redis > 正文

Redis整合Spring結合使用緩存實例

2020-10-28 21:39:52
字體:
來源:轉載
供稿:網友

一、Redis介紹
什么是Redis?
      redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。
它有什么特點?
(1)Redis數據庫完全在內存中,使用磁盤僅用于持久性。
(2)相比許多鍵值數據存儲,Redis擁有一套較為豐富的數據類型。
(3)Redis可以將數據復制到任意數量的從服務器。
Redis 優勢?
 (1)異常快速:Redis的速度非??欤棵肽軋绦屑s11萬集合,每秒約81000+條記錄。
 (2)支持豐富的數據類型:Redis支持最大多數開發人員已經知道像列表,集合,有序集合,散列數據類型。這使得它非常容易解決各種各樣的問題,因為我們知道哪些問題是可以處理通過它的數據類型更好。
(3)操作都是原子性:所有Redis操作是原子的,這保證了如果兩個客戶端同時訪問的Redis服務器將獲得更新后的值。
(4)多功能實用工具:Redis是一個多實用的工具,可以在多個用例如緩存,消息,隊列使用(Redis原生支持發布/訂閱),任何短暫的數據,應用程序,如Web應用程序會話,網頁命中計數等。
Redis 缺點?
(1)單線程
(2)耗內存
二、使用實例
本文使用maven+eclipse+sping
1、引入jar包

  <!--Redis start --> <dependency>   <groupId>org.springframework.data</groupId>   <artifactId>spring-data-redis</artifactId>   <version>1.6.1.RELEASE</version> </dependency> <dependency>   <groupId>redis.clients</groupId>   <artifactId>jedis</artifactId>   <version>2.7.3</version> </dependency>   <!--Redis end --> 

2、配置bean
在application.xml加入如下配置

<!-- jedis 配置 -->   <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 >  <!-- redis服務器中心 -->   <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 >      <!-- cache配置 -->   <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一些配置數據redis.properties如下:

#redis中心 redis.host=10.75.202.11 redis.port=6379 redis.password=123456 redis.maxIdle=100 redis.maxActive=300 redis.maxWait=1000 redis.testOnBorrow=true redis.timeout=100000  # 不需要加入緩存的類 targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager # 不需要緩存的方法 methodNames=  #設置緩存失效時間 com.service.impl.xxxRecordManager= 60 com.service.impl.xxxSetRecordManager= 60 defaultCacheExpireTime=3600  fep.local.cache.capacity =10000 

要掃這些properties文件,在application.xml加入如下配置

 <!-- 引入properties配置文件 -->   <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">   <property name="locations">     <list>       <value>classpath:properties/*.properties</value>       <!--要是有多個配置文件,只需在這里繼續添加即可 -->     </list>   </property> </bean> 

3、一些工具類
(1)RedisUtil
上面的bean中,RedisUtil是用來緩存和去除數據的實例

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<Serializable, Object> redisTemplate;    /**    * 批量刪除對應的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<Serializable> keys = redisTemplate.keys(pattern);     if (keys.size() > 0)       redisTemplate.delete(keys);   }    /**    * 刪除對應的value    *    * @param key    */   public void remove(final String key) {     if (exists(key)) {       redisTemplate.delete(key);     }   }    /**    * 判斷緩存中是否有對應的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<Serializable, Object> operations = redisTemplate         .opsForValue();     result = operations.get(key);     return result;   }    /**    * 寫入緩存    *    * @param key    * @param value    * @return    */   public boolean set(final String key, Object value) {     boolean result = false;     try {       ValueOperations<Serializable, Object> operations = redisTemplate           .opsForValue();       operations.set(key, value);       result = true;     } catch (Exception e) {       e.printStackTrace();     }     return result;   }    /**    * 寫入緩存    *    * @param key    * @param value    * @return    */   public boolean set(final String key, Object value, Long expireTime) {     boolean result = false;     try {       ValueOperations<Serializable, Object> 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<Serializable, Object> redisTemplate) {     this.redisTemplate = redisTemplate;   } } 

(2)MethodCacheInterceptor
切面MethodCacheInterceptor,這是用來給不同的方法來加入判斷如果緩存存在數據,從緩存取數據。否則第一次從數據庫取,并將結果保存到緩存 中去。

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<String> targetNamesList; // 不加入緩存的service名稱   private List<String> methodNamesList; // 不加入緩存的方法名稱   private Long defaultCacheExpireTime; // 緩存默認的過期時間   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");         //配置文件位置直接被寫死,有需要自己修改下        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(",");        // 加載過期時間設置       defaultCacheExpireTime = Long.valueOf(p.getProperty("defaultCacheExpireTime"));       xxxRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxRecordManager"));       xxxSetRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxSetRecordManager"));       // 創建list       targetNamesList = new ArrayList<String>(targetNames.length);       methodNamesList = new ArrayList<String>(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();     // 不需要緩存的內容     //if (!isAddCache(StringUtil.subStrForLastDot(targetName), methodName)) {     if (!isAddCache(targetName, methodName)) {       // 執行方法返回結果       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);       }       // 寫入緩存       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;   }    /**    * 創建緩存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++) {         sbu.append("_").append(arguments[i]);       }     }     return sbu.toString();   }    public void setRedisUtil(RedisUtil redisUtil) {     this.redisUtil = redisUtil;   } } 

4、配置需要緩存的類或方法
在application.xml加入如下配置,有多個類或方法可以配置多個

<!-- 需要加入緩存的類或方法 --> <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、執行結果:
寫了一個簡單的單元測試如下:

@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("查找結果" + configSettUnit.getBusinessType());    // localSecondFIFOCache.put("configSettUnit", configSettUnit.getBusinessType());  // String string = localSecondFIFOCache.get("configSettUnit");    logger.info("查找結果" + string); } 

這是第一次執行單元測試的過程:
MethodCacheInterceptor這個類中打了斷點,然后每次查詢前都會先進入這個方法


依次運行,發現沒有緩存,所以會直接去查數據庫

打印了出來的SQL語句:

第二次執行:
因為第一次執行時,已經寫入緩存了。所以第二次直接從緩存中取數據

3、取兩次的結果進行地址的對比:
發現兩個不是同一個對象,沒錯,是對的。如果是使用ehcache的話,那么二者的內存地址會是一樣的。那是因為redis和ehcache使用的緩存機制是不一樣的。ehcache是基于本地電腦的內存使用緩存,所以使用緩存取數據時直接在本地電腦上取。轉換成java對象就會是同一個內存地址,而redis它是在裝有redis服務的電腦上(一般是另一臺電腦),所以取數據時經過傳輸到本地,會對應到不同的內存地址,所以用==來比較會返回false。但是它確實是從緩存中去取的,這點我們從上面的斷點可以看到。

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品videossex88| 欧美色欧美亚洲高清在线视频| 欧美性猛交xxxx黑人| 国产亚洲视频在线观看| 91高清在线免费观看| 日韩二区三区在线| 欧美日韩性视频| 欧美日韩国产精品一区二区三区四区| 久久久久国色av免费观看性色| 欧美麻豆久久久久久中文| 精品成人69xx.xyz| 91精品国产网站| 亚洲三级免费看| 亚洲综合日韩中文字幕v在线| 夜夜嗨av一区二区三区四区| 91精品久久久久久久久久久久久| 日本一区二区不卡| 国产久一一精品| 久久精品在线播放| 日本最新高清不卡中文字幕| 日韩精品极品视频免费观看| 日韩av有码在线| 亚洲国产精品久久久久秋霞蜜臀| 亚洲国产日韩欧美在线动漫| 欧美性感美女h网站在线观看免费| 日韩欧美第一页| 国产一区二区三区在线观看网站| 91av在线免费观看| 中日韩美女免费视频网站在线观看| 欧美视频免费在线观看| 亚洲xxxx在线| 亚州精品天堂中文字幕| 亚洲色图15p| 国产精品 欧美在线| 91久久久亚洲精品| 亚洲视频欧洲视频| 成人亚洲欧美一区二区三区| 这里只有精品久久| 8x海外华人永久免费日韩内陆视频| 在线播放亚洲激情| 丝袜亚洲另类欧美重口| 国产男女猛烈无遮挡91| 91免费在线视频网站| 日本精品免费一区二区三区| 黑人欧美xxxx| 国产美女精品视频免费观看| 伊人久久男人天堂| 热久久美女精品天天吊色| 国产v综合ⅴ日韩v欧美大片| 亚洲女人天堂色在线7777| 伊人久久久久久久久久| 欧美激情一区二区三区高清视频| 久热在线中文字幕色999舞| 国产97免费视| 日韩在线视频免费观看| 亚洲福利视频专区| 国产亚洲精品激情久久| 成人免费淫片aa视频免费| 91精品国产沙发| 日韩精品在线私人| 日韩成人免费视频| 亚洲iv一区二区三区| 亚洲国产精品一区二区三区| 国产日韩在线播放| 久久久久国色av免费观看性色| 日韩在线视频二区| 国产精品视频中文字幕91| 欧美视频在线观看免费| 欧美巨大黑人极品精男| 欧美不卡视频一区发布| 欧美猛交ⅹxxx乱大交视频| 国产亚洲欧洲高清一区| 欧美成人性生活| 亚洲国产精品资源| 日本精品视频在线播放| 在线性视频日韩欧美| 色妞一区二区三区| 成人午夜在线影院| 97视频免费在线观看| 久久久噜噜噜久久| 日本久久亚洲电影| 久久国产精品网站| 精品国产网站地址| 亚洲九九九在线观看| 国产精品美女久久久久久免费| 日韩欧美在线视频日韩欧美在线视频| 国产一区私人高清影院| 欧美天天综合色影久久精品| 一级做a爰片久久毛片美女图片| 久久国产精品久久久| 欧美色图在线视频| 成人免费在线网址| 欧美精品久久久久久久久久| 日日噜噜噜夜夜爽亚洲精品| 91国自产精品中文字幕亚洲| 亚洲欧美日韩一区在线| 亚洲性av网站| 欧美日韩午夜激情| 日韩中文字幕精品| 国内精品视频久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 欧美性少妇18aaaa视频| 美日韩精品视频免费看| 精品国产电影一区| 久久综合免费视频| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产精品久久久久久影视| 亚洲成在人线av| 国产精品视频99| 最新国产成人av网站网址麻豆| 亚洲欧美成人一区二区在线电影| 国产精品久久久久久久久久三级| 2021久久精品国产99国产精品| 亚洲成人网在线| 久久99久久亚洲国产| 亚洲福利视频免费观看| 美女啪啪无遮挡免费久久网站| 欧美午夜无遮挡| 亚洲成人久久久| 亚洲网站在线观看| 韩国精品美女www爽爽爽视频| 国产日韩欧美视频在线| 欧美日韩成人精品| 国产精品视频导航| 日韩中文在线中文网三级| 精品国偷自产在线视频| 中文字幕一精品亚洲无线一区| 51久久精品夜色国产麻豆| 91精品免费久久久久久久久| 一区二区三区动漫| 91日韩在线播放| 欧美精品在线视频观看| 91久久精品日日躁夜夜躁国产| 78m国产成人精品视频| 51色欧美片视频在线观看| 日韩亚洲一区二区| 日韩精品视频中文在线观看| 欧美日韩国产精品一区| 欧美与黑人午夜性猛交久久久| 中文字幕九色91在线| 精品国产一区二区三区久久狼黑人| 亚洲精品自产拍| 国产精品视频精品视频| 精品欧美激情精品一区| 亚洲国产精品久久久久秋霞不卡| 亚洲精品免费一区二区三区| 久久99国产综合精品女同| 成人黄色午夜影院| 国产一区二区三区18| 亚洲护士老师的毛茸茸最新章节| 欧美放荡办公室videos4k| 久久亚洲国产精品成人av秋霞| 久久影视三级福利片| 姬川优奈aav一区二区| 亚洲第一在线视频| 国产精品露脸av在线| 国产偷亚洲偷欧美偷精品| 色综合亚洲精品激情狠狠| 日韩免费中文字幕| 精品国产欧美成人夜夜嗨| 97久久超碰福利国产精品…| 精品久久久久久久久国产字幕| 日韩电视剧在线观看免费网站| 亚洲综合色激情五月|