溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot整合Redis緩存實現(xiàn)的方法

發(fā)布時間:2022-03-29 13:49:12 來源:億速云 閱讀:206 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“SpringBoot整合Redis緩存實現(xiàn)的方法”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“SpringBoot整合Redis緩存實現(xiàn)的方法”文章能幫助大家解決問題。

SpringBoot支持的緩存組件

在SpringBoot中,數(shù)據(jù)的緩存管理存儲依賴于Spring框架中cache相關(guān)的org.springframework.cache.Cache和org.springframework.cache.CacheManager緩存管理器接口。

如果程序中沒有定義類型為CacheManager的Bean組件或者是名為cacheResolver的CacheResolver緩存解析器,SpringBoot將嘗試選擇啟用以下緩存組件(按照指定的順序):

(1)Generic

(2)JCache (JSR-107) (EhCache 3、Hazelcast、Infinispan等)

(3)EhCache 2.x

(4)Hazelcast

(5)Infinispan

(6)Couchbase

(7)Redis

(8)Caffeine

(9)Simple

上面按照SpringBoot緩存組件的加載順序,列舉了SpringBoot支持的9種緩存組件,在項目中添加某個緩存管理組件(例如Redis)后,SpringBoot項目會選擇并啟用對應(yīng)的緩存管理器。如果在項目中同時添加了多個緩存組件,且沒有指定緩存管理器或者緩存解析器(CacheManager或者cacheResolver),那么SpringBoot會按照上述順序在添加的多個緩存組件中優(yōu)先啟用排在前面的某個緩存組件進行緩存管理(例如,同時添加了Couchbase和Redis這兩個緩存組件,那么優(yōu)先啟用Couchbase組件)。

在上一篇文章 SpringBoot緩存管理(一) 默認緩存管理 介紹的默認緩存管理中,我們搭建的項目沒有添加任何緩存管理組件,但是依舊實現(xiàn)了緩存管理。這是因為開啟緩存管理后,SpringBoot會按照上述緩存組件順序查找有效的緩存組件進行緩存管理,如果沒有任何緩存組件,會默認使用最后一個Simple緩存組件進行管理。Simple緩存組件是SpringBoot默認的緩存管理組件,它默認使用內(nèi)存中的ConcurrentMap進行緩存存儲,所以在沒有添加任何第三方緩存組件的情況下,依舊可以實現(xiàn)內(nèi)存中的緩存管理,但是不推薦這種緩存管理方式。

基于注解的Redis緩存實現(xiàn)

在 SpringBoot緩存管理(一) 默認緩存管理 搭建的項目基礎(chǔ)上引入Redis緩存組件,使用基于注解的方式講解SpringBoot整合Redis緩存的具體實現(xiàn)。

(1)添加Spring Data Redis依賴啟動器

在pom.xml文件中添加Spring Data Redis依賴啟動器:

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

當(dāng)我們添加Redis相關(guān)的依賴啟動器后,SpringBoot會使用RedisCacheConfigratioin作為自動配置類進行緩存相關(guān)的自動裝配類(之前為默認的SimpleCacheConfiguration),容器中使用的緩存管理器變?yōu)榱薘edisCacheManager(之前為默認為cacheManager),這個緩存管理器創(chuàng)建的Cache為RedisCache,進而操控Redis進行數(shù)據(jù)的緩存。

(2)Redis服務(wù)器連接配置

在項目的全局配置文件application.properties中添加Redis數(shù)據(jù)庫的連接配置,示例代碼如下:

# Redis服務(wù)器地址
spring.redis.host=127.0.0.1
# Redis服務(wù)器連接端口
spring.redis.port=6379
# Redis服務(wù)器連接密碼(默認為空)
spring.redis.password=

(3)對CommentService類中的方法進行修改

使用@Cacheable、@CachePut、@CacheEvict三個注解進行緩存管理,分別進行緩存存儲、緩存更新及緩存刪除等操作:

package com.hardy.springbootdatacache.service;

import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.repository.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * @Author: HardyYao
 * @Date: 2021/6/19
 */
@Service
public class CommentService {

    @Autowired
    private CommentRepository commentRepository;

    /**
     * 根據(jù)評論id查詢評論
     * @Cacheable:將該方法的查詢結(jié)果comment存放在SpringBoot默認緩存中
     * cacheNames:起一個緩存命名空間,對應(yīng)緩存唯一標識
     * @param id
     * @return
     */
    @Cacheable(cacheNames = "comment", unless = "#result==null")
    public Comment findCommentById(Integer id){
        Optional<Comment> comment = commentRepository.findById(id);
        if(comment.isPresent()){
            Comment comment1 = comment.get();
            return comment1;
        }
        return null;
    }

    /**
     * 更新評論
     * @param comment
     * @return
     */
    @CachePut(cacheNames = "comment",key = "#result.id")
    public Comment updateComment(Comment comment) {
        commentRepository.updateComment(comment.getAuthor(), comment.getaId());
        return comment;
    }

    /**
     * 刪除評論
     * @param comment_id
     */
    @CacheEvict(cacheNames = "comment")
    public void deleteComment(int comment_id) {
        commentRepository.deleteById(comment_id);
    }

}

在上述代碼中,使用了@Cacheable、@CachePut、@CacheEvict注解在數(shù)據(jù)查詢、數(shù)據(jù)更新及數(shù)據(jù)刪除方法上進行了緩存管理。

其中,查詢緩存@Cacheable注解中沒有標記key值,將會使用默認參數(shù)值comment_id作為key進行數(shù)據(jù)保存,在進行緩存更新時必須使用同樣的的key;同樣,在使用查詢緩存@Cacheable注解中,定義了 unless= "#result==null" 表示查詢結(jié)果為空則不進行緩存。

(4)在CommentController類中新增兩個接口

新增更新和刪除的接口:

package com.hardy.springbootdatacache.controller;

import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: HardyYao
 * @Date: 2021/6/19
 */
@RestController
public class CommentController {

    @Autowired
    private CommentService commentService;

    @RequestMapping(value = "/findCommentById")
    public Comment findCommentById(Integer id){
        Comment comment = commentService.findCommentById(id);
        return comment;
    }

    @RequestMapping(value = "/updateComment")
    public Comment updateComment(Comment comment){
        Comment oldComment = commentService.findCommentById(comment.getId());
        oldComment.setAuthor(comment.getAuthor());
        Comment comment1 = commentService.updateComment(oldComment);
        return comment1;
    }

    @RequestMapping(value = "/deleteComment")
    public void deleteComment(Integer id){
        commentService.deleteComment(id);
    }

}

(5)基于注解的Redis查詢緩存測試

在瀏覽器中輸入:http://localhost:8080/findCommentById?id=1 進行訪問:

SpringBoot整合Redis緩存實現(xiàn)的方法

頁面報錯了,查看控制臺信息:

SpringBoot整合Redis緩存實現(xiàn)的方法

根據(jù)報錯信息可知:查詢用戶評論信息Comment時執(zhí)行了相應(yīng)的SQL語句,但是在進行緩存存儲時出現(xiàn)了IllegalArgumentException非法參數(shù)異常,提示信息要求對應(yīng)的Comment實體類必須實現(xiàn)序列化(DefaultSerializer requires a Serializable payload but received an object of type [com.hardy.springbootdatacache.entity.Comment])。

(6)將緩存對象實現(xiàn)序列化

SpringBoot整合Redis緩存實現(xiàn)的方法

(7)重啟項目測試查詢緩存

在瀏覽器中輸入:http://localhost:8080/findCommentById?id=1 進行訪問(連續(xù)訪問三次):

SpringBoot整合Redis緩存實現(xiàn)的方法SpringBoot整合Redis緩存實現(xiàn)的方法

打開Redis客戶端可視化工具Redis Desktop Manager,連接本地啟用的Redis服務(wù),查看具體的數(shù)據(jù)緩存效果:

SpringBoot整合Redis緩存實現(xiàn)的方法

執(zhí)行findById()方法查詢出的用戶評論信息Comment正確存儲到了Redis緩存庫中名為comment的名稱空間下。

其中緩存數(shù)據(jù)的唯一標識key值是以“名稱空間comment::+參數(shù)值(comment::1)”的字符串形式體現(xiàn)的,而value值則是經(jīng)過JDK默認序列格式化后的HEX格式存儲。這種JDK默認序列格式化后的數(shù)據(jù)顯然不方便緩存數(shù)據(jù)的可視化查看和管理,所以在實際開發(fā)中,通常會自定義數(shù)據(jù)的序列化格式,這方面的內(nèi)容在后面會介紹。

(8)基于注解的Redis緩存更新測試

先通過瀏覽器訪問:http://localhost:8080/updateComment?id=1&author=hardy;

接著在訪問:http://localhost:8080/findCommentById?id=1,查看瀏覽器返回信息及控制臺打印信息:

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

可以看到,執(zhí)行updateComment()更新id為1的數(shù)據(jù)時執(zhí)行了一條更新的SQL語句,后續(xù)調(diào)用findById()方法查詢id為1的用戶評論信息時沒有再次執(zhí)行查詢的SQL語句,且瀏覽器返回了更新后的正確結(jié)果,這說明@CachePut緩存更新配置成功。

(9)基于注解的Redis緩存刪除測試

通過瀏覽器訪問:http://localhost:8080/deleteComment?id=1 和 http://localhost:8080/findCommentById?id=1

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

執(zhí)行deleteComment()方法刪除id為1的數(shù)據(jù)后查詢結(jié)果為空,查看Redis緩存數(shù)據(jù)庫:

SpringBoot整合Redis緩存實現(xiàn)的方法

可以看到之前存儲的comment相關(guān)數(shù)據(jù)被刪除掉了,這表明@CacheEvict注解緩存刪除成功實現(xiàn)。

通過上面的案例可以看出:使用基于注解的Redis緩存實現(xiàn)只需要添加Redis依賴、并使用幾個注解在對應(yīng)的方法上,就可以實現(xiàn)對數(shù)據(jù)的緩存管理。

另外,還可以在SpringBoot全局配置文件中配置Redis有效期,示例代碼如下:

# 對基于注解的Redis緩存數(shù)據(jù)統(tǒng)一設(shè)置有效期為1分鐘,單位毫秒
spring.cache.redis.time-to-live=60000

上述代碼中,在SpringBoot全局配置文件中添加了“spring.cache.redis.time-to-live”屬性統(tǒng)一設(shè)置Redis數(shù)據(jù)的有效期(單位為毫秒),但這種方式不夠靈活,因此一般不用。

基于API的Redis緩存實現(xiàn)

在SpringBoot整合Redis緩存實現(xiàn)中,除了基于注解形式的Redis緩存形式外,還有一種開發(fā)中更常用的方式——基于API的Redis緩存實現(xiàn)。這種基于API的Redis緩存實現(xiàn),需要在某種業(yè)務(wù)需求下通過Redis提供的API調(diào)用相關(guān)方法實現(xiàn)數(shù)據(jù)緩存管理。同時,這種方法還可以手動管理緩存的有效期。

下面,通過Redis API的方式講解SpringBoot整合Redis緩存的具體實現(xiàn)。

(1)使用Redis API進行業(yè)務(wù)數(shù)據(jù)緩存管理

在 com.hardy.springbootdatacache.service 包下新建一個 ApiCommentService:

package com.hardy.springbootdatacache.service;

import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.repository.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @Author: HardyYao
 * @Date: 2021/6/19
 */
@Service
public class ApiCommentService {

    @Autowired
    private CommentRepository commentRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根據(jù)評論id查詢評論
     * @param id
     * @return
     */
    public Comment findCommentById(Integer id){
        // 先查Redis緩存
        Object o = redisTemplate.opsForValue().get("comment_" + id);
        if (o != null) {
            return (Comment) o;
        } else {
            // 如果緩存中沒有,則從數(shù)據(jù)庫查詢
            Optional<Comment> dbComment = commentRepository.findById(id);
            if (dbComment.isPresent()) {
                Comment redisComment = dbComment.get();
                // 將查詢結(jié)果存儲到緩存中,并設(shè)置有效期為1天
                redisTemplate.opsForValue().set("comment_"+id, redisComment,1, TimeUnit.DAYS);
                return redisComment;
            } else {
                return null;
            }
        }

    }

    /**
     * 更新評論
     * @param comment
     * @return
     */
    public Comment updateComment(Comment comment) {
        commentRepository.updateComment(comment.getAuthor(), comment.getId());
        // 更新數(shù)據(jù)庫數(shù)據(jù)后進行緩存更新
        redisTemplate.opsForValue().set("comment_" + comment.getId(), comment);
        return comment;
    }

    /**
     * 刪除評論
     * @param comment_id
     */
    public void deleteComment(int comment_id) {
        commentRepository.deleteById(comment_id);
        // 刪除數(shù)據(jù)庫數(shù)據(jù)后進行緩存刪除
        redisTemplate.delete("comment_" + comment_id);
    }

}

(2)編寫Web訪問層ApiCommentController

package com.hardy.springbootdatacache.controller;

import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.service.ApiCommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: HardyYao
 * @Date: 2021/6/19
 */
@RestController
@RequestMapping("api")  // 改變請求路徑
public class ApiCommentController {

    @Autowired
    private ApiCommentService apiCommentService;

    @RequestMapping(value = "/findCommentById")
    public Comment findCommentById(Integer id){
        Comment comment = apiCommentService.findCommentById(id);
        return comment;
    }

    @RequestMapping(value = "/updateComment")
    public Comment updateComment(Comment comment){
        Comment oldComment = apiCommentService.findCommentById(comment.getId());
        oldComment.setAuthor(comment.getAuthor());
        Comment comment1 = apiCommentService.updateComment(oldComment);
        return comment1;
    }

    @RequestMapping(value = "/deleteComment")
    public void deleteComment(Integer id){
        apiCommentService.deleteComment(id);
    }

}

(3)測試基于API的Redis緩存實現(xiàn)

輸入:http://localhost:8080/api/findCommentById?id=2(連續(xù)輸入三次)、http://localhost:8080/api/updateComment?id=2&author=hardy、http://localhost:8080/deleteComment?id=2進行訪問:

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

查看控制臺消息及Redis數(shù)據(jù)庫:

SpringBoot整合Redis緩存實現(xiàn)的方法

SpringBoot整合Redis緩存實現(xiàn)的方法

基于API的Redis緩存實現(xiàn)的相關(guān)配置:基于API的Redis緩存實現(xiàn)不需要@EnableCaching注解開啟基于注解的緩存支持,所以這里可以選擇將添加在項目啟動類上的@EnableCaching注解進行刪除或者注釋,不會影響項目的功能實現(xiàn)。

關(guān)于“SpringBoot整合Redis緩存實現(xiàn)的方法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI