国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > Java > 正文

淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案

2024-07-13 10:14:43
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

緩存可以說(shuō)是加速服務(wù)響應(yīng)速度的一種非常有效并且簡(jiǎn)單的方式。在緩存領(lǐng)域,有很多知名的框架,如EhCache 、Guava、HazelCast等。Redis作為key-value型數(shù)據(jù)庫(kù),由于他的這一特性,Redis也成為一種流行的數(shù)據(jù)緩存工具。

在傳統(tǒng)方式下對(duì)于緩存的處理代碼是非常臃腫的。

例如:我們要把一個(gè)查詢函數(shù)加入緩存功能,大致需要三步。

一、在函數(shù)執(zhí)行前,我們需要先檢查緩存中是否存在數(shù)據(jù),如果存在則返回緩存數(shù)據(jù)

二、如果不存在,就需要在數(shù)據(jù)庫(kù)的數(shù)據(jù)查詢出來(lái)。

三、最后把數(shù)據(jù)存放在緩存中,當(dāng)下次調(diào)用此函數(shù)時(shí),就可以直接使用緩存數(shù)據(jù),減輕了數(shù)據(jù)庫(kù)壓力。

那么實(shí)現(xiàn)上面的三步需要多少代碼呢?下面是一個(gè)示例:

SpringCache,集成,redis緩存,redis,緩存   

上圖中的紅色部分都是模板代碼,真正與這個(gè)函數(shù)有關(guān)的代碼卻只占了1/5,對(duì)于所有需要實(shí)現(xiàn)緩存功能的函數(shù),都需要加上臃腫的模板代碼??芍^是一種極不優(yōu)雅的解決方案。

那么如何讓臃腫的代碼重回清新的當(dāng)初呢?

AOP不就是專門解決這種模板式代碼的最佳方案嗎,幸運(yùn)的是我們不需要再自己實(shí)現(xiàn)切面了,SpringCache已經(jīng)為我們提供好了切面,我們只需要進(jìn)行簡(jiǎn)單的配置,就可以重回當(dāng)初了,像下面這樣:

SpringCache,集成,redis緩存,redis,緩存  

只需要加一個(gè)注解就可以了,對(duì)于原來(lái)的代碼連改都不需要改,是不是已經(jīng)躍躍欲試了?

對(duì)于配置SpringCache只需要三步:

第一步:加入相關(guān)依賴:

<dependency>   <groupId>redis.clients</groupId>   <artifactId>jedis</artifactId>   <version>2.9.0</version> </dependency> <dependency>   <groupId>org.springframework.data</groupId>   <artifactId>spring-data-redis</artifactId>   <version>1.6.0.RELEASE</version> </dependency> <dependency>  <groupId>org.apache.commons</groupId>  <artifactId>commons-lang3</artifactId>   <version>3.3.2</version></dependency>

第二步:配置SpringCache,Redis連接等信息

applicationContext-redis.xml

<?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:p="http://www.springframework.org/schema/p"    xmlns:context="http://www.springframework.org/schema/context"    xmlns:mvc="http://www.springframework.org/schema/mvc"    xmlns:cache="http://www.springframework.org/schema/cache"   xsi:schemaLocation="http://www.springframework.org/schema/beans               http://www.springframework.org/schema/beans/spring-beans-4.2.xsd               http://www.springframework.org/schema/context               http://www.springframework.org/schema/context/spring-context-4.2.xsd               http://www.springframework.org/schema/mvc               http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd             http://www.springframework.org/schema/cache              http://www.springframework.org/schema/cache/spring-cache-4.2.xsd">    <!-- 配置文件加載 -->  <context:property-placeholder location="classpath:*.properties"/><cache:annotation-driven cache-manager="cacheManager"/>  <!-- redis連接池 -->  <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="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"      p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>  <!-- redis模板 -->  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">       <property name="connectionFactory" ref="JedisConnectionFactory" />    </bean>     <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">       <property name="caches">        <set>          <!-- 這里可以配置多個(gè)redis -->         <bean class="com.cky.rest.utils.RedisCache">             <property name="redisTemplate" ref="redisTemplate" />             <property name="name" value="content"/>             <!-- name對(duì)應(yīng)的名稱要在類或方法的注解中使用 -->         </bean>       </set>       </property>     </bean>  </beans>

redis.properties文件:

# Redis settings # server IP redis.host=192.168.100.55 # server port redis.port=6379 # server pass redis.pass=# use dbIndex redis.database=0 #max idel instance of jedisredis.maxIdle=300 #if wait too long ,throw JedisConnectionExceptionredis.maxWait=3000 #if true,it will validate before borrow jedis instance,what you get instance is all usefullredis.testOnBorrow=true 

第三步,編寫Cache接口實(shí)現(xiàn)類

Spring對(duì)于緩存只是提供了抽象的接口,并且通過(guò)接口來(lái)調(diào)用功能,沒(méi)有具體的實(shí)現(xiàn)類,所以需要我們自己實(shí)現(xiàn)具體的操作。

在上面配置中可知,每個(gè)實(shí)現(xiàn)類都會(huì)注入一個(gè)redisTemplate實(shí)例,我們就可以通過(guò)redisTemplate來(lái)操作redis

