【Shiro第六篇】SpringBoot + Shiro集成缓存功能
目录
一、概述
二、Shiro集成Redis实现缓存
三、Shiro集成Ehcache实现缓存
四、总结
一、概述
Shiro 提供了类似于 Spring 的 Cache 抽象,即 Shiro 本身不实现 Cache,但是对 Cache 进行了又抽象,方便更换不同的底层 Cache 实现。
Shiro 提供的 Cache 接口:
public interface Cache<K, V> {//根据Key获取缓存中的值public V get(K key) throws CacheException;//往缓存中放入key-value,返回缓存中之前的值public V put(K key, V value) throws CacheException; //移除缓存中key对应的值,返回该值public V remove(K key) throws CacheException;//清空整个缓存public void clear() throws CacheException;//返回缓存大小public int size();//获取缓存中所有的keypublic Set<K> keys();//获取缓存中所有的valuepublic Collection<V> values();
}
Shiro 提供的 CacheManager 接口:
public interface CacheManager {//根据缓存名字获取一个Cachepublic <K, V> Cache<K, V> getCache(String name) throws CacheException;
}
Shiro 还提供了 CacheManagerAware 用于注入 CacheManager:
public interface CacheManagerAware {//注入CacheManagervoid setCacheManager(CacheManager cacheManager);
}
Shiro 内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如 Realm)是否实现了 CacheManagerAware 并自动注入相应的 CacheManager。
在上一篇文章【使用Shiro实现用户授权功能】中,我们通过在doGetAuthorizationInfo(PrincipalCollection principalCollection)方法中,每次都去查询用户对应的角色和权限信息,实际上对于一个用户来说,其权限在短时间内基本是不会变化的。因此,Shiro提供了缓存功能,可以将权限缓存起来,避免频繁访问数据库获取权限信息,本篇文章主要介绍基于Redis和Ehcache缓存的实现,下面我们来看具体的实现。
二、Shiro集成Redis实现缓存
【a】引入redis-shiro依赖
<!-- shiro-redis -->
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version>
</dependency>
<!-- 对象池,使用redis时必须引入 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>
【b】application.yml中加入redis的配置
spring:redis:host: localhostport: 6379timeout: 0mslettuce:pool:# 连接池最大连接数(使用负值表示没有限制) 默认 8max-active: 8# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1max-wait: -1ms# 连接池中的最大空闲连接 默认 8max-idle: 8# 连接池中的最小空闲连接 默认 0min-idle: 0
【c】在Shiro全局配置类中配置Redis缓存管理器以及redis管理器
/*** 配置Redis缓存管理器*/
@Bean
public RedisCacheManager redisCacheManager() {RedisCacheManager redisCacheManager = new RedisCacheManager();//设置redis管理器redisCacheManager.setRedisManager(redisManager());return redisCacheManager;
}/*** 配置redis管理器*/
@Bean
public RedisManager redisManager() {RedisManager redisManager = new RedisManager();//设置一小时超时,单位是秒redisManager.setExpire(3600);return redisManager;
}
【d】将Redis缓存管理器加入给SecurityManager安全管理器管理
//设置缓存管理器
defaultWebSecurityManager.setCacheManager(redisCacheManager());
【e】新增一个需要访问权限的接口
@RequiresPermissions(value = "user:list")
@RequestMapping("/userList")
public String userList(){return "userList";
}
新建userList.html:
<!doctype html><!--注意:引入thymeleaf的名称空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
userList page
</body>
</html>
success.html中加入如下超链接:
<div>跳转到userList.html: <a href="/userList">userList.html</a><br></div>
【f】启动项目
Caused by: java.lang.ClassNotFoundException: org.apache.shiro.event.EventBusat java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_121]at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_121]at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_121]at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_121]... 25 common frames omitted
可见,项目启动报错:ClassNotFoundException: org.apache.shiro.event.EventBus。因为Maven依赖的jar包中缺少了EventBus这个class文件,原来maven工程中已经依赖了shiro-core1.4.0的版本 ,在shiro-redis依赖中使用了shiro-core-1.2版本,把1.4版本的排除了出去, 而这个类要在1.3版本上才有,所以需要排除1.2版本。
<!-- shiro-redis -->
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version><exclusions><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion></exclusions>
</dependency>
重新启动项目,这次启动没有报错了,但是当你访问list.html页面时,页面报如下的错误:
tried to access method redis.clients.jedis.JedisPool.returnResource
翻译一下,其实指的就是尝试从类org.crazycake.shiro.RedisManager访问方法,但是访问不到。
原因其实是redis.clients:jedis:3.1.0版本种的returnResource()方法访问修饰符变为protected,所以我们换低一点的版本即可:
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version><exclusions><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion><exclusion><artifactId>shiro-core</artifactId><groupId>org.apache.shiro</groupId></exclusion><exclusion><artifactId>jedis</artifactId><groupId>redis.clients</groupId></exclusion></exclusions>
</dependency>
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version>
</dependency>
再次重启项目,使用admin/123456进行登录:
依次访问userList.html和list.html两个需要授权的页面,如下图:
注意:需要首先启动好Redis服务,否则项目连不上Redis,会报错。
如下图,可以看到后台只打印出一次从数据库查询获取权限的日志信息,证明我们的redis缓存起效果。
以上就是关于Shiro整合Redis实现用户权限缓存功能,接下来我们再来看另外一种实现方式:Shiro整合Ehcache实现用户权限缓存功能。
三、Shiro集成Ehcache实现缓存
【a】引入Shiro跟Ehcachae整合相关依赖
<!-- shiro ehcache -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.3.2</version>
</dependency>
<!-- ehchache -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId>
</dependency>
【b】新建Ehcache配置文件
在resource/config路径下新建shiro-ehcache-config.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"updateCheck="false"><diskStore path="java.io.tmpdir/Tmp_EhCache"/><!--defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象eternal:代表对象是否永不过期timeToIdleSeconds:最大的发呆时间timeToLiveSeconds:最大的存活时间overflowToDisk:是否允许对象被写入到磁盘--><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!--cache:为指定名称的对象进行缓存的特殊配置name:指定对象的完整名--><!-- 登录记录缓存锁定1小时 --><cachename="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"/></ehcache>
【c】Shiro全局配置类中配置Ehcache
/*** Ehcache缓存管理器* @return*/
@Bean
@Primary //指定ehcache为主要的缓存管理器
public EhCacheManager ehCacheManager() {EhCacheManager ehCacheManager = new EhCacheManager();ehCacheManager.setCacheManagerConfigFile("classpath:config/shiro-ehcache-config.xml");return ehCacheManager;
}
【d】将缓存对象注入到SecurityManager中
//设置EhCacheManager缓存管理员
defaultWebSecurityManager.setCacheManager(ehCacheManager());
【e】启动项目测试
使用admin/123456进行登录:
依次访问userList.html和list.html两个需要授权的页面,如下图:
如下图,可以看到后台只打印出一次从数据库查询获取权限的日志信息,同样证明我们的ehcache缓存起效果。
注意,需要注释掉前面在shiro全局配置类中注入的redis缓存,否则启动会报错:因为发现两个缓存管理器。当然如果不注释的话,也可以使用@Primary注解指定某个缓存管理器为主要的管理器。
扩展知识:
Ehcache的配置详细说明如下:
(一)、以下属性是必须的:
1、name: Cache的名称,必须是唯一的(ehcache会把这个cache放到HashMap里)。
2、maxElementsInMemory:在内存中缓存的element的最大数目。
3、maxElementsOnDisk:在磁盘上缓存的element的最大数目,默认值为0,表示不限制。
4、eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。
5、overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。
(二)、以下属性是可选的:
1、timeToIdleSeconds: 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。
2、timeToLiveSeconds: 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。
3、diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。
4、diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。
5、diskSpoolBufferSizeMB: DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。
6、memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。
(三)、缓存的3 种清空策略 :
1、FIFO ,First In First Out (先进先出);
2、LFU , Less Frequently Used (最少使用)。意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存;
3、LRU ,Least Recently Used(最近最少使用)。 (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存;
四、总结
本篇文章主要总结了Shiro提供的缓存功能,能大大减少授权的时候对数据库的查询,通过配置两种缓存管理器:Redis和Ehcache缓存管理器。在实际项目中,可以根据需求配置两种缓存管理器,实现用户高效授权操作。
【Shiro第六篇】SpringBoot + Shiro集成缓存功能相关推荐
- 七十六、SpringBoot 的数据缓存cache+Redis(三)
@Author:Runsen 来源:尚硅谷 下面建议读者学习尚硅谷的B站的SpringBoot视频,我是学雷丰阳视频入门的. 具体链接如下:B站尚硅谷SpringBoot教程 文章目录 Redis P ...
- 【Shiro】六、Apache Shiro Session管理
1.Session的介绍 关于Session 会话:从启动一个Session到关闭这个Session作为一个会话,是对客户端和服务器端交互的一种封装,带有时效性 会话的产生: 一般从容器中产生 Web ...
- Shiro第四篇【Shiro与Spring整合、快速入门、Shiro过滤器、登陆认证】
Spring与Shiro整合 导入jar包 shiro-web的jar. shiro-spring的jar shiro-code的jar 快速入门 shiro也通过filter进行拦截.filter拦 ...
- springboot+shiro+redis+jwt实现多端登录:PC端和移动端同时在线(不同终端可同时在线)
前言 之前写了篇 springboot+shiro+redis多端登录:单点登录+移动端和PC端同时在线 的文章,但是token用的不是 jwt 而是 sessionID,虽然已经实现了区分pc端和移 ...
- SpringBoot集成Shiro前后端分离使用redis做缓存
文章目录 一 .shiro介绍 1.基础介绍 2.基本功能点 3.基本流程图 二. 常用的权限管理表关系 2.1. 表组成 2.2. 表结构 三.实战案例 3.1. 案例介绍 3.2. 依赖 3.3. ...
- springboot shiro和freemarker集成之权限控制完全参考手册(跳过认证,登录由三方验证,全网首发)...
本文主要考虑单点登录场景,登录由其他系统负责,业务子系统只使用shiro进行菜单和功能权限校验,登录信息通过token从redis取得,这样登录验证和授权就相互解耦了. 用户.角色.权限进行集中式管理 ...
- Shiro和SpringBoot简单集成
Shiro是一种简单的安全框架,可以用来处理系统的登录和权限问题. 本篇记录一下Spring Boot和Shiro集成,并使用Jwt Token进行无状态登录的简单例子. 参考Demo地址,此Demo ...
- Spring Boot教程(十六):Spring Boot集成shiro
Apache Shiro™是一个功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理.借助Shiro易于理解的API,您可以快速轻松地保护任何应用程序 - 从最小的移动应用程序到 ...
- SpringBoot系列 - 集成Shiro权限管理
Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,相比Spring Security而言相当简单, 可能没有Spring Security做的功能强大, ...
- Shiro教程_2 Shiro+SpringBoot+Mysql+Redis(缓存)
源代码 https://gitee.com/fakerlove/Shiro Shiro+SpringBoot+Mysql+Redis(缓存) 1. 添加依赖 <?xml version=&quo ...
最新文章
- playframework学习笔记1 -- 开发环境和第一个工程
- Kafka日志清理之Log Deletion
- RocketMQ消息轨迹-设计篇
- 天平应什么放置_电子天平讲义全解(使用/维护/分类)
- Rabin-Karp字符串查找算法学习:poj1200
- 带有LLVM的eBPF组件
- 用Unity的Animation播放Animator动画Clip
- as 与 is 的区别
- 真正优秀的人是如何度过假期的
- button执行onclick函数_JavaScript 函数定义与调用
- 论大学学霸是怎样炼成的……
- python调用百度云文字识别
- pyhton——爬小说网站(顶点最强国防生)
- LensFlare Studio for Mac 6.3 镜头光晕特效软件 破解版下载
- 虚拟数字人营销时代来临,虚拟主播与真人主持直播间同台互动
- 图表说话之解析excel商务饼图做法
- 计算机无法连接到宽带,win10提示无法连接到宽带连接不能建立到远程计算机怎么解决...
- Appium 常用初始化启动参数 Capability详解
- 月薪40K起,什么是Python全栈工程师?全栈工程师薪资为何这么高?
- Using Sketch with Framer 使用Sketch与Framer Lynda课程中文字幕
热门文章
- java匿名内部类 内部类_java中的匿名内部类详细总结
- 计算机信息与自然科学,郑旭飞 - 计算机与信息科学学院 - Powered by 西南大学
- 机器学习- 吴恩达Andrew Ng Week9 知识总结 Recommender Systems
- 极客大学架构师训练营 数据结构与算法 平衡二叉树 红黑树 动态规划 遗传算法 第15课 听课总结
- 服务器系统更新失败进不了系统,第五人格更新后进不去怎么办 更新连接服务器失败...
- 2021-09-1427. 移除元素
- 从有序数组中找出某个数出现的次数
- 谷歌浏览器翻译设置_谷歌翻译网站最近有点“小脾气”
- 【知识图谱系列】GCNII模型探索DeepGNN的Over-Smoothing问题
- android studio for android learning (十一) 利用bundle在activity之间进行数据传递示例