【Shiro】3.Springboot实现缓存

news/2024/12/21 23:56:11/文章来源:https://www.cnblogs.com/luyj00436/p/18446712

最近已经快速入门了Shiro。对于登录、授权、认证等方法,每次都是从数据库直接查询。如果登录的人员过多,对数据库来说,是一项压力。如何减轻数据库的压力。

  • EhCache 实现缓存
  • 集成 Redis 实现 Shiro 缓存(推荐使用)

在此之前,我们已经简单学会EhCache 和Reids的使用。

EhCache 实现缓存

Shiro 提供了缓存管理器,这样在用户第一次认证授权后访问其受限资源的时候就不用每次查询数据库从而达到减轻数据压力的作用,使用 Shiro 的缓存管理器也很简单。第一步,在pom.xml引入依赖

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.13.10</version>
</dependency>

ShiroConfiguratin 添加缓存配置:

 1 /**
 2  * 3.创建自定义realm
 3  * @return
 4  */
 5 @Bean
 6 public Realm getRealm(){
 7     UserRealm userRealm = new UserRealm();
 8     // 设置缓存管理器
 9     userRealm.setCacheManager(new EhCacheManager());
10     // 开启全局缓存
11     userRealm.setCachingEnabled(true);
12     // 开启认证缓存并指定缓存名称
13     userRealm.setAuthenticationCachingEnabled(true);
14     userRealm.setAuthenticationCacheName("authenicationCache");
15     // 开启缓存授权并指定缓存名称
16     userRealm.setAuthorizationCachingEnabled(true);
17     userRealm.setAuthorizationCacheName("authenicationCache");
18     return userRealm;
19 }

这样就将 EhCache 集成进来了,但是 shiro 的这个缓存是本地缓存,也就是说当程序宕机重启后仍然需要从数据库加载数据,不能实现分布式缓存的功能。

集成 Redis 实现 Shiro 缓存(推荐使用)

已知Redis的使用,我们实现了Redis的引用和配置。

在pom.xml文件引入Redis依赖

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

配置RedisConfig

 1 @Configuration
 2 @EnableCaching
 3 public class RedisConfig extends CachingConfigurerSupport {
 4 
 5     /**
 6      * RedisTemplate相关配置
 7      * 使redis支持插入对象
 8      *
 9      * @param factory
10      * @return 方法缓存 Methods the cache
11      */
12     @Bean
13     public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
14         RedisTemplate<String, Object> template = new RedisTemplate<>();
15         // 配置连接工厂
16         template.setConnectionFactory(factory);
17         // 序列化 key 和hashKey采用String序列化;value和hashValue采用JSON序列化
18         GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
19         template.setKeySerializer(RedisSerializer.string());
20         template.setHashKeySerializer(RedisSerializer.string());
21         // value和hashvalue采用JSON序列化
22         template.setValueSerializer(jsonRedisSerializer);
23         template.setHashValueSerializer(jsonRedisSerializer);
24         return template;
25     }
26 }

配置redis的数据库连接,这里以application.yml为例

spring:redis:database: 0     # 数据库索引,默认为0host: 127.0.0.1 # redis地址port: 6379      # redis服务器端口地址 # sping.redis.password 表示密码,因为密码为空,这里不设置jedis:pool:max-wait: 3000  # 连接池最大阻塞等待时间,单位毫秒(使用负值表示没有限制)min-idle: 0     # 连接池最小空闲时间timeout: 3000       # 连接超时时间(毫秒)

添加自定义缓存配置。自定义配置缓存管理器(RedisCacheManage)和自定义缓存方法(RedisCache)。

 1 @Autowired
 2 private RedisTemplate redisTemplate;
 3 
 4 /**
 5  * 3.创建自定义realm
 6  * @return
 7  */
 8 @Bean
 9 public Realm getRealm(){
10     SysUserRealm sysUserRealm = new SysUserRealm();
11     // 设置缓存管理器
12     sysUserRealm.setCacheManager(new RedisCacheManage(redisTemplate)); // 自定义Redis数据库缓存方法
13     // 开启全局缓存
14     sysUserRealm.setCachingEnabled(true);
15     // 开启认证缓存并指定缓存名称
16     sysUserRealm.setAuthenticationCachingEnabled(true);
17     sysUserRealm.setAuthenticationCacheName("authenicationCache");
18     // 开启缓存授权并指定缓存名称
19     sysUserRealm.setAuthorizationCachingEnabled(true);
20     sysUserRealm.setAuthorizationCacheName("authenicationCache");
21     return sysUserRealm;
22 }
 1 public class RedisCacheManage implements CacheManager {
 2     private RedisTemplate redisTemplate;
 3 
 4     public RedisCacheManage(RedisTemplate redisTemplate) {
 5          this.redisTemplate = redisTemplate;
 6     }
 7 
 8     @Override
 9     public <K, V> Cache<K, V> getCache(String s) throws CacheException {
10         return new RedisCache(s , this.redisTemplate);
11     }
12 }
 1 public class RedisCache<K,V> implements Cache<K,V> {
 2     /** 缓存名称 **/
 3     private String cacheName;
 4     private RedisTemplate redisTemplate;
 5     public RedisCache(String cacheName, RedisTemplate redisTemplate){
 6         this.cacheName = cacheName;
 7         this.redisTemplate = redisTemplate;
 8     }
 9 
10     /**
11      * 获取缓存
12      * @param k
13      * @return
14      * @throws CacheException
15      */
16     @Override
17     public V get(K k) throws CacheException {
18         System.out.println("cacheName=" +this.cacheName);
19         System.out.println("k=" + k.toString());
20         System.out.println("res=" + this.redisTemplate);
21         return (V) redisTemplate.opsForHash().get(this.cacheName,k.toString());
22     }
23 
24     /**
25      * 设置缓存Key
26      * @param k
27      * @param v
28      * @return
29      * @throws CacheException
30      */
31     @Override
32     public V put(K k, V v) throws CacheException {
33          redisTemplate.opsForHash().put(this.cacheName,k.toString(),v);
34          return null;
35     }
36 
37     /**
38      * 移除缓存Key
39      * @param k
40      * @return
41      * @throws CacheException
42      */
43     @Override
44     public V remove(K k) throws CacheException {
45         return (V)redisTemplate.opsForHash().delete(this.cacheName,k.toString());
46     }
47 
48     /**
49      * 清除缓存
50      * @throws CacheException
51      */
52     @Override
53     public void clear() throws CacheException {
54         redisTemplate.delete(this.cacheName);
55     }
56 
57     /**
58      * 获取缓存的数量
59      * @return
60      */
61     @Override
62     public int size() {
63         return redisTemplate.opsForHash().size(this.cacheName).intValue();
64     }
65 
66     @Override
67     public Set<K> keys() {
68         return (Set<K>) redisTemplate.opsForHash().values(this.cacheName);
69     }
70 
71     @Override
72     public Collection<V> values() {
73         return redisTemplate.opsForHash().values(this.cacheName);
74     }
75 }

 此时,我们可以运行测试方法(这里使用了测试接口)

 /*** 系统认证、授权测试* @return*/@GetMapping("/test")public String test(){System.out.println("系统认证测试");String username = "christy";String password = Md5Utils.Md5PassWord("123456");System.out.println(password);try {Subject subject = SecurityUtils.getSubject();subject.login(new UsernamePasswordToken(username,password));}catch (UnknownAccountException e){System.err.println("认证失败:用户不存在");return  "redirect:/login";}catch (IncorrectCredentialsException e){System.err.println("认证失败:密码不正确");return  "redirect:/login";}catch (Exception e){System.err.println("认证失败");e.printStackTrace();// 如果认证失败仍然回到登录页面return  "redirect:/login";}return  "redirect:/login";}

调用接口后,我们发现Redis数据库存储了登录和授权的hash值。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/808371.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

织梦如何数据库备份,织梦cms网站数据怎么备份与还原

织梦CMS(DedeCMS)的数据库备份和还原是非常重要的操作,可以帮助你在出现问题时快速恢复数据。下面详细介绍如何进行织梦CMS的数据库备份和还原。 一、数据库备份 1. 使用 phpMyAdmin 备份数据库登录 phpMyAdmin登录到你的网站控制面板(如 cPanel)。 找到并打开 phpMyAdmin…

【软考】3 校验码

校验码 码距概念:任意进制的两个码值之间的最小二进制位数称为校验码的码距 例如:二进制1bit位,从0到1,则码距是1,二进制2bit位 从 00 到 11 一共4个码字,但码距还是为1 可以设置 性别男为 00 女为 11两个合法码字,则该两个合法码字的最小码距为2 (间隔 01 和 10 两个)…

IOU指标

IOU:全称 intersection over union 交并比,两个区域真实框和预测框之间的交集比他们之间的总面积-交集的 IOU指标:通常用于评估计算机视觉任务中的模型性能,特别是目标检测和图像分割。一个较高的IoU值意味着模型的定位和分割精度更好。

Redis安装管理, RDB, AOF ubuntu使用

1.1 Redis 基础redis单线程处理用户请求,不用加锁。其他线程做别的工作1.2 Redis 安装 Ubuntu 安装 Redis 范例:基于官方仓库包安装 (可以安装最新版本)#官方地址 https://redis.io/docs/install/install-redis/install-redis-on-linux/#导入key [root@ubuntu2204 ~]#curl -f…

查找和管理数据库的具体步骤

登录MySQL命令行使用SSH连接到服务器。 登录MySQL命令行:bashmysql -u root -p输入MySQL root用户的密码。查看数据库列表在MySQL命令行中查看所有数据库:sqlSHOW DATABASES;选择织梦CMS数据库选择织梦CMS使用的数据库:sqlUSE dedecmsv56gbk;查看数据库表查看织梦CMS数据库中…

DedeCMS Error Track:DedeCMS错误警告:连接数据库失败

当织梦CMS(DedeCMS)出现“连接数据库失败”的错误时,可以通过以下几个步骤进行排查和解决: 1. 检查数据库配置文件打开配置文件打开织梦CMS的数据库配置文件 include/config.inc.php。 使用FTP工具或SSH连接到服务器,然后打开该文件。检查配置信息确认数据库配置信息是否正…

SpringMVC内容

SpringMVC简介 SpringMVC(Model View Controller) 是以Servlet API为基础的 Web 框架并可以部署到 Servlet容器(比如:Tomcat),是控制层框架,主要负责与前端交互,接收前端的参数,在服务层进行交互,并把结果返回会前端页面。 SpringMVC工作原理当发送请求的时候,Dis…

Linux系统安装Pycharm专业版【附破解方法】

​写在前面 本教程适用于 Pycharm 2022.2.3 以下所有版本 一、版本信息 虚拟机产品:VMware Workstation 17 Pro 虚拟机版本:17.0.0 build-20800274 ISO映像文件:ubuntukylin-22.04-pro-amd64.iso Pycharm版本:PyCharm 2022.3.3 (Professional Edition) 资源链接:https:/…

谷歌收录批量查询,谷歌收录批量查询的方法步骤

谷歌收录批量查询是网站管理员和SEO专家常用的一种方法,用于同时查询多个页面或网站在谷歌搜索引擎中的收录情况。以下是几种常见的谷歌收录批量查询方法及其步骤: 一、使用Google Search Console(谷歌搜索控制台) 虽然Google Search Console主要面向单个网站的监控和管理,…

怎么查看网站是否被谷歌收录,查看网站是否被谷歌收录的快速检测方法

查看网站是否被谷歌收录,有多种快速检测方法可供选择。以下是一些常用的方法: 一、使用“site:”指令 打开谷歌搜索引擎:在浏览器中打开Google.com,确保使用的是谷歌的官方搜索引擎。 输入查询指令:在搜索框中输入“site:”加上你的网站域名(注意使用英文状态下的冒号,并…

10 月 4 日 S 组 风 雨 大 作

智障行为+2T1 T2 T3 T40 0 0 0好吧至少下一次不会考更低了 T1 你有个 n 个点 m 条边的无向图,每条边都有红蓝两种颜色中的一种,保证红色的边形成了这个图的一个生成树。 你希望给这些边赋上边权,保证边权是 1 ∼ m 的排列,使得红色的边是最小生成树。 希望这些边权形成的序…

南沙C++信奥赛陈老师解一本通题: 1828:【02NOIP提高组】均分纸牌

​【题目描述】有n堆纸牌,编号分别为 1,2,…,n。每堆上有若干张,但纸牌总数必为nn的倍数。可以在任一堆上取若干张纸牌,然后移动。 移牌规则为:在编号为1的堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 n 的堆上取的纸牌,只能移到编号为n−1的堆上;其他堆上取的纸…