package com.cky.rest.utils;import java.io.Serializable;import org.apache.commons.lang3.SerializationUtils;import org.springframework.cache.Cache;import org.springframework.cache.support.SimpleValueWrapper;import org.springframework.dao.DataAccessException;import org.springframework.data.redis.connection.RedisConnection;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;public class RedisCache implements Cache {  private RedisTemplate<String, Object> redisTemplate;  private String name;  @Override  public void clear() {    System.out.println("-------緩存清理------");    redisTemplate.execute(new RedisCallback<String>() {      @Override      public String doInRedis(RedisConnection connection) throws DataAccessException {        connection.flushDb();        return "ok";      }    });  }  @Override  public void evict(Object key) {    System.out.println("-------緩存刪除------");    final String keyf=key.toString();    redisTemplate.execute(new RedisCallback<Long>() {      @Override      public Long doInRedis(RedisConnection connection) throws DataAccessException {        return connection.del(keyf.getBytes());      }          });  }  @Override  public ValueWrapper get(Object key) {    System.out.println("------緩存獲取-------"+key.toString());    final String keyf = key.toString();    Object object = null;    object = redisTemplate.execute(new RedisCallback<Object>() {      @Override      public Object doInRedis(RedisConnection connection) throws DataAccessException {        byte[] key = keyf.getBytes();        byte[] value = connection.get(key);        if (value == null) {          System.out.println("------緩存不存在-------");          return null;        }        return SerializationUtils.deserialize(value);      }    });    ValueWrapper obj=(object != null ? new SimpleValueWrapper(object) : null);    System.out.println("------獲取到內(nèi)容-------"+obj);    return obj;  }  @Override  public void put(Object key, Object value) {    System.out.println("-------加入緩存------");    System.out.println("key----:"+key);    System.out.println("key----:"+value);    final String keyString = key.toString();    final Object valuef = value;    final long liveTime = 86400;    redisTemplate.execute(new RedisCallback<Long>() {      @Override      public Long doInRedis(RedisConnection connection) throws DataAccessException {        byte[] keyb = keyString.getBytes();        byte[] valueb = SerializationUtils.serialize((Serializable) valuef);        connection.set(keyb, valueb);        if (liveTime > 0) {          connection.expire(keyb, liveTime);        }        return 1L;      }    });  }    @Override  public <T> T get(Object arg0, Class<T> arg1) {    // TODO Auto-generated method stub    return null;  }    @Override  public String getName() {    return this.name;  }  @Override  public Object getNativeCache() {    return this.redisTemplate;  }    @Override  public ValueWrapper putIfAbsent(Object arg0, Object arg1) {    // TODO Auto-generated method stub    return null;  }  public RedisTemplate<String, Object> getRedisTemplate() {    return redisTemplate;  }  public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {    this.redisTemplate = redisTemplate;  }  public void setName(String name) {    this.name = name;  }}

在配置過(guò)程中曾經(jīng)出現(xiàn)過(guò)兩次錯(cuò)誤:

1.Xxxx.ClassNotFoundException 最后發(fā)現(xiàn)是jar下載不完整,把maven本地倉(cāng)庫(kù)的對(duì)應(yīng)jar包文件夾刪除完從新下載就好了

2.Xxxx.MethodNotFoundException 這種情況是版本不對(duì),換成第一步中的版本就可以了

SpringCache中常見注解的使用:

@Cacheable注解

最常用的注解,會(huì)把被注解方法的返回值緩存。工作原理是:首先在緩存中查找,如果沒(méi)有執(zhí)行方法并緩存結(jié)果,然后返回?cái)?shù)據(jù)。此注解的緩存名必須指定,和cacheManager中的caches中的某一個(gè)Cache的name值相對(duì)應(yīng)。可以使用value或cacheNames指定。

如果沒(méi)有指定key屬性,spring會(huì)使用默認(rèn)的主鍵生成器產(chǎn)生主鍵。也可以自定義主鍵,在key中可以使用SpEL表達(dá)式。如下:

  @Cacheable(cacheNames=”content”,key=”#user.userId”)  Public User getUser(User user){    xxxxx  } 

可以使用condition屬性,來(lái)給緩存添加條件,如下:

@Cacheable(cacheNames=”content”,key=”#user.userId”,condition=”#user.age<40”)Public User getUser(User user){xxxxx}

@CachePut注解

先執(zhí)行方法,然后將返回值放回緩存??梢杂米骶彺娴母?。

@CacheEvict注解

該注解負(fù)責(zé)從緩存中顯式移除數(shù)據(jù),通常緩存數(shù)據(jù)都有有效期,當(dāng)過(guò)期時(shí)數(shù)據(jù)也會(huì)被移除。

此注解多了兩個(gè)屬性:

allEntries是否移除所有緩存條目。

beforeInvocation:在方法調(diào)用前還是調(diào)用后完成移除操作。true/false

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄石市| 上思县| 新乐市| 开原市| 兴业县| 福泉市| 西青区| 安阳县| 大埔区| 密云县| 聂拉木县| 平舆县| 沙田区| 武山县| 交口县| 同心县| 杂多县| 康保县| 朔州市| 东乌珠穆沁旗| 个旧市| 黄平县| 垫江县| 宾川县| 嘉禾县| 静宁县| 沽源县| 辽阳县| 桦甸市| 棋牌| 探索| 拜城县| 汶上县| 荣成市| 克拉玛依市| 谷城县| 龙岩市| 离岛区| 怀集县| 睢宁县| 错那县|