一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 淺談SpringCache與redis集成實現(xiàn)緩存解決方案

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

2021-03-06 11:31宇的季節(jié) Java教程

本篇文章主要介紹了淺談SpringCache與redis集成實現(xiàn)緩存解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

緩存可以說是加速服務響應速度的一種非常有效并且簡單的方式。在緩存領域,有很多知名的框架,如ehcache 、guava、hazelcast等。redis作為key-value型數(shù)據(jù)庫,由于他的這一特性,redis也成為一種流行的數(shù)據(jù)緩存工具。

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

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

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

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

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

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

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

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

那么如何讓臃腫的代碼重回清新的當初呢?

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

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

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

對于配置springcache只需要三步:

第一步:加入相關依賴:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?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> 
        <!-- 這里可以配置多個redis -->
        <bean class="com.cky.rest.utils.rediscache"
           <property name="redistemplate" ref="redistemplate" /> 
           <property name="name" value="content"/> 
           <!-- name對應的名稱要在類或方法的注解中使用 -->
        </bean>
      </set> 
     </property> 
   </bean> 
</beans>

redis.properties文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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 jedis
redis.maxidle=300
#if wait too long ,throw jedisconnectionexception
redis.maxwait=3000
#if true,it will validate before borrow jedis instance,what you get instance is all usefull
redis.testonborrow=true

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

spring對于緩存只是提供了抽象的接口,并且通過接口來調(diào)用功能,沒有具體的實現(xiàn)類,所以需要我們自己實現(xiàn)具體的操作。

在上面配置中可知,每個實現(xiàn)類都會注入一個redistemplate實例,我們就可以通過redistemplate來操作redis

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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;
  }
}

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

1.xxxx.classnotfoundexception 最后發(fā)現(xiàn)是jar下載不完整,把maven本地倉庫的對應jar包文件夾刪除完從新下載就好了

2.xxxx.methodnotfoundexception 這種情況是版本不對,換成第一步中的版本就可以了

springcache中常見注解的使用:

@cacheable注解

最常用的注解,會把被注解方法的返回值緩存。工作原理是:首先在緩存中查找,如果沒有執(zhí)行方法并緩存結(jié)果,然后返回數(shù)據(jù)。此注解的緩存名必須指定,和cachemanager中的caches中的某一個cache的name值相對應。可以使用value或cachenames指定。

如果沒有指定key屬性,spring會使用默認的主鍵生成器產(chǎn)生主鍵。也可以自定義主鍵,在key中可以使用spel表達式。如下:

?
1
2
3
4
@cacheable(cachenames=”content”,key=”#user.userid”)
public user getuser(user user){
  xxxxx
}

可以使用condition屬性,來給緩存添加條件,如下:

?
1
2
@cacheable(cachenames=”content”,key=”#user.userid”,condition=”#user.age<40”)
public user getuser(user user){xxxxx}

@cacheput注解

先執(zhí)行方法,然后將返回值放回緩存。可以用作緩存的更新。

@cacheevict注解

該注解負責從緩存中顯式移除數(shù)據(jù),通常緩存數(shù)據(jù)都有有效期,當過期時數(shù)據(jù)也會被移除。

此注解多了兩個屬性:

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

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

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/chenkeyu/p/8028781.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久久国语露脸精品国产 | 毛片网站观看 | 色婷婷久久综合中文久久一本 | 玩50岁四川熟女大白屁股直播 | 久久久精品日本一区二区三区 | 肉文高h调教 | 久久国产主播福利在线 | 咪咪爱在线视频 | 美女被狂干 | 国产免费久久精品44 | 亚洲六月丁香六月婷婷蜜芽 | 91网红福利精品区一区二 | 日韩在线 在线播放 | 成人在线小视频 | 亚洲精品无码不卡在线观看 | 国产japanese孕妇孕交 | 成人伊人青草久久综合网破解版 | 2021久久 | 美女脱了内裤张开腿亲吻男生 | 每天都要睡男人(nph) | 韩国免费特一级毛片 | 亚洲不卡视频 | 国产青草亚洲香蕉精品久久 | 性欧美13处丶14处 | 毛片在线看网站 | 奇米影视先锋 | 国产精品天天看特色大片不卡 | 千金肉奴隶在线观看 | 免费网站看v片在线香蕉 | 国产麻豆剧果冻传媒影视4934 | 免费看伦理片 | 奇米影视7777 | 女仆色永久免费网站 | 久久中文电影 | 欧美日韩亚洲第一区在线 | 日本老师动漫 | 国产人人草 | 男女肉粗暴进来下面好紧 | 2015小明台湾永久区域免费 | 四虎永久在线精品免费影视 | 999久久精品国产 |