Apache Shiro 分布式架构下Redis实现Session 的共享

释放双眼,带上耳机,听听看~!

2018年03月14日 16:22:50

阅读数:16

转载地址:https://blog.csdn.net/yr_xiaozheng/article/details/79556137

参考资料:http://blog.csdn.net/lishehe/article/details/45223823

写的非常棒,只是缺少了几个工具类,我在这里给出了自己的代码,方便用到。

  1.  redis.properties

[java] view plain
 copy

  1. redis.host=

127.0
.
0.1
  

  1. redis.port=

6379
  

  1. redis.

default
.db=
2
  

  1. redis.timeout=

100000
  

  1. redis.maxIdle=

100
  

  1. redis.maxWaitMillis=

30000
  

  1. redis.testOnBorrow=

true
  

2. applicationContext-shiro.xml

[html] view plain
 copy

  1. <?

xml
 
version

"1.0"
 
encoding

"UTF-8"
?>
  

  1. <

beans
 
xmlns

"http://www.springframework.org/schema/beans"
  

  1.        

xmlns:xsi

"http://www.w3.org/2001/XMLSchema-instance"
  

  1.        

xsi:schemaLocation

"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"

  

  1.     

<
bean
 
id

"securityManager"
 
class

"org.apache.shiro.web.mgt.DefaultWebSecurityManager"

  

  1.         

<!–配置 session 管理–>

  

  1.         

<
property
 
name

"sessionManager"
 
ref

"sessionManager"
/>
  

  1.         

<!–配置 记住我–>

  

  1.         

<
property
 
name

"rememberMeManager"
 
ref

"rememberMeManager"
/>
  

  1.         

<!– 配置多个Realm的登录认证 –>

  

  1.         

<
property
 
name

"authenticator"
 
ref

"authenticator"
/>
  

  1.         

<!– 配置多个Realm的权限认证 –>

  

  1.         

<
property
 
name

"authorizer"
 
ref

"authorizer"
/>
  

  1.   
  2.   
  3.         

<!– redis缓存 –>

  

  1.         

<
property
 
name

"cacheManager"
 
ref

"redisCacheManager"
 
/>
  

  1.     

</
bean

  

  1.   
  2.     

<!–配置多个 realm 的权限权限认证–>

  

  1.     

<
bean
 
id

"authorizer"
 
class

"org.apache.shiro.authz.ModularRealmAuthorizer"

  

  1.         

<
property
 
name

"realms"

  

  1.             

<
list

  

  1.                 

<!–这个实现权限匹配的方法–>

  

  1.                 

<
ref
 
bean

"myRealm"
/>
  

  1.             

</
list

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!– 配置多个Realm –>

  

  1.     

<
bean
 
id

"authenticator"
 
class

"org.apache.shiro.authc.pam.ModularRealmAuthenticator"

  

  1.   
  2.         

<!–验证的时候,是用迭代器,所以可以认为验证的顺序就是这个 list 的顺序–>

  

  1.         

<
property
 
name

"realms"

  

  1.             

<
list

  

  1.                 

<!–<ref bean="otherRealm"/>–>

  

  1.                 

<
ref
 
bean

"myRealm"
/>
  

  1.             

</
list

  

  1.         

</
property

  

  1.         

<
property
 
name

"authenticationStrategy"

  

  1.   
  2.             

<!–所有 realm 认证通过才算登录成功–>

  

  1.             

<!–<bean id="authenticationStrategy" class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"/>–>

  

  1.             

<!–验证某个 realm 成功后直接返回,不会验证后面的 realm 了–>

  

  1.             

<
bean
 
id

"authenticationStrategy"
 
class

"org.apache.shiro.authc.pam.FirstSuccessfulStrategy"
/>
  

  1.             

<!–所有的 realm 都会验证,其中一个成功,也会继续验证后面的 realm,最后返回成功–>

  

  1.             

<!–<bean id="authenticationStrategy" class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"/>–>

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!–自定义 MyRealm,登录的认证入口 ,需要继承AuthorizingRealm,项目中会体现–>

  

  1.     

<
bean
 
id

"myRealm"
 
class

"com.tms.shiro.MyRealm"

  

  1.         

<!– 配置密码匹配器 –>

  

  1.         

<
property
 
name

"credentialsMatcher"

  

  1.             

<
bean
 
class

"org.apache.shiro.authc.credential.HashedCredentialsMatcher"

  

  1.                 

<!– 加密算法为SHA-256 –>

  

  1.                 

<
property
 
name

"hashAlgorithmName"
 
value

"SHA-256"
/>
  

  1.                 

<!– 加密迭代次数 –>

  

  1.                 

<
property
 
name

"hashIterations"
 
value

"1024"
/>
  

  1.                 

<!–是否存储散列后的密码为16进制,为 true:.toHex(),为 false:.toBase64()–>

  

  1.                 

<
property
 
name

"storedCredentialsHexEncoded"
 
value

"false"
/>
  

  1.             

</
bean

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!–rememberMeManager管理 配置–>

  

  1.     

<
bean
 
id

"rememberMeManager"
 
class

"org.apache.shiro.web.mgt.CookieRememberMeManager"

  

  1.         

<
property
 
name

"cookie"

  

  1.             

<
bean
 
class

"org.apache.shiro.web.servlet.SimpleCookie"

  

  1.                 

<!–设置超时时间 单位 秒,一天=86400–>

  

  1.                 

<
constructor-arg
 
value

"shiro-cookie"
/>
  

  1.                 

<
property
 
name

"maxAge"
 
value

"86400"
/>
  

  1.                 

<
property
 
name

"httpOnly"
 
value

"true"
/>
  

  1.             

</
bean

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!–session管理 配置–>

  

  1.     

<!–<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">–>

  

  1.     <!–

<
bean
 
id

"sessionManager"
 
class

"com.tms.shiro.SessionManager"

  

  1.         <!–session 过期时间 单位 毫秒,

2400000

40min

  

  1.         

<
property
 
name

"globalSessionTimeout"
 
value

"2400000"
/>
  

  1.   
  2.         <!–有需要可以自行配置–

  

  1.         <!–

<
property
 
name

"cacheManager"
 
ref

"xxxx"

</
property

  

  1.         <!–有需要可以自行配置–

  

  1.         <!–

<
property
 
name

"sessionDAO"
 
ref

"xxx"

</
property

  

  1.   
  2.         

<
property
 
name

"sessionIdCookie"
 
ref

"sessionIdCookie"
/>
  

  1.     

</
bean

  

  1.   
  2.     

<!– 自定义sessionId 防止同tomcat 等容器冲突 –>

  

  1.     

<
bean
 
id

"sessionIdCookie"
 
class

"org.apache.shiro.web.servlet.SimpleCookie"

  

  1.         

<
constructor-arg
 
value

"token"
/>
  

  1.         

<
property
 
name

"maxAge"
 
value

"86400"
/>
  

  1.         

<
property
 
name

"path"
 
value

"/"
/>
  

  1.   
  2.     

</
bean

  

  1.   
  2.     

<!–shiro 请求拦截器,这里的 bean id 一定要对应 web.xml 中的filter-name,否则找不到这个拦截器–>

  

  1.     

<
bean
 
id

"shiroFilter"
 
class

"com.tms.shiro.MyShiroFilterFactoryBean"

  

  1.         

<
property
 
name

"securityManager"
 
ref

"securityManager"
/>
  

  1.         

<!–登录地址–>

  

  1.         

<
property
 
name

"loginUrl"
 
value

"login"
/>
  

  1.         

<!–登录成功跳转的地址–>

  

  1.         

<
property
 
name

"successUrl"
 
value

"/userAction_findList"
/>
  

  1.         

<!–权限认证失败跳转的地址–>

  

  1.         

<
property
 
name

"unauthorizedUrl"
 
value

"error"
/>
  

  1.         

<!–需要权限拦截的路径–>

  

  1.         

<
property
 
name

"filterChainDefinitions"

  

  1.             

<
value

  

  1.                 

<!–/login = anon–>

  

  1.                 

<!–/validateCode = anon–>

  

  1.                 

<!–/\*\* = authc–>

  

  1.             

</
value

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!– 保证实现了Shiro内部lifecycle函数的bean执行 ,不明觉厉,没有深究–>

  

  1.     

<
bean
 
id

"lifecycleBeanPostProcessor"
 
class

"org.apache.shiro.spring.LifecycleBeanPostProcessor"
/>
  

  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.     

<!– 自定义redisManager-redis –>

  

  1.     

<
bean
 
id

"redisCacheManager"
 
class

"com.tms.util.redis.RedisCacheManager"

  

  1.         

<
property
 
name

"redisManager"
 
ref

"redisManager"
 
/>
  

  1.     

</
bean

  

  1.     

<!– 自定义cacheManager –>

  

  1.     

<
bean
 
id

"redisCache"
 
class

"com.tms.util.redis.RedisCache"

  

  1.         

<
constructor-arg
 
ref

"redisManager"

</
constructor-arg

  

  1.     

</
bean

  

  1.   
  2.     

<
bean
 
id

"redisManager"
 
class

"com.tms.util.redis.RedisManager"

</
bean

  

  1.   
  2.     

<!– session会话存储的实现类 –>

  

  1.     

<
bean
 
id

"redisShiroSessionDAO"
 
class

"com.tms.util.redis.RedisSessionDao"

  

  1.         

<
property
 
name

"redisManager"
 
ref

"redisManager"
 
/>
  

  1.     

</
bean

  

  1.   
  2.     

<!– session管理器 –>

  

  1.     

<
bean
 
id

"sessionManager"
  

  1.           

class

"com.tms.shiro.SessionManager"

  

  1.         

<!– 设置全局会话超时时间,默认30分钟(1800000) –>

  

  1.         

<
property
 
name

"globalSessionTimeout"
 
value

"1800000"
 
/>
  

  1.         

<!– 是否在会话过期后会调用SessionDAO的delete方法删除会话 默认true –>

  

  1.         

<
property
 
name

"deleteInvalidSessions"
 
value

"true"
 
/>
  

  1.   
  2.         

<!– 会话验证器调度时间 –>

  

  1.         

<
property
 
name

"sessionValidationInterval"
 
value

"1800000"
 
/>
  

  1.   
  2.         

<!– session存储的实现 –>

  

  1.         

<
property
 
name

"sessionDAO"
 
ref

"redisShiroSessionDAO"
 
/>
  

  1.         

<!– sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID –>

  

  1.         

<
property
 
name

"sessionIdCookie"
 
ref

"sharesession"
 
/>
  

  1.         

<!– 定时检查失效的session –>

  

  1.         

<
property
 
name

"sessionValidationSchedulerEnabled"
 
value

"true"
 
/>
  

  1.     

</
bean

  

  1.   
  2.     

<!– sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID –>

  

  1.     

<
bean
 
id

"sharesession"
 
class

"org.apache.shiro.web.servlet.SimpleCookie"

  

  1.         

<!– cookie的name,对应的默认是 JSESSIONID –>

  

  1.         

<
constructor-arg
 
name

"name"
 
value

"SHAREJSESSIONID"
 
/>
  

  1.         

<!– jsessionId的path为 / 用于多个系统共享jsessionId –>

  

  1.         

<
property
 
name

"path"
 
value

"/"
 
/>
  

  1.         

<
property
 
name

"httpOnly"
 
value

"true"
/>
  

  1.     

</
bean

  

  1.   
  2.   
  3.     

<!– shiro的自带缓存管理器encahe –>

  

  1.     

<!– <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> –>

  

  1.     <!– 

<
property
 
name

"cacheManagerConfigFile"
 
value

"classpath:config/ehcache-shiro.xml"
  

  1.         

/>
 —

  

  1.     

<!– </bean> –>

  

  1.   
  2.     

<!– 开启shiro的注解,需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 –>

  

  1.     

<
bean
  

  1.             

class

"org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
  

  1.             

depends-on

"lifecycleBeanPostProcessor"

</
bean

  

  1.     

<
bean
  

  1.             

class

"org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"

  

  1.         

<
property
 
name

"securityManager"
 
ref

"securityManager"
 
/>
  

  1.     

</
bean

  

  1.   
  2. </

beans

  

  1. redis.xml

[html] view plain
 copy

  1. <?

xml
 
version

"1.0"
 
encoding

"UTF-8"
?>
  

  1. <

beans
 
xmlns

"http://www.springframework.org/schema/beans"
  

  1.        

xmlns:xsi

"http://www.w3.org/2001/XMLSchema-instance"
  

  1.        

xmlns:c

"http://www.springframework.org/schema/c"
 
xmlns:cache

"http://www.springframework.org/schema/cache"
  

  1.        

xmlns:context

"http://www.springframework.org/schema/context"
  

  1.        

xsi:schemaLocation
="http://www.springframework.org/schema/beans  

  1.         http://www.springframework.org/schema/beans/spring-beans.xsd  
  2.  http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"

  

  1.   
  2.     

<!– 加载Reids属性配置文件 ignore-unresolvable="true"–>

  

  1.     

<
context:property-placeholder
  

  1.             

location

"classpath:redis.properties"
/>
  

  1.   
  2.     

<
bean
 
id

"propertyConfigurerRedis"
  

  1.           

class

"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"

  

  1.         

<
property
 
name

"order"
 
value

"1"
/>
  

  1.         

<
property
 
name

"ignoreUnresolvablePlaceholders"
 
value

"true"
/>
  

  1.         

<
property
 
name

"systemPropertiesMode"
 
value

"1"
/>
  

  1.         

<
property
 
name

"searchSystemEnvironment"
 
value

"true"
/>
  

  1.         

<
property
 
name

"locations"

  

  1.             

<
list

  

  1.                 

<
value

classpath:redis.properties
</
value

  

  1.             

</
list

  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!–支持缓存注释, 使用key生成器–>

  

  1.     

<
bean
 
id

"redisCacheKeyGenerator"
 
class

"com.tms.util.redis.CustomRedisCacheKeyGenerator"
/>
  

  1.     

<
cache:annotation-driven
 
key-generator

"redisCacheKeyGenerator"
/>
  

  1.   
  2.   
  3.     

<!– 配置redis池,最大空闲实例数,(创建实例时)最大等待时间,(创建实例时)是否验证 –>

  

  1.     

<
bean
 
id

"jedisPoolConfig"
 
class

"redis.clients.jedis.JedisPoolConfig"

  

  1.         

<
property
 
name

"maxIdle"
 
value

"${redis.maxIdle}"
/>
  

  1.         

<
property
 
name

"testOnBorrow"
 
value

"${redis.testOnBorrow}"
/>
  

  1.         

<
property
 
name

"maxWaitMillis"
 
value

"${redis.maxWaitMillis}"
/>
  

  1.         

<
property
 
name

"minEvictableIdleTimeMillis"
 
value

"300000"
/>
  

  1.         

<
property
 
name

"numTestsPerEvictionRun"
 
value

"3"
/>
  

  1.         

<
property
 
name

"timeBetweenEvictionRunsMillis"
 
value

"6000"
/>
  

  1.     

</
bean

  

  1.   
  2.     

<
bean
 
id

"jedisConnectionFactory"
  

  1.           

class

"org.springframework.data.redis.connection.jedis.JedisConnectionFactory"

  

  1.         

<
property
 
name

"usePool"
 
value

"true"

</
property

  

  1.         

<
property
 
name

"hostName"
 
value

"${redis.host}"
/>
  

  1.         

<
property
 
name

"port"
 
value

"${redis.port}"
/>
  

  1.         

<
property
 
name

"timeout"
 
value

"${redis.timeout}"
/>
  

  1.         

<
property
 
name

"database"
 
value

"${redis.default.db}"

</
property

  

  1.   
  2.         

<
property
 
name

"poolConfig"
 
ref

"jedisPoolConfig"

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<
bean
 
id

"jedisTemplate"
 
class

"org.springframework.data.redis.core.RedisTemplate"

  

  1.         

<
property
 
name

"connectionFactory"
 
ref

"jedisConnectionFactory"

</
property

  

  1.         

<
property
 
name

"keySerializer"

  

  1.             

<
bean
 
class

"org.springframework.data.redis.serializer.StringRedisSerializer"
/>
  

  1.         

</
property

  

  1.         

<
property
 
name

"valueSerializer"

  

  1.             

<
bean
 
class

"org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"
/>
  

  1.         

</
property

  

  1.     

</
bean

  

  1.   
  2.     

<!–V2 配置cacheManager, 使用默认的 用户自定义的 RedisCacheManager  –>

  

  1.     

<
bean
 
id

"cacheManager"
 
class

"com.tms.util.redis.CustomizedRedisCacheManager"

  

  1.         

<
constructor-arg
 
ref

"jedisTemplate"
/>
  

  1.         

<!–使用前缀,使用以后,以cache的value作为redis中的namespace,缓存的键也会加入这个前缀–>

  

  1.         

<
property
 
name

"usePrefix"
 
value

"true"
/>
  

  1.   
  2.         

<!– 前缀命名,仅当usePrefix为true时才生效,本例子不使用 –>

  

  1.         

<!–<property name="cachePrefix">–>

  

  1.         

<!–<bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix">–>

  

  1.         

<!–<constructor-arg name="delimiter" value=":"/>–>

  

  1.         

<!–</bean>–>

  

  1.         

<!–</property>–>

  

  1.         

<!– 默认有效期1h ,本例子不使用–>

  

  1.         

<!–<property name="defaultExpiration" value="3600"/>–>

  

  1.     

</
bean

  

  1.   
  2. </

beans

  

  1. SerializerUtil.java

[java] view plain
 copy

  1. import

 org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;  

  1.   
  2. /** 
  3.  * @Author: 
  4.  * @Date: 2018-03-13 12:33 
  5.  * @Modified By: 
  6.  * @Description: 
  7.  */

  

  1. public

 
class
 SerializerUtil {  

  1.   
  2.     

private
 
static
 
final
 JdkSerializationRedisSerializer jdkSerializationRedisSerializer = 
new
 JdkSerializationRedisSerializer();  

  1.   
  2.     

/** 

  1.      * 序列化对象 
  2.      * @param obj 
  3.      * @return 
  4.      */

  

  1.     

public
 
static
 <T> 
byte
[] serialize(T obj){  

  1.         

try
 {  

  1.             

return
 jdkSerializationRedisSerializer.serialize(obj);  

  1.         } 

catch
 (Exception e) {  

  1.             

throw
 
new
 RuntimeException(
"序列化失败!"
, e);  

  1.         }  
  2.     }  
  3.   
  4.     

/** 

  1.      * 反序列化对象 
  2.      * @param bytes 字节数组 
  3.      * @param 
  4.      * @return 
  5.      */

  

  1.     

@SuppressWarnings
(
"unchecked"
)  

  1.     

public
 
static
 <T> T deserialize(
byte
[] bytes){  

  1.         

try
 {  

  1.             

return
 (T) jdkSerializationRedisSerializer.deserialize(bytes);  

  1.         } 

catch
 (Exception e) {  

  1.             

throw
 
new
 RuntimeException(
"反序列化失败!"
, e);  

  1.         }  

  2.     }  

  3.   

  4. }  

  5. RedisSessionDao.java

[java] view plain
 copy

  1. import

 org.apache.shiro.session.Session;  

  1. import

 org.apache.shiro.session.UnknownSessionException;  

  1. import

 org.apache.shiro.session.mgt.eis.AbstractSessionDAO;  

  1. import

 org.slf4j.Logger;  

  1. import

 org.slf4j.LoggerFactory;  

  1.   
  2. import

 java.io.Serializable;  

  1. import

 java.util.Collection;  

  1. import

 java.util.HashSet;  

  1. import

 java.util.Set;  

  1.   
  2. /** 
  3.  * @Author: 
  4.  * @Date: 2018-03-13 12:35 
  5.  * @Modified By: 
  6.  * @Description: 
  7.  */

  

  1. public

 
class
 RedisSessionDao 
extends
 AbstractSessionDAO {  

  1.   
  2.     

private
 Logger logger = LoggerFactory.getLogger(
this
.getClass());  

  1.   
  2.     

private
 RedisManager redisManager;  

  1.   
  2.     

/** 

  1.      * The Redis key prefix for the sessions 
  2.      */

  

  1.     

private
 
static
 
final
 String KEY_PREFIX = 
"shiro_redis_session:"
;  

  1.   
  2.     

private
 
byte
[] getByteKey(String key){  

  1.         

return
 key.getBytes();  

  1.     }  
  2.   
  3.     

@Override
  

  1.     

public
 
void
 update(Session session) 
throws
 UnknownSessionException {  

  1.         

this
.saveSession(session);  

  1.     }  
  2.   
  3.     

@Override
  

  1.     

public
 
void
 delete(Session session) {  

  1.         

if
 (session == 
null
 || session.getId() == 
null
) {  

  1.             logger.error(

"session or session id is null"
);  

  1.             

return
;  

  1.         }  
  2.         redisManager.del(getByteKey(KEY_PREFIX + session.getId()));  
  3.     }  
  4.   
  5.     

@Override
  

  1.     

public
 Collection<Session> getActiveSessions() {  

  1.         Set<Session> sessions = 

new
 HashSet<Session>();  

  1.         Set<

byte
[]> keys = redisManager.keys(KEY_PREFIX + 
"*"
);  

  1.         

if
(keys != 
null
 && keys.size()>
0
){  

  1.             

for
(
byte
[] key : keys){  

  1.                 Session s = (Session) SerializerUtil.deserialize(redisManager.get(SerializerUtil.deserialize(key)));  
  2.                 sessions.add(s);  
  3.             }  
  4.         }  
  5.         

return
 sessions;  

  1.     }  
  2.   
  3.     

@Override
  

  1.     

protected
 Serializable doCreate(Session session) {  

  1.         Serializable sessionId = 

this
.generateSessionId(session);  

  1.         

this
.assignSessionId(session, sessionId);  

  1.         

this
.saveSession(session);  

  1.         

return
 sessionId;  

  1.     }  
  2.   
  3.     

@Override
  

  1.     

protected
 Session doReadSession(Serializable sessionId) {  

  1.         

if
(sessionId == 
null
){  

  1.             logger.error(

"session id is null"
);  

  1.             

return
 
null
;  

  1.         }  
  2.   
  3.         Session s = (Session)redisManager.get(getByteKey(KEY_PREFIX + sessionId));  
  4.         

return
 s;  

  1.     }  
  2.   
  3.     

private
 
void
 saveSession(Session session) 
throws
 UnknownSessionException{  

  1.         

if
 (session == 
null
 || session.getId() == 
null
) {  

  1.             logger.error(

"session or session id is null"
);  

  1.             

return
;  

  1.         }  
  2.         

//设置过期时间
  

  1.         

long
 expireTime = 1800000l;  

  1.         session.setTimeout(expireTime);  
  2.         redisManager.setEx(KEY_PREFIX + session.getId(), session, expireTime);  
  3.     }  
  4.   
  5.     

public
 
void
 setRedisManager(RedisManager redisManager) {  

  1.         

this
.redisManager = redisManager;  

  1.     }  
  2.   
  3.     

public
 RedisManager getRedisManager() {  

  1.         

return
 redisManager;  

  1.     }  

  2.   

  3. }  

  4.  RedisManager.java

[java] view plain
 copy

  1. import

 org.apache.commons.lang3.StringUtils;  

  1. import

 org.apache.shiro.dao.DataAccessException;  

  1. import

 org.springframework.beans.factory.annotation.Autowired;  

  1. import

 org.springframework.data.redis.connection.RedisConnection;  

  1. import

 org.springframework.data.redis.core.RedisCallback;  

  1. import

 org.springframework.data.redis.core.RedisTemplate;  

  1.   
  2. import

 java.io.Serializable;  

  1. import

 java.util.Set;  

  1.   
  2. /** 
  3.  * @Author:  
  4.  * @Date: 2018-03-13 12:30 
  5.  * @Modified By: 
  6.  * @Description: 
  7.  */

  

  1. public

 
class
 RedisManager {  

  1.   
  2.     

@Autowired
  

  1.     

private
 RedisTemplate<Serializable, Serializable> redisTemplate;  

  1.   
  2.     

/** 

  1.      * 过期时间 
  2.      */

  

  1.   
  2.     

/** 

  1.      * 添加缓存数据(给定key已存在,进行覆盖) 
  2.      * @param key 
  3.      * @param obj 
  4.      * @throws DataAccessException 
  5.      */

  

  1.     

public
 <T> 
void
 set(
byte
[] key, T obj) 
throws
 DataAccessException{  

  1.         

final
 
byte
[] bkey = key;  

  1.         

final
 
byte
[] bvalue = SerializerUtil.serialize(obj);  

  1.         redisTemplate.execute(

new
 RedisCallback<Void>() {  

  1.             

@Override
  

  1.             

public
 Void doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 connection.set(bkey, bvalue);  
  2.                 

return
 
null
;  

  1.             }  
  2.         });  
  3.     }  
  4.   
  5.     

/** 

  1.      * 添加缓存数据(给定key已存在,不进行覆盖,直接返回false) 
  2.      * @param key 
  3.      * @param obj 
  4.      * @return 操作成功返回true,否则返回false 
  5.      * @throws DataAccessException 
  6.      */

  

  1.     

public
 <T> 
boolean
 setNX(String key, T obj) 
throws
 DataAccessException{  

  1.         

final
 
byte
[] bkey = key.getBytes();  

  1.         

final
 
byte
[] bvalue = SerializerUtil.serialize(obj);  

  1.         

boolean
 result = redisTemplate.execute(
new
 RedisCallback<Boolean>() {  

  1.             

@Override
  

  1.             

public
 Boolean doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 

return
 connection.setNX(bkey, bvalue);  

  1.             }  
  2.         });  
  3.   
  4.         

return
 result;  

  1.     }  
  2.   
  3.     

/** 

  1.      * 添加缓存数据,设定缓存失效时间 
  2.      * @param key 
  3.      * @param obj 
  4.      * @param expireSeconds 过期时间,单位 秒 
  5.      * @throws DataAccessException 
  6.      */

  

  1.     

public
 <T> 
void
 setEx(String key, T obj, 
final
 
long
 expireSeconds) 
throws
 DataAccessException{  

  1.         

final
 
byte
[] bkey = key.getBytes();  

  1.         

final
 
byte
[] bvalue = SerializerUtil.serialize(obj);  

  1.         redisTemplate.execute(

new
 RedisCallback<Boolean>() {  

  1.             

@Override
  

  1.             

public
 Boolean doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 connection.setEx(bkey, expireSeconds, bvalue);  
  2.                 

return
 
true
;  

  1.             }  
  2.         });  
  3.     }  
  4.   
  5.     

/** 

  1.      * 获取key对应value 
  2.      * @param key 
  3.      * @return 
  4.      * @throws DataAccessException 
  5.      */

  

  1.     

public
 <T> T get(
final
 
byte
[] key) 
throws
 DataAccessException{  

  1.         

byte
[] result = redisTemplate.execute(
new
 RedisCallback<
byte
[]>() {  

  1.             

@Override
  

  1.             

public
 
byte
[] doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 

return
 connection.get(key);  

  1.             }  
  2.         });  
  3.         

if
 (result == 
null
) {  

  1.             

return
 
null
;  

  1.         }  
  2.         

return
 SerializerUtil.deserialize(result);  

  1.     }  
  2.   
  3.     

/** 

  1.      * 删除指定key数据 
  2.      * @param key 
  3.      * @return 返回操作影响记录数 
  4.      */

  

  1.     

public
 Long del(
final
 
byte
[] key){  

  1.         

if
 (key.length == 
0
) {  

  1.             

return
 0l;  

  1.         }  
  2.         Long delNum = redisTemplate.execute(

new
 RedisCallback<Long>() {  

  1.             

@Override
  

  1.             

public
 Long doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 

byte
[] keys = key;  

  1.                 

return
 connection.del(keys);  

  1.             }  
  2.         });  
  3.         

return
 delNum;  

  1.     }  
  2.   
  3.     

public
 Set<
byte
[]> keys(
final
 String key){  

  1.         

if
 (StringUtils.isEmpty(key)) {  

  1.             

return
 
null
;  

  1.         }  
  2.         Set<

byte
[]> bytesSet = redisTemplate.execute(
new
 RedisCallback<Set<
byte
[]>>() {  

  1.             

@Override
  

  1.             

public
 Set<
byte
[]> doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 

byte
[] keys = key.getBytes();  

  1.                 

return
 connection.keys(keys);  

  1.             }  
  2.         });  
  3.   
  4.         

return
 bytesSet;  

  1.     }  
  2.   
  3.     

/** 

  1.      * dbSize 
  2.      */

  

  1.     

public
 Long dbSize(){  

  1.         Long delNum = redisTemplate.execute(

new
 RedisCallback<Long>() {  

  1.             

@Override
  

  1.             

public
 Long doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 

return
 connection.dbSize();  

  1.             }  
  2.         });  
  3.         

return
 delNum;  

  1.     }  
  2.   
  3.     

/** 

  1.      * flushDB 
  2.      */

  

  1.     

public
 
void
 flushDB() 
throws
 DataAccessException{  

  1.         redisTemplate.execute(

new
 RedisCallback<Void>() {  

  1.             

@Override
  

  1.             

public
 Void doInRedis(RedisConnection connection) 
throws
 DataAccessException {  

  1.                 connection.flushDb();  
  2.                 

return
 
null
;  

  1.             }  

  2.         });  

  3.     }}  

  4.  RedisCacheManager.java

[java] view plain
 copy

  1. import

 org.apache.shiro.cache.Cache;  

  1. import

 org.apache.shiro.cache.CacheException;  

  1. import

 org.apache.shiro.cache.CacheManager;  

  1. import

 org.slf4j.Logger;  

  1. import

 org.slf4j.LoggerFactory;  

  1.   
  2. import

 java.util.concurrent.ConcurrentHashMap;  

  1. import

 java.util.concurrent.ConcurrentMap;  

  1.   
  2. /** 
  3.  * @Author: 
  4.  * @Date: 2018-03-13 14:08 
  5.  * @Modified By: 
  6.  * @Description: 
  7.  */

  

  1. public

 
class
 RedisCacheManager 
implements
 CacheManager{  

  1.   
  2.     

private
 
static
 
final
 Logger logger = LoggerFactory  

  1.             .getLogger(RedisCacheManager.

class
);  

  1.   
  2.     

private
 
final
 ConcurrentMap<String, Cache> caches = 
new
 ConcurrentHashMap<String, Cache>();  

  1.   
  2.     

private
 RedisManager redisManager;  

  1.   
  2.     

/** 

  1.      * The Redis key prefix for caches 
  2.      */

  

  1.     

private
 String keyPrefix = 
"shiro_redis_cache:"
;  

  1.   
  2.     

/** 

  1.      * Returns the Redis session keys 
  2.      * prefix. 
  3.      * @return The prefix 
  4.      */

  

  1.     

public
 String getKeyPrefix() {  

  1.         

return
 keyPrefix;  

  1.     }  
  2.   
  3.     

/** 

  1.      * Sets the Redis sessions key 
  2.      * prefix. 
  3.      * @param keyPrefix The prefix 
  4.      */

  

  1.     

public
 
void
 setKeyPrefix(String keyPrefix) {  

  1.         

this
.keyPrefix = keyPrefix;  

  1.     }  
  2.   
  3.     

@Override
  

  1.     

public
 <K, V> Cache<K, V> getCache(String name) 
throws
 CacheException {  

  1.         logger.debug(

"获取名称为: "
 + name + 
" 的RedisCache实例"
);  

  1.   
  2.         Cache c = caches.get(name);  
  3.   
  4.         

if
 (c == 
null
) {  

  1.   
  2.             

// initialize the Redis manager instance
  

  1.             redisManager.init();  
  2.   
  3.             

// create a new cache instance
  

  1.             c = 

new
 RedisCache<K, V>(redisManager, keyPrefix);  

  1.   
  2.             

// add it to the cache collection
  

  1.             caches.put(name, c);  
  2.         }  
  3.         

return
 c;  

  1.     }  
  2.   
  3.     

public
 RedisManager getRedisManager() {  

  1.         

return
 redisManager;  

  1.     }  
  2.   
  3.     

public
 
void
 setRedisManager(RedisManager redisManager) {  

  1.         

this
.redisManager = redisManager;  

  1.     }  

  2.   

  3. }  

  4.  RedisCache.java

[java] view plain
 copy

  1. import

 org.apache.shiro.cache.Cache;  

  1. import

 org.apache.shiro.cache.CacheException;  

  1. import

 org.apache.shiro.util.CollectionUtils;  

  1. import

 org.slf4j.Logger;  

  1. import

 org.slf4j.LoggerFactory;  

  1.   
  2. import

 java.util.*;  

  1.   
  2. /** 
  3.  * @Author: 
  4.  * @Date: 2018-03-13 14:10 
  5.  * @Modified By: 
  6.  * @Description: 
  7.  */

  

  1. public

 
class
 RedisCache<K,V> 
implements
 Cache<K,V> {  

  1.     

private
 Logger logger = LoggerFactory.getLogger(
this
.getClass());  

  1.   
  2.     

/** 

  1.      * The wrapped Jedis instance. 
  2.      */

  

  1.     

private
 RedisManager cache;  

  1.   
  2.     

/** 

  1.      * The Redis key prefix for the sessions 
  2.      */

  

  1.     

private
 String keyPrefix = 
"shiro_redis_session:"
;  

  1.   
  2.     

/** 

  1.      * Returns the Redis session keys 
  2.      * prefix. 
  3.      * @return The prefix 
  4.      */

  

  1.     

public
 String getKeyPrefix() {  

  1.         

return
 keyPrefix;  

  1.     }  
  2.   
  3.     

/** 

  1.      * Sets the Redis sessions key 
  2.      * prefix. 
  3.      * @param keyPrefix The prefix 
  4.      */

  

  1.     

public
 
void
 setKeyPrefix(String keyPrefix) {  

  1.         

this
.keyPrefix = keyPrefix;  

  1.     }  
  2.   
  3.     

/** 

  1.      * 通过一个JedisManager实例构造RedisCache 
  2.      */

  

  1.     

public
 RedisCache(RedisManager cache){  

  1.         

if
 (cache == 
null
) {  

  1.             

throw
 
new
 IllegalArgumentException(
"Cache argument cannot be null."
);  

  1.         }  
  2.         

this
.cache = cache;  

  1.     }  
  2.   
  3.     

/** 

  1.      * Constructs a cache instance with the specified 
  2.      * Redis manager and using a custom key prefix. 
  3.      * @param cache The cache manager instance 
  4.      * @param prefix The Redis key prefix 
  5.      */

  

  1.     

public
 RedisCache(RedisManager cache,  

  1.                       String prefix){  
  2.   
  3.         

this
( cache );  

  1.   
  2.         

this
.keyPrefix = prefix;  

  1.     }  
  2.   
  3.     

/** 

  1.      * 获得byte[]型的key 
  2.      * @param key 
  3.      * @return 
  4.      */

  

  1.     

private
 
byte
[] getByteKey(K key){  

  1.         

if
(key 
instanceof
 String){  

  1.             String preKey = 

this
.keyPrefix + key;  

  1.             

return
 preKey.getBytes();  

  1.         }

else
{  

  1.             

return
 SerializerUtil.serialize(key);  

  1.         }  
  2.     }  
  3.   
  4.     

@Override
  

  1.     

public
 V get(K key) 
throws
 CacheException {  

  1.         logger.debug(

"根据key从Redis中获取对象 key ["
 + key + 
"]"
);  

  1.         

try
 {  

  1.             

if
 (key == 
null
) {  

  1.                 

return
 
null
;  

  1.             }

else
{  

  1.                 

byte
[] rawValue = cache.get(getByteKey(key));  

  1.                 

@SuppressWarnings
(
"unchecked"
)  

  1.                 V value = (V) SerializerUtil.deserialize(rawValue);  
  2.                 

return
 value;  

  1.             }  
  2.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.   
  3.     }  
  4.   
  5.     

@Override
  

  1.     

public
 V put(K key, V value) 
throws
 CacheException {  

  1.         logger.debug(

"根据key从存储 key ["
 + key + 
"]"
);  

  1.         

try
 {  

  1.             cache.set(getByteKey(key), SerializerUtil.serialize(value));  
  2.             

return
 value;  

  1.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3.   
  4.     

@Override
  

  1.     

public
 V remove(K key) 
throws
 CacheException {  

  1.         logger.debug(

"从redis中删除 key ["
 + key + 
"]"
);  

  1.         

try
 {  

  1.             V previous = get(key);  
  2.             cache.del(getByteKey(key));  
  3.             

return
 previous;  

  1.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3.   
  4.     

@Override
  

  1.     

public
 
void
 clear() 
throws
 CacheException {  

  1.         logger.debug(

"从redis中删除所有元素"
);  

  1.         

try
 {  

  1.             cache.flushDB();  
  2.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3.   
  4.     

@Override
  

  1.     

public
 
int
 size() {  

  1.         

try
 {  

  1.             Long longSize = 

new
 Long(cache.dbSize());  

  1.             

return
 longSize.intValue();  

  1.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3.   
  4.     

@SuppressWarnings
(
"unchecked"
)  

  1.     

@Override
  

  1.     

public
 Set<K> keys() {  

  1.         

try
 {  

  1.             Set<

byte
[]> keys = cache.keys(
this
.keyPrefix + 
"*"
);  

  1.             

if
 (CollectionUtils.isEmpty(keys)) {  

  1.                 

return
 Collections.emptySet();  

  1.             }

else
{  

  1.                 Set<K> newKeys = 

new
 HashSet<K>();  

  1.                 

for
(
byte
[] key:keys){  

  1.                     newKeys.add((K)key);  
  2.                 }  
  3.                 

return
 newKeys;  

  1.             }  
  2.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3.   
  4.     

@Override
  

  1.     

public
 Collection<V> values() {  

  1.         

try
 {  

  1.             Set<

byte
[]> keys = cache.keys(
this
.keyPrefix + 
"*"
);  

  1.             

if
 (!CollectionUtils.isEmpty(keys)) {  

  1.                 List<V> values = 

new
 ArrayList<V>(keys.size());  

  1.                 

for
 (
byte
[] key : keys) {  

  1.                     

@SuppressWarnings
(
"unchecked"
)  

  1.                     V value = get((K)key);  
  2.                     

if
 (value != 
null
) {  

  1.                         values.add(value);  
  2.                     }  
  3.                 }  
  4.                 

return
 Collections.unmodifiableList(values);  

  1.             } 

else
 {  

  1.                 

return
 Collections.emptyList();  

  1.             }  
  2.         } 

catch
 (Throwable t) {  

  1.             

throw
 
new
 CacheException(t);  

  1.         }  
  2.     }  
  3. }  

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索