当前位置:   article > 正文

Spring Boot集成shiro之使用redis缓存demo

Spring Boot集成shiro之使用redis缓存demo

1.背景

上次发了这篇文章《Spring Boot集成Shiro快速入门Demo》后,有网友“just.blue”后台反馈集成redis有点问题,今天特地把集成过程发出来

2.为什么要使用cache

用来减轻数据库的访问压力,从而提升查询效率。

3.Shiro使用Redis做缓存

redis环境准备

参照代码工程li面redis模块里面docker,按照要求启动即可

引入pom,xml

  1. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>

redis配置

  1. spring:
  2. redis:
  3. database: 0
  4. port: 6379
  5. host: 127.0.0.1
  6. password: 123456
  7. timeout=3000:
  8. jedis:
  9. pool:
  10. max-active: 8
  11. max-idle: 8
  12. max-wait: -1
  13. min-idle: 0

cache接口实现

创建RedisCacheManager实现CacheManager接口

  1. package com.et.shiro.cache;
  2. import org.apache.shiro.cache.Cache;
  3. import org.apache.shiro.cache.CacheException;
  4. import org.apache.shiro.cache.CacheManager;
  5. public class RedisCacheManager implements CacheManager {
  6. @Override
  7. public <K, V> Cache<K, V> getCache(String cacheKey) throws CacheException {
  8. return new RedisCache<>(cacheKey);
  9. }
  10. }

创建RedisCache实现Cache接口

  1. package com.et.shiro.cache;
  2. import org.apache.shiro.cache.Cache;
  3. import org.apache.shiro.cache.CacheException;
  4. import org.springframework.data.redis.core.RedisTemplate;
  5. import org.springframework.data.redis.serializer.StringRedisSerializer;
  6. import java.util.Collection;
  7. import java.util.Set;
  8. public class RedisCache<K, V> implements Cache<K, V> {
  9. private String cacheName;
  10. public RedisCache() {
  11. }
  12. public RedisCache(String cacheName) {
  13. this.cacheName = cacheName;
  14. }
  15. private RedisTemplate getRedisTemplate() {
  16. RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
  17. redisTemplate.setKeySerializer(new StringRedisSerializer());
  18. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  19. return redisTemplate;
  20. }
  21. @Override
  22. public V get(K k) throws CacheException {
  23. return (V) getRedisTemplate().opsForHash().get(this.cacheName,k.toString());
  24. }
  25. @Override
  26. public V put(K k, V v) throws CacheException {
  27. getRedisTemplate().opsForHash().put(this.cacheName,k.toString(), v);
  28. return null;
  29. }
  30. @Override
  31. public V remove(K k) throws CacheException {
  32. return (V) getRedisTemplate().opsForHash().delete(this.cacheName,k.toString());
  33. }
  34. @Override
  35. public void clear() throws CacheException {
  36. getRedisTemplate().opsForHash().delete(this.cacheName);
  37. }
  38. @Override
  39. public int size() {
  40. return getRedisTemplate().opsForHash().size(this.cacheName).intValue();
  41. }
  42. @Override
  43. public Set<K> keys() {
  44. return getRedisTemplate().opsForHash().keys(this.cacheName);
  45. }
  46. @Override
  47. public Collection<V> values() {
  48. return getRedisTemplate().opsForHash().values(this.cacheName);
  49. }
  50. }

获取bean工具类

  1. package com.et.shiro.cache;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.ApplicationContextAware;
  5. import org.springframework.stereotype.Component;
  6. @Component
  7. public class ApplicationContextUtil implements ApplicationContextAware {
  8. private static ApplicationContext applicationContext;
  9. @Override
  10. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  11. this.applicationContext = applicationContext;
  12. }
  13. public static <T> T getBean(String beanName) {
  14. return (T)applicationContext.getBean(beanName);
  15. }
  16. public static <T> T getBean(Class<T> className) {
  17. return applicationContext.getBean(className);
  18. }
  19. }

由于自定义realm中认证所需要的盐值内部并没有实现序列化接口,所以我们需要自己定一个MyByteSource继承SimpleByteSource并实现Serializable接口

  1. package com.et.shiro.config;
  2. import org.apache.shiro.util.SimpleByteSource;
  3. import java.io.Serializable;
  4. public class MyByteSource extends SimpleByteSource implements Serializable {
  5. public MyByteSource(String string) {
  6. super(string);
  7. }
  8. }

在自定义的Realm中需要在认证的方法中,改写salt的处理。

  1. @Override
  2. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
  3. throws AuthenticationException {
  4. System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
  5. String username = (String)token.getPrincipal();
  6. System.out.println(token.getCredentials());
  7. //query user by username
  8. //in here ,you can cache some data for efficient
  9. UserInfo userInfo = userInfoService.findByUsername(username);
  10. System.out.println("----->>userInfo="+userInfo);
  11. if(userInfo == null){
  12. return null;
  13. }
  14. SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
  15. userInfo, //username
  16. userInfo.getPassword(), //password
  17. new MyByteSource(userInfo.getCredentialsSalt()),
  18. //ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
  19. getName() //realm name
  20. );
  21. return authenticationInfo;
  22. }

注意实体类(角色类,用户类,权限类)要记得实现Serializable接口 最后在Shiro配置类中开启缓存,使用我们自己定义的RedisManager

  1. @Bean
  2. public MyShiroRealm myShiroRealm(){
  3. MyShiroRealm myShiroRealm = new MyShiroRealm();
  4. myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());// 设置解密规则
  5. // 开启全局缓存
  6. myShiroRealm.setCachingEnabled(true);
  7. // 开启认证缓存
  8. myShiroRealm.setAuthenticationCachingEnabled(true);
  9. // 设置认证缓存管理的名字
  10. myShiroRealm.setAuthenticationCacheName("authenticationCache");
  11. // 开启授权缓存管理
  12. myShiroRealm.setAuthorizationCachingEnabled(true);
  13. // 设置授权缓存管理的名字
  14. myShiroRealm.setAuthorizationCacheName("authorizationCache");
  15. // 开启Redis缓存
  16. myShiroRealm.setCacheManager(new RedisCacheManager());
  17. return myShiroRealm;
  18. }

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

4.测试

启动项目,访问http://127.0.0.1:8088/userInfo/userAdd,会跳转到登录页,输入admin 123456,查看redis是否缓存了

538

登录用户,第一次会从数据库中查询,并通过RedisTemplate的put方法将用户信息装入缓存,下次再刷新首页就会从redis中查询权限,授权等信息。退出时会调用RedisTemplate中的remove方法清除向对应的用户缓存。

5.引用

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/647694
推荐阅读
相关标签
  

闽ICP备14008679号