SpringBoot緩存注解學(xué)習(xí)筆記之Redis

之前用SpringBoot+MyBatisPlus+SpringMVC整合搭建了一個基礎(chǔ)web開發(fā)框架恳蹲,使用這三個框架搭建出來項目結(jié)構(gòu)非常的清爽查辩,沒有過多的配置文件骏全,各個模塊之間有清晰的聯(lián)系与斤,非常適合敏捷開發(fā)肪康。

最近學(xué)習(xí)了Redis這個基于內(nèi)存的,Key-Value數(shù)據(jù)形式的高性能數(shù)據(jù)庫撩穿,感覺學(xué)習(xí)了入門之后很簡單磷支,沒有體會到它具體能干嘛,我就想著使用Redis這個數(shù)據(jù)庫來整合之前搭建的框架食寡,利用Spring中的緩存機制雾狈,將查詢的信息緩存到Redis中。

抵皱、善榛、、呻畸、移盆、、擂错、味滞、、钮呀、剑鞍、、
個人博客地址:http://z77z.oschina.io/
爽醋,蚁署,,蚂四,光戈,,遂赠,久妆,,跷睦,筷弦,,

安裝Redis

Window 下安裝 下載地址:https://github.com/MSOpenTech/redis/releases。 Redis 支持32 位和64 位烂琴。這個需要根據(jù)你系統(tǒng)平臺的實際情況選擇爹殊,這里我們下載 Redis-x64-xxx.zip壓縮包到 C盤的tools目錄中,解壓后奸绷,將文件夾重新命名為 redis梗夸。

下載Redis版本

打開一個 cmd 窗口 使用cd命令切換目錄到 C:\tools\redis 運行 redis-server.exe redis.windows.conf 。
如果想方便的話号醉,可以把 redis 的路徑加到系統(tǒng)的環(huán)境變量里反症,這樣就省得再輸路徑了,后面的那個 redis.windows.conf 可以省略扣癣,如果省略惰帽,會啟用默認的。輸入之后父虑,會顯示如下界面:

啟動成功后

啟動成功后不要關(guān)閉命令窗口该酗,不然redis服務(wù)也會關(guān)閉。如果不想每次使用都一直開著這個命令窗口士嚎,可以將redis服務(wù)添加到windows的服務(wù)中:

安裝命令:
redis-server.exe --service-install redis.windows.conf --loglevel verbose 

卸載命令:
redis-server --service-uninstall

安裝成功后呜魄,可以在windows的服務(wù)管理中對redis進行管理,就不用每次都打開命令窗口來啟動redis服務(wù)了莱衩,如下圖:

在windows中管理redis服務(wù)

獲取之前項目

環(huán)境我就直接在之前的整合框架上進行搭建爵嗅,之前項目下載地址:https://git.oschina.net/z77z/springboot_mybatisplus
注意:之前搭建這個框架的時候我為了獲取基礎(chǔ)數(shù)據(jù),在啟動springboot的時候也啟動了爬蟲程序笨蚁,如果不想每次啟動都啟動爬蟲可以注釋掉啟動類中的run方法睹晒。

添加Redis依賴到pom.xml中

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

在application.properties中添加配置

# REDIS (RedisProperties)
# Redis數(shù)據(jù)庫索引(默認為0)
spring.redis.database=0
# Redis服務(wù)器地址
spring.redis.host=localhost
# Redis服務(wù)器連接端口
spring.redis.port=6379
# Redis服務(wù)器連接密碼(默認為空)
spring.redis.password=
# 連接池最大連接數(shù)(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=8
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=0
# 連接超時時間(毫秒)
spring.redis.timeout=0

我們需要做的配置到這里就已經(jīng)完成了,Spring Boot會在偵測到存在Redis的依賴并且Redis的配置是可用的情況下括细,使用RedisCacheManager初始化CacheManager伪很。也就是說要使用緩存的話,SpringBoot就會選擇Redis來作為緩存的容器奋单。

編寫一個簡單的redis讀寫測試列

/**
 * redis讀寫測試
 * @author z77z
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisCacheTest {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    
    @Test
    public void redisTest() throws Exception {

        //保存字符串
        stringRedisTemplate.opsForValue().set("aaa", "111");
        //讀取字符串
        String aaa = stringRedisTemplate.opsForValue().get("aaa");
        System.out.println(aaa);
    }
}

打印結(jié)果:

redis讀寫測試結(jié)果

編寫緩存測試列

不使用緩存:

/**
 * 獲取數(shù)據(jù)锉试,并且做緩存處理
 * @author z77z
 *
 */
@Component
public class RedisCache {
    
    @Autowired
    BeautifulPicturesService beautifulPicturesService;
    //@Cacheable(value = "BeautifulPictures")
    public BeautifulPictures getBeautifulPicturesList(String id) {
        return beautifulPicturesService.selectById(id);
    }
}

/**
 * 測試類
 * @author z77z
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisCacheTest {
    @Autowired
    BeautifulPicturesService beautifulPicturesService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    
    @Autowired
    RedisCache redisCache;
    
    @Test
    public void redisTest() throws Exception {

        //保存字符串
        stringRedisTemplate.opsForValue().set("aaa", "111");
        //讀取字符串
        String aaa = stringRedisTemplate.opsForValue().get("aaa");
        System.out.println(aaa);
    }
    
    @Test
    public void CacheTest() {
        BeautifulPictures beautifulPicture = redisCache.getBeautifulPicturesList("1011");
        System.out.println("第一次查詢結(jié)果:");
        System.out.println(beautifulPicture);

        BeautifulPictures beautifulPicture1 = redisCache.getBeautifulPicturesList("1011");
        System.out.println("第二次查詢結(jié)果:");
        System.out.println(beautifulPicture1);
    }
}

執(zhí)行結(jié)果:

不使用緩存測試結(jié)果

可以從日志中看出兩次查詢都是執(zhí)行了sql,也就是執(zhí)行了getBeautifulPicturesList這個方法

使用緩存:

在getBeautifulPicturesList方法的上面添加@Cacheable(value = "BeautifulPictures")注解览濒,當(dāng)請求這個方法時會先判斷緩存中是否存在呆盖,存在就在緩存中獲取,不會執(zhí)行這個方法贷笛。不存在就正常執(zhí)行這個方法獲取返回值并且存如緩存中应又。添加注解后執(zhí)行結(jié)果如下:

添加緩存注釋后

從日志中可以看出,第一次查詢的時候執(zhí)行的sql乏苦,而第二次查詢的時候沒有執(zhí)行sql丁频,說明是從緩存中獲取的數(shù)據(jù)。

緩存數(shù)據(jù)一致性保證

CRUD (Create 創(chuàng)建,Retrieve 讀取席里,Update 更新,Delete 刪除) 操作中拢驾,除了 R具備冪等性奖磁,其他三個發(fā)生的時候都可能會造成緩存結(jié)果和數(shù)據(jù)庫不一致。為了保證緩存數(shù)據(jù)的一致性繁疤,在進行 CUD 操作的時候我們需要對可能影響到的緩存進行更新或者清除咖为。如下:

/**
 * 獲取數(shù)據(jù),并且做緩存處理
 * @author z77z
 *
 */
@Component
public class RedisCache {
    
    @Autowired
    BeautifulPicturesService beautifulPicturesService;
    
    //查詢
    @Cacheable(value = "beautifulPictures")
    public BeautifulPictures getBeautifulPicturesList(String id) {
        return beautifulPicturesService.selectById(id);
    }
    
    //修改
    @CachePut(value = "beautifulPictures")
    public void updateBeautifulPicture(String id) {
        BeautifulPictures beautifulPictures = new BeautifulPictures();
        beautifulPictures.setTitle("Title被我修改了一下稠腊,哈哈");
        beautifulPictures.setId(id);
        beautifulPicturesService.updateById(beautifulPictures);
    }
}
/**
 * 測試類
 * @author z77z
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisCacheTest {
    @Autowired
    BeautifulPicturesService beautifulPicturesService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    
    @Autowired
    RedisCache redisCache;
    
    @Test
    public void redisTest() throws Exception {

        //保存字符串
        stringRedisTemplate.opsForValue().set("aaa", "111");
        //讀取字符串
        String aaa = stringRedisTemplate.opsForValue().get("aaa");
        System.out.println(aaa);
    }
    
    @Test
    public void CacheTest() {
        String id = "1";
        BeautifulPictures beautifulPicture = redisCache.getBeautifulPicturesList(id);
        System.out.println("第一次查詢結(jié)果:");
        System.out.println(beautifulPicture);

        BeautifulPictures beautifulPicture1 = redisCache.getBeautifulPicturesList(id);
        System.out.println("第二次查詢結(jié)果:");
        System.out.println(beautifulPicture1);
        
        redisCache.updateBeautifulPicture(id);
        
        BeautifulPictures beautifulPicture2 = redisCache.getBeautifulPicturesList(id);
        System.out.println("第三次查詢結(jié)果:");
        System.out.println(beautifulPicture2);
    }
}

保持緩存一致性測試結(jié)果:

保持緩存的一致性測試

在會導(dǎo)致數(shù)據(jù)發(fā)生改變的方法上添加@CachePut(value = "beautifulPictures")注解躁染,添加后會更新緩存中的值,并且每次都會正常執(zhí)行方法內(nèi)容架忌。

SpringBoot緩存注解詳解

  • @Cacheable:作用是主要針對方法配置吞彤,能夠根據(jù)方法的請求參數(shù)對其結(jié)果進行緩存

主要參數(shù)說明:

  1. value:緩存的名稱,在 spring 配置文件中定義叹放,必須指定至少一個饰恕,例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}。
  2. key:緩存的 key井仰,可以為空埋嵌,如果指定要按照 SpEL 表達式編寫,如果不指定俱恶,則缺省按照方法的所有參數(shù)進行組合雹嗦,例如:@Cacheable(value=”testcache”,key=”#userName”)。
  3. condition:緩存的條件合是,可以為空了罪,使用 SpEL 編寫,返回 true 或者 false端仰,只有為 true 才進行緩存捶惜,例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2。
  • @CachePut:作用是主要針對方法配置荔烧,能夠根據(jù)方法的請求參數(shù)對其結(jié)果進行緩存吱七,和 @Cacheable 不同的是,它每次都會觸發(fā)真實方法的調(diào)用

主要參數(shù)說明:

  1. value鹤竭,keycondition參數(shù)配置和@Cacheable一樣踊餐。
  • @CacheEvict:作用是主要針對方法配置,能夠根據(jù)一定的條件對緩存進行清空

主要參數(shù)說明:

  1. value臀稚,keycondition參數(shù)配置和@Cacheable一樣吝岭。
  2. allEntries:是否清空所有緩存內(nèi)容,缺省為 false,如果指定為 true窜管,則方法調(diào)用后將立即清空所有緩存散劫,例如:@CachEvict(value=”testcache”,allEntries=true)。
  3. beforeInvocation:是否在方法執(zhí)行前就清空幕帆,缺省為 false获搏,如果指定為 true,則在方法還沒有執(zhí)行的時候就清空緩存失乾,缺省情況下常熙,如果方法執(zhí)行拋出異常,則不會清空緩存碱茁,例如@CachEvict(value=”testcache”裸卫,beforeInvocation=true)。

另外說下: @cache(“something");這個相當(dāng)于save()操作纽竣,@cachePut相當(dāng)于Update()操作墓贿,只要他標示的方法被調(diào)用,那么都會緩存起來退个,而@cache則是先看下有沒已經(jīng)緩存了募壕,然后再選擇是否執(zhí)行方法。@CacheEvict相當(dāng)于Delete()操作语盈。用來清除緩存用的舱馅。

荊軻刺秦王~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刀荒,隨后出現(xiàn)的幾起案子代嗤,更是在濱河造成了極大的恐慌,老刑警劉巖缠借,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件干毅,死亡現(xiàn)場離奇詭異,居然都是意外死亡泼返,警方通過查閱死者的電腦和手機硝逢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绅喉,“玉大人渠鸽,你說我怎么就攤上這事〔窆蓿” “怎么了徽缚?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長革屠。 經(jīng)常有香客問我凿试,道長排宰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任那婉,我火速辦了婚禮板甘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘详炬。我一直安慰自己虾啦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布痕寓。 她就那樣靜靜地躺著,像睡著了一般蝇闭。 火紅的嫁衣襯著肌膚如雪呻率。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天呻引,我揣著相機與錄音礼仗,去河邊找鬼。 笑死逻悠,一個胖子當(dāng)著我的面吹牛元践,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播童谒,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼单旁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饥伊?” 一聲冷哼從身側(cè)響起象浑,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琅豆,沒想到半個月后愉豺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡茫因,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年蚪拦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冻押。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡驰贷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翼雀,到底是詐尸還是另有隱情饱苟,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布狼渊,位于F島的核電站箱熬,受9級特大地震影響类垦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜城须,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一蚤认、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糕伐,春花似錦砰琢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至褥蚯,卻和暖如春挚冤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赞庶。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工训挡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人歧强。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓澜薄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摊册。 傳聞我的和親對象是個殘疾皇子肤京,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容