SpringBoot では、データのキャッシュ管理とストレージは、スプリングフレームワーク。
プログラム内に CacheManager タイプの Bean コンポーネントまたは cacheResolver という名前の CacheResolver キャッシュ リゾルバーが定義されていない場合、SpringBoot は次のキャッシュ コンポーネントを (指定された順序で) 有効にしようとします。 1) 汎用
(2) JCache (JSR-107) (EhCache 3、Hazelcast、Infinispanなど)
(3) EhCache 2.x
(4) Hazelcast
(5)Infinispan
(6)Couchbase
(7)Redis
(8)カフェイン
(9) Simple
上記は、SpringBoot キャッシュ コンポーネントの読み込み順序に従って SpringBoot でサポートされる 9 つのキャッシュ コンポーネントをリストしています。キャッシュ管理コンポーネント (Redis など) をプロジェクトに追加した後、SpringBoot プロジェクトは対応するコンポーネントを選択して有効にします。キャッシュマネージャーです。プロジェクトに複数のキャッシュコンポーネントが同時に追加され、キャッシュマネージャーまたはキャッシュリゾルバー(CacheManagerまたはcacheResolver)が指定されていない場合、SpringBootは上記の順序で追加された複数のキャッシュコンポーネントのうち最初のものを優先的に有効にします。キャッシュ管理を実行します (たとえば、2 つのキャッシュ コンポーネント Couchbase と Redis が同時に追加された場合、Couchbase コンポーネントが最初に有効になります)。
前回の記事「SpringBoot のキャッシュ管理 (1) デフォルトのキャッシュ管理」で紹介したデフォルトのキャッシュ管理では、構築したプロジェクトにはキャッシュ管理コンポーネントが追加されていませんでしたが、キャッシュ管理は引き続き実装されました。これは、
キャッシュ管理が有効になった後、SpringBoot は上記のキャッシュ コンポーネントの順序でキャッシュ管理に有効なキャッシュ コンポーネントを検索します。キャッシュ コンポーネントがない場合は、デフォルトで最後のシンプル キャッシュ コンポーネントが管理に使用されます。。シンプル キャッシュ コンポーネントは SpringBoot のデフォルトのキャッシュ管理コンポーネントであり、デフォルトでキャッシュ ストレージにメモリ内の ConcurrentMap を使用するため、サードパーティのキャッシュ コンポーネントを追加しなくてもメモリ内のキャッシュ管理を実現できますが、これはお勧めできません。このキャッシュ管理方法。 アノテーションベースの Redis キャッシュ実装
SpringBoot キャッシュ管理 (1) デフォルトのキャッシュ管理で構築されたプロジェクトに基づいて Redis キャッシュ コンポーネントを紹介し、アノテーションベースのメソッドを使用して具体的な詳細を説明します。 SpringBoot の Redis キャッシュの統合が達成されました。 (1) Spring Data Redis 依存関係スターターを追加します Spring Data Redis 依存関係スターターを pom.xml ファイルに追加します:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>
(3) CommentService クラスのメソッドを変更する
キャッシュ管理に @Cacheable、@CachePut、@CacheEvict の 3 つのアノテーションを使用し、キャッシュの保存、キャッシュの更新、キャッシュの削除などの操作を実行します。それぞれ:
# Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password=
上記のコードでは、@Cacheable、@CachePut、および @CacheEvict アノテーションを使用して、データ クエリ、データ更新、およびデータ削除メソッドのキャッシュ管理を実行します。
このうち、クエリキャッシュの @Cacheable アノテーションにはマークキーの値が存在せず、デフォルトパラメータ値の comment_id がデータを保存するキーとして使用されます。キャッシュを更新するときも同じキーを使用する必要があります。 ; 同様にクエリキャッシュを使用する場合 @Cacheable アノテーションでは、unless= "#result==null" が定義されており、クエリ結果が空の場合はキャッシュされません。
(4) CommentController クラスに 2 つの新しいインターフェイスを追加します。
新しい更新インターフェイスと削除インターフェイスを追加します:
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 */@Servicepublic class CommentService { @Autowiredprivate CommentRepository commentRepository;/** * 根据评论id查询评论 * @Cacheable:将该方法的查询结果comment存放在SpringBoot默认缓存中 * cacheNames:起一个缓存命名空间,对应缓存唯一标识 * @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); } }
(5) アノテーション ベースの Redis クエリ キャッシュ テスト
ブラウザに http://localhost:8080/findCommentById?id=1 と入力してアクセスします:
#ページでエラーが報告されました。コンソール情報を確認してください:#エラー メッセージによると、ユーザー コメント情報 Comment をクエリするときに対応する SQL ステートメントが実行されましたが、キャッシュ保存中に IllegalArgumentException が発生し、情報要件が求められました。対応する Comment エンティティ クラスは次のとおりです。シリアル化を実装します (DefaultSerializer にはシリアル化可能なペイロードが必要ですが、タイプ [com.hardy.springbootdatacache.entity.Comment] のオブジェクトを受け取りました)。
(6) キャッシュ オブジェクトをシリアル化する
(7) プロジェクトを再起動してクエリ キャッシュをテストします
在浏览器中输入:http://localhost:8080/findCommentById?id=1 进行访问(连续访问三次):
打开Redis客户端可视化工具Redis Desktop Manager,连接本地启用的Redis服务,查看具体的数据缓存效果:
执行findById()方法查询出的用户评论信息Comment正确存储到了Redis缓存库中名为comment的名称空间下。
其中缓存数据的唯一标识key值是以“名称空间comment::+参数值(comment::1)”的字符串形式体现的,而value值则是经过JDK默认序列格式化后的HEX格式存储。这种JDK默认序列格式化后的数据显然不方便缓存数据的可视化查看和管理,所以在实际开发中,通常会自定义数据的序列化格式,这方面的内容在后面会介绍。
(8)基于注解的Redis缓存更新测试
先通过浏览器访问:http://localhost:8080/updateComment?id=1&author=hardy;
接着在访问:http://localhost:8080/findCommentById?id=1,查看浏览器返回信息及控制台打印信息:
可以看到,执行updateComment()更新id为1的数据时执行了一条更新的SQL语句,后续调用findById()方法查询id为1的用户评论信息时没有再次执行查询的SQL语句,且浏览器返回了更新后的正确结果,这说明@CachePut缓存更新配置成功。
(9)基于注解的Redis缓存删除测试
通过浏览器访问:http://localhost:8080/deleteComment?id=1 和 http://localhost:8080/findCommentById?id=1
执行deleteComment()方法删除id为1的数据后查询结果为空,查看Redis缓存数据库:
可以看到之前存储的comment相关数据被删除掉了,这表明@CacheEvict注解缓存删除成功实现。
通过上面的案例可以看出:使用基于注解的Redis缓存实现只需要添加Redis依赖、并使用几个注解在对应的方法上,就可以实现对数据的缓存管理。
另外,还可以在SpringBoot全局配置文件中配置Redis有效期,示例代码如下:
# 对基于注解的Redis缓存数据统一设置有效期为1分钟,单位毫秒 spring.cache.redis.time-to-live=60000
上述代码中,在SpringBoot全局配置文件中添加了“spring.cache.redis.time-to-live”属性统一设置Redis数据的有效期(单位为毫秒),但这种方式不够灵活,因此一般不用。
在SpringBoot整合Redis缓存实现中,除了基于注解形式的Redis缓存形式外,还有一种开发中更常用的方式——基于API的Redis缓存实现。这种基于API的Redis缓存实现,需要在某种业务需求下通过Redis提供的API调用相关方法实现数据缓存管理。同时,这种方法还可以手动管理缓存的有效期。
下面,通过Redis API的方式讲解SpringBoot整合Redis缓存的具体实现。
(1)使用Redis API进行业务数据缓存管理
在 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 */@Servicepublic class ApiCommentService { @Autowiredprivate CommentRepository commentRepository; @Autowiredprivate RedisTemplate redisTemplate;/** * 根据评论id查询评论 * @param id * @return */public Comment findCommentById(Integer id){// 先查Redis缓存Object o = redisTemplate.opsForValue().get("comment_" + id);if (o != null) {return (Comment) o; } else {// 如果缓存中没有,则从数据库查询Optional<Comment> dbComment = commentRepository.findById(id);if (dbComment.isPresent()) { Comment redisComment = dbComment.get();// 将查询结果存储到缓存中,并设置有效期为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());// 更新数据库数据后进行缓存更新redisTemplate.opsForValue().set("comment_" + comment.getId(), comment);return comment; }/** * 删除评论 * @param comment_id */public void deleteComment(int comment_id) { commentRepository.deleteById(comment_id);// 删除数据库数据后进行缓存删除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 { @Autowiredprivate 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缓存实现
输入:http://localhost:8080/api/findCommentById?id=2(连续输入三次)、http://localhost:8080/api/updateComment?id=2&author=hardy、http://localhost:8080/deleteComment?id=2进行访问:
コンソール メッセージと Redis データベースの表示:
API ベースの関連事項Redis キャッシュ実装の構成: API ベースの Redis キャッシュ実装では、アノテーションベースのキャッシュのサポートを有効にするために @EnableCaching アノテーションが必要ないため、ここでプロジェクトの起動クラスに追加された @EnableCaching アノテーションを削除するか、アノテーションを付けるかを選択できます。いいえ プロジェクトの機能実装に影響します。
以上がSpringBoot と Redis キャッシュの統合を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。