【Shiro学习】一一一一集成redis缓存(一)

Shiro学习笔记_01:集成redis缓存

 

1.引入依赖

 <dependency>
     <groupId>org.apache.shiro</groupId>
     <artifactId>shiro-spring</artifactId>
     <version>${shiro.version}</version>
 </dependency>
 <dependency>
     <groupId>org.apache.shiro</groupId>
     <artifactId>shiro-ehcache</artifactId>
     <version>${shiro.version}</version>
 </dependency>

2.配置yml文件

image-20210611211045976

3.配置缓存文件

image-20210611221742756

观察一下原来的 Realm配置

当用户通过了AuthrenticationInfo(认证)之后会进行AuthorizationInfo(授权),但是此时如果每个用都在进入的时候进行查询操作数据,这样就会让数据库的吞吐量加大最终导致数据库挂掉。所以现在就需要做缓存来支持我们需要的功能。

这是根据角色(role)来获取对应的权限(permission)

image-20210611211353646

3.1查看默认缓存

首先查看一下我们本来的Realm配置信息

下图是使用的最原始EhCacheManager配置的缓存信息,但是我们需要的是将缓存放入Redis中

image-20210611212207494

3.2配置RedisCache

我们查看一下EhCacheManager这个类的信息

image-20210611212725718

默认实现了shiro提供的CacheManager

image-20210611212810720

3.3自定义RedisCache

根据上面的信息可以得知,如果我们需要定义一个RedisCache就必须实现一下shiro提供的CacheManager

image-20210611213041614

返回的值是一个Cache<K, V>,我们可以查看一下它的实现类有什么

image-20210611213419994

是不是和上面的EhCacheManager()似曾相识的感觉?所以问题解决,我们可以进行实现Cache来重写里面的方法,实现自定义的目的

 /**
  * description: RedisCache 缓存配置
  * date: 2021/6/11 16:43
  * author: XiaoCoder
  * version: 1.0
  */
 ​
 public class RedisCache<k, v> implements Cache<k, v> {
 ​
     private String cacheName;
 ​
     public RedisCache() {
     }
 ​
     public RedisCache(String cacheName) {
         this.cacheName = cacheName;
     }
 ​
     @Override
     public v get(k k) throws CacheException {
         System.out.println("get k:" + k);
         return (v) getRedisTemplate().opsForValue().get(k.toString());
     }
 ​
     @Override
     public v put(k k, v v) throws CacheException {
         System.out.println("put key:" + k);
         System.out.println("put value:" + v);
         getRedisTemplate().opsForValue().set(k.toString(), v);
         return null;
     }
 ​
     @Override
     public v remove(k k) throws CacheException {
         return (v) getRedisTemplate().opsForHash().delete(this.cacheName, k.toString());
     }
 ​
     @Override
     public void clear() throws CacheException {
         System.out.println("=============clear==============");
         getRedisTemplate().delete(this.cacheName);
     }
 ​
     @Override
     public int size() {
         return getRedisTemplate().opsForHash().size(this.cacheName).intValue();
     }
 ​
     @Override
     public Set<k> keys() {
         return getRedisTemplate().opsForHash().keys(this.cacheName);
     }
 ​
     @Override
     public Collection<v> values() {
         return getRedisTemplate().opsForHash().values(this.cacheName);
     }
 ​
     private RedisTemplate getRedisTemplate() {
         // 这里是通过自定义的获取bean的方法,进行转化得到的数据
         RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
         // Creates a new StringRedisSerializer using UTF-8.序列化方式
         redisTemplate.setKeySerializer(new StringRedisSerializer());
         // Creates a new StringRedisSerializer using UTF-8.序列化方式
         redisTemplate.setHashKeySerializer(new StringRedisSerializer());
         return redisTemplate;
     }
 ​
 }

获取bean的工具类

image-20210611213915109

3.4 配置实体类的序列化

让实体类role,permission,user实现Serializable

3.4.1 注意:salt(盐)

盐也需要进行相同的序列号。如果不序列化盐,在Redis缓存和JVM数据进行交互的时候会报错

 /**
  * 认证
  *
  * @param token
  * @return
  * @throws AuthenticationException
  */
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
     UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
     String account = usernamePasswordToken.getUsername();
     User user = userService.getOne(new QueryWrapper<User>().eq("username", account));
     if (user == null) {
         return null;
     }
     return new SimpleAuthenticationInfo(user, user.getPassword(), new MyByteSource(user.getSalt()), this.getName());
 }

创建一个MyByteSource类实现ByteSource, Serializable 重写 Shiro默认的序列化规则

 /**
  * description: MyByteSource
  * date: 2021/6/11 18:45
  * author: XiaoCoder
  * version: 1.0
  */
 public class MyByteSource implements ByteSource, Serializable {
     private byte[] bytes;
     private String cachedHex;
     private String cachedBase64;
 ​
     public MyByteSource() {
 ​
     }
 ​
     public MyByteSource(byte[] bytes) {
         this.bytes = bytes;
     }
 ​
     public MyByteSource(char[] chars) {
         this.bytes = CodecSupport.toBytes(chars);
     }
 ​
     public MyByteSource(String string) {
         this.bytes = CodecSupport.toBytes(string);
     }
 ​
     public MyByteSource(ByteSource source) {
         this.bytes = source.getBytes();
     }
 ​
     public MyByteSource(File file) {
         this.bytes = (new MyByteSource.BytesHelper()).getBytes(file);
     }
 ​
     public MyByteSource(InputStream stream) {
         this.bytes = (new MyByteSource.BytesHelper()).getBytes(stream);
     }
 ​
     public static boolean isCompatible(Object o) {
         return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
     }
 ​
     public byte[] getBytes() {
         return this.bytes;
     }
 ​
     public boolean isEmpty() {
         return this.bytes == null || this.bytes.length == 0;
     }
 ​
     public String toHex() {
         if (this.cachedHex == null) {
             this.cachedHex = Hex.encodeToString(this.getBytes());
         }
 ​
         return this.cachedHex;
     }
 ​
     public String toBase64() {
         if (this.cachedBase64 == null) {
             this.cachedBase64 = Base64.encodeToString(this.getBytes());
         }
 ​
         return this.cachedBase64;
     }
 ​
     public String toString() {
         return this.toBase64();
     }
 ​
     public int hashCode() {
         return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0;
     }
 ​
     public boolean equals(Object o) {
         if (o == this) {
             return true;
         } else if (o instanceof ByteSource) {
             ByteSource bs = (ByteSource) o;
             return Arrays.equals(this.getBytes(), bs.getBytes());
         } else {
             return false;
         }
     }
 ​
     private static final class BytesHelper extends CodecSupport {
         private BytesHelper() {
         }
 ​
         public byte[] getBytes(File file) {
             return this.toBytes(file);
         }
 ​
         public byte[] getBytes(InputStream stream) {
             return this.toBytes(stream);
         }
     }
 ​
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值