2021年你还不会Shiro?----10.使用redis实现Shiro的缓存

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 上一篇文章已经总结了使用ehCache来实现Shiro的缓存管理,步骤也很简单,引入依赖后,直接开启Realm的缓存管理器即可。如果使用Redis来实现缓存管理其实也是一样的,我们也是需要引入redis的依赖,然后开启缓存传入自定义的redis的缓存管理器就行。区别是我们需要为自定义的redis缓存管理器提供自定义的缓存管理类。这个缓存管理类中需要使用到redisTemplate模板,这个模板我们也是需要自己定义。

前言:

上一篇文章已经总结了使用ehCache来实现Shiro的缓存管理,步骤也很简单,引入依赖后,直接开启Realm的缓存管理器即可。如果使用Redis来实现缓存管理其实也是一样的,我们也是需要引入redis的依赖,然后开启缓存传入自定义的redis的缓存管理器就行。区别是我们需要为自定义的redis缓存管理器提供自定义的缓存管理类。这个缓存管理类中需要使用到redisTemplate模板,这个模板我们也是需要自己定义。


一.实现过程



主要过程就是导入依赖、提供自定义缓存管理器、提供缓存管理类、开启缓存传入自定义缓存管理器即可。


1.导入redis依赖。


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


2.提供自定义缓存管理器 MyRedisCacheManager


我们使用EhCacheManager缓存时发现EhCacheManager实现了CacheManager这个接口,所以我们自定义缓存管理器时也需要实现该接口,这个接口只有一个方法,就是用来获取缓存管理类,实现如下:

public class MyRedisCacheManager implements CacheManager {
    /**
    *   只要加入了缓存管理器,配置了缓存管理类,系统就会默认在查询完认证和授权后将信息放入到缓存中
    *   且下次需要认证和授权时,都是优先去查询缓存中的内容,查询不到,才会去查询数据库,这里也验证了
    *   这一点,与之前的画的加入缓存后的授权信息的获取图是一样的。
     */
    @Override
    public <K, V> Cache<K, V> getCache(String cacheName) throws CacheException {
        System.out.println("进入到了自定义缓存管理器,传入参数cacheName:"+ cacheName);
        return new RedisCache<K,V>(cacheName);
    }
}


3.设计自己的缓存管理类


根据上方的代码我们可以看到,所有的缓存管理类的实例都应该是Cache的实现类。所以我们自己定义redis的缓存管理类应该也必须去实现这个Cache类。实现如下:

@NoArgsConstructor
public class RedisCache<k,v> implements Cache<k,v> {
    private String cacheName;
    @Autowired
    public  RedisTemplate redisTemplate;
    public static RedisTemplate redisTemplateSelf;
    @PostConstruct
    public void getRedisTemplate(){
        this.redisTemplateSelf = redisTemplate;
    }
    public RedisCache (String cacheName1){
        this.cacheName = cacheName1;
    }
    @Override
    public v get(k k) throws CacheException {
        System.out.println(cacheName+":获取缓存方法,传入参数:" + k+",此时的redisTemplate:"+redisTemplateSelf);
        //获取缓存中数据时一定要为k加toStirng方法,否则会报错序列化的错
        if(null != redisTemplateSelf.opsForHash().get(cacheName.toString(),k.toString())){
            return (v)redisTemplateSelf.opsForHash().get(cacheName.toString(),k.toString());
        }
        return null;
    }
    @Override
    public v put(k k, v v) throws CacheException {
        System.out.println("加入缓存方法,传入参数 K:" + k+",V:"+v);
        //放入redis中的值,一定要是序列化的对象
        redisTemplateSelf.opsForHash().put(cacheName.toString(),k.toString(),v);
        return null;
    }
    @Override
    public v remove(k k) throws CacheException {
        System.out.println("调用了remove方法,传入参数:"+k.toString());
        redisTemplateSelf.opsForHash().delete(cacheName.toString(),k.toString());
        return null;
    }
    @Override
    public void clear() throws CacheException {
        System.out.println("调用了clear方法");
        redisTemplateSelf.delete(cacheName);
    }
    @Override
    public int size() {
        return redisTemplateSelf.opsForHash().size(cacheName).intValue();
    }
    @Override
    public Set<k> keys() {
        return redisTemplateSelf.opsForHash().keys(cacheName);
    }
    @Override
    public Collection<v> values() {
        return redisTemplateSelf.opsForHash().values(cacheName);
    }
}


这个类里我们实现了设置缓存、获取缓存、移除缓存、情况缓存等方法。

其中我们开启缓存后,用户登录成功就会将缓存放入到redis中,使用退出功能,就会清楚当前登录的缓存信息,授权信息也是一样,只要使用退出功能就会清空当前的缓存信息。但是这里并没有设计过期时间的处理。所以真实场景下,我们还需要考虑过期时间的设置。这里显然我们用到了RedisTemplate模板,这个模板我们一般也是自己定义,不过也可以直接使用SpringBoot默认提供的。这里我们采用自己定义RedisTemplate的方式。


4.自定义RedisTemplate注入到Spring容器中


 //注入自定义的RedisTemplate
    @Bean
    public RedisTemplate getRedisTemplate(RedisConnectionFactory connectionFactory){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    //注入Shiro的缓存对象
    @Bean
    public RedisCache getRedisCache(){
        RedisCache redisCache = new RedisCache();
        return  redisCache;
    }


5.Realm中开启缓存管理


经过以上的过程,必要的过程以及完成了,可以在Realm中开启缓存管理器了,如下:

@Bean
    public FirstRealm getRealm(){
        FirstRealm firstRealm = new FirstRealm();
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(2048);
//        下面的写法也是正常的,不过现在都是使用上面的写法,下面的写法已经是不推荐使用的了。
//        Md5CredentialsMatcher md5CredentialsMatcher = new Md5CredentialsMatcher();
//        md5CredentialsMatcher.setHashIterations(2048);
        firstRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        //开启缓存
//        firstRealm.setCachingEnabled(true);//开启全局的缓存管理
        firstRealm.setAuthenticationCachingEnabled(true);//开启认证缓存
//        firstRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
        //缓存名称很有必要设置,因为若是只使用k,v的形式设置redis缓存,认证和授权默认的k都是用户名,所以我们
        //需要使用k,map的形式存储,k就可以是这个设置的缓存名称,缓存管理器中传入的k就是这个值。
        firstRealm.setAuthenticationCacheName("authenticationCache");//设置缓存名称--认证
        firstRealm.setAuthorizationCacheName("authorizationCache");//设置缓存名称--授权
        firstRealm.setCacheManager(new MyRedisCacheManager());
        return firstRealm;
    }


6.测试缓存是否有效


我们已经完成了使用Redis进行Shiro的缓存管理的所有功能。下面就来测试下上面的过程是否有效。


20210401104118382.gif


经过多次刷新页面发现,每次都是去缓存中拿数据,而不是去走认证方法,这样我们的缓存实现就成功了。但是上方的redisTemplate虽然是我们定义的,但是真实项目中一般不这么用,都会定义自己的Redis工具类。


shiro留下的坑,盐必须序列化


在Realm中定义缓存管理器与在安全管理器中定义缓存管理器有区别吗?


没什么区别,在自定义realm中设置缓存管理,与安全管理器中设置缓存,realm都能正常拥有缓存。不过不同的是若是在安全管理器中设置缓存,安全管理器拥有了缓存,realm同时也会有缓存,若是在realm设置,安全管理器则不会有缓存。但是事实上安全管理器的缓存管理也是为了realm服务的,除了realm需要缓存管理,其他也没有了。所以即使这设置的范围不同,但是效果都是一样的。在我看来,设置在realm中更符合逻辑。符合谁需要设置给谁的原则。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
5天前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
|
14天前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
81 22
|
12天前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
88 7
|
17天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
51 10
|
12天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
28 0
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
70 6
|
1月前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
169 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿

热门文章

最新文章