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

首頁 > 數據庫 > Redis > 正文

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

2020-03-17 12:41:16
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Redis整合Spring結合使用緩存實例,介紹了如何在Spring中配置redis,并通過Spring中AOP的思想,將緩存的方法切入到有需要進入緩存的類或方法前面。需要的朋友可以參考下
 

一、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這個類中打了斷點,然后每次查詢前都會先進入這個方法

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

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

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

打印了出來的SQL語句:

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

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

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

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

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

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



注:相關教程知識閱讀請移步到Redis頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久国产三级电影| 少妇高潮久久77777| 国产亚洲欧美另类中文| 亚洲的天堂在线中文字幕| 久久视频在线看| 国产精品久久久久久久久久久新郎| 国产精品老女人视频| 77777亚洲午夜久久多人| 中文字幕在线观看亚洲| 亚洲福利影片在线| 日本午夜在线亚洲.国产| 57pao国产成人免费| 中文字幕在线成人| 中文字幕亚洲欧美| 中文字幕一精品亚洲无线一区| 久久精品99国产精品酒店日本| 一个人看的www欧美| 欧美色道久久88综合亚洲精品| 欧洲精品在线视频| 亚洲福利视频专区| 91国产精品视频在线| 亚洲a在线播放| 欧美洲成人男女午夜视频| 国产精品亚洲第一区| 中文字幕亚洲第一| 亚洲人成网站色ww在线| 久久影视三级福利片| 国产成人综合精品在线| 日韩欧美成人精品| 最新亚洲国产精品| 亚洲欧美精品suv| 日本精品中文字幕| 7777免费精品视频| 久久成人在线视频| 久久亚洲欧美日韩精品专区| 日韩免费观看在线观看| 国产精品一区二区久久精品| 日韩精品在线电影| 亚洲a中文字幕| 在线观看国产精品91| 国内精品久久久久影院 日本资源| 亚洲综合在线播放| 久久99精品久久久久久青青91| 国产精品丝袜视频| 国产精品天天狠天天看| 精品视频中文字幕| 免费91麻豆精品国产自产在线观看| 精品久久久久人成| 中日韩美女免费视频网站在线观看| 亚洲第一区中文99精品| 美女久久久久久久| 亚洲影院色无极综合| 成人久久久久爱| 亚洲成人av片在线观看| 热久久这里只有精品| 成人午夜在线观看| 久久99精品久久久久久噜噜| 欧美孕妇毛茸茸xxxx| 亚洲国产高清福利视频| 日韩高清免费在线| www.国产精品一二区| 国产成人综合一区二区三区| 久久成人免费视频| 国产精品精品视频一区二区三区| 亚洲欧美国产精品久久久久久久| 国产精品v日韩精品| 欧美电影免费观看| 91视频免费在线| 北条麻妃一区二区在线观看| 久久天天躁狠狠躁夜夜躁| 亚洲精品国产suv| 国产又爽又黄的激情精品视频| 日韩免费精品视频| 国产99久久精品一区二区| 国产精品美女无圣光视频| 91av视频在线播放| 最新亚洲国产精品| 欧美成人免费小视频| 亚洲欧美综合精品久久成人| 国产精品一区二区久久| 国产一区二区日韩精品欧美精品| 成人免费网视频| 久久久久久久久综合| 国产精品久久久久77777| 欧美国产日本高清在线| 欧美国产精品日韩| 国产精品第二页| 欧美激情亚洲国产| 久久久久久亚洲精品不卡| 欧美视频一区二区三区…| 久久国产精品电影| 国产精品第1页| 日韩av在线网页| 成人国产精品日本在线| 91精品国产乱码久久久久久蜜臀| 国产精品日韩在线观看| 欧美成人精品h版在线观看| 蜜臀久久99精品久久久无需会员| 色在人av网站天堂精品| 国产精品99一区| 欧美日韩裸体免费视频| 久久久久久久久久婷婷| 亚洲国产欧美一区二区丝袜黑人| 亚洲欧美在线一区二区| 欧美精品18videos性欧美| 亚洲黄色在线看| 狠狠色狠色综合曰曰| 亚洲欧美国产va在线影院| 国内精品久久久久久影视8| 欧美成人亚洲成人| www.久久久久| 国产精品国产亚洲伊人久久| 亚洲欧美日韩区| 亚洲一级黄色av| 欧美精品成人在线| 国产一区二区三区高清在线观看| 日韩免费观看av| 日韩av一区二区在线观看| 欧洲永久精品大片ww免费漫画| 国产精品专区h在线观看| 欧美最猛性xxxx| 久久久久久国产精品三级玉女聊斋| 亚洲国产另类 国产精品国产免费| 国产精品啪视频| 日韩美女视频中文字幕| 亚洲最大激情中文字幕| 97av在线视频免费播放| 91国内在线视频| 欧美激情视频网址| 久久久久久久久久久91| 亚洲人成电影在线观看天堂色| 欧美午夜激情小视频| 亚洲va男人天堂| 成人欧美一区二区三区黑人孕妇| 久久久这里只有精品视频| 精品激情国产视频| 欧美成人亚洲成人日韩成人| 欧美在线视频网| 欧美福利在线观看| 亚洲成在人线av| 国产精品视频在线观看| 亚洲一区二区三区视频播放| 国产精品久久久久久久天堂| 日韩免费在线看| 精品久久久久久久久久久久久久| 亚洲天堂第一页| 91精品免费看| 精品久久久久久电影| 狠狠干狠狠久久| 日本亚洲欧美三级| 好吊成人免视频| 亚洲免费av网址| 国产综合色香蕉精品| 国产精品一区二区性色av| 日本不卡高字幕在线2019| 国产精品一区二区三区久久| 中文字幕成人在线| 国产成人免费av电影| 日本一欧美一欧美一亚洲视频| 欧美日韩成人在线视频| 国产女人精品视频| 亚洲精品电影在线| 久久精品国产69国产精品亚洲| 久久久亚洲欧洲日产国码aⅴ|