|  |  |  | 
|---|
|  |  |  | package com.doumee.config.shiro; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.doumee.service.proxy.CacheProxy; | 
|---|
|  |  |  | import lombok.extern.slf4j.Slf4j; | 
|---|
|  |  |  | import org.apache.shiro.cache.Cache; | 
|---|
|  |  |  | import org.apache.shiro.cache.CacheException; | 
|---|
|  |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
|---|
|  |  |  | import org.apache.shiro.subject.PrincipalCollection; | 
|---|
|  |  |  | import org.apache.shiro.util.CollectionUtils; | 
|---|
|  |  |  | import org.springframework.context.annotation.Scope; | 
|---|
|  |  |  | import org.springframework.data.redis.core.RedisTemplate; | 
|---|
|  |  |  | import org.springframework.data.redis.serializer.SerializationException; | 
|---|
|  |  |  | import org.springframework.stereotype.Component; | 
|---|
|  |  |  | import org.springframework.util.CollectionUtils; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.annotation.Resource; | 
|---|
|  |  |  | import java.io.Serializable; | 
|---|
|  |  |  | import java.lang.reflect.Method; | 
|---|
|  |  |  | import java.util.ArrayList; | 
|---|
|  |  |  | import java.util.Collection; | 
|---|
|  |  |  | import java.util.Collections; | 
|---|
|  |  |  | import java.util.Set; | 
|---|
|  |  |  | import java.util.concurrent.TimeUnit; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * Shiro缓存 | 
|---|
|  |  |  | * @author Eva.Caesar Liu | 
|---|
|  |  |  | * @date 2023/03/21 14:49 | 
|---|
|  |  |  | * @date 2023/04/17 12:11 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @Scope(value = "prototype") | 
|---|
|  |  |  | @Slf4j | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private String keyPrefix = ""; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | private CacheProxy<Object, Serializable> cacheProxy; | 
|---|
|  |  |  | @Resource(name="sessionRedisTemplate") | 
|---|
|  |  |  | private RedisTemplate<Object, Serializable> redisTemplate; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public ShiroCache () { | 
|---|
|  |  |  | log.debug("ShiroCache: new, keyPrefix = [" + keyPrefix + "]"); | 
|---|
|  |  |  | 
|---|
|  |  |  | if (key == null) { | 
|---|
|  |  |  | return null; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return cacheProxy.get(getKey(key)); | 
|---|
|  |  |  | return redisTemplate.opsForValue().get(getKey(key)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | 
|---|
|  |  |  | if (key == null) { | 
|---|
|  |  |  | return null; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | cacheProxy.put(getKey(key), value); | 
|---|
|  |  |  | redisTemplate.opsForValue().set(getKey(key), value); | 
|---|
|  |  |  | return value; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | if (key == null) { | 
|---|
|  |  |  | return null; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | cacheProxy.put(getKey(key), value, timeout); | 
|---|
|  |  |  | redisTemplate.opsForValue().set(getKey(key), value, timeout, TimeUnit.SECONDS); | 
|---|
|  |  |  | return value; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public void clear() throws CacheException { | 
|---|
|  |  |  | Set<Object> keys = this.keys(); | 
|---|
|  |  |  | cacheProxy.remove(keys); | 
|---|
|  |  |  | redisTemplate.delete(keys); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public Set<Object> keys() { | 
|---|
|  |  |  | Set<Object> keys = cacheProxy.keys(keyPrefix + "*"); | 
|---|
|  |  |  | Set<Object> keys = redisTemplate.keys(keyPrefix + "*"); | 
|---|
|  |  |  | if (CollectionUtils.isEmpty(keys)) { | 
|---|
|  |  |  | return Collections.emptySet(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | return values; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | for (Object k : keys) { | 
|---|
|  |  |  | values.add(cacheProxy.get(k)); | 
|---|
|  |  |  | values.add(redisTemplate.opsForValue().get(k)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return values; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | return null; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Serializable value = this.get(getKey(key)); | 
|---|
|  |  |  | cacheProxy.remove(getKey(key)); | 
|---|
|  |  |  | redisTemplate.delete(getKey(key)); | 
|---|
|  |  |  | return value; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private Object getKey (Object key) { | 
|---|
|  |  |  | if (key instanceof PrincipalCollection) { | 
|---|
|  |  |  | return this.keyPrefix + getRedisKeyFromPrincipalIdField((PrincipalCollection)key); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return (key instanceof String ? (this.keyPrefix + key) : key); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 获取redis cache key | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | private String getRedisKeyFromPrincipalIdField(PrincipalCollection key) { | 
|---|
|  |  |  | Object principalObject = key.getPrimaryPrincipal(); | 
|---|
|  |  |  | if (principalObject instanceof String) { | 
|---|
|  |  |  | return principalObject.toString(); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | Method pincipalIdGetter = this.getPrincipalIdGetter(principalObject); | 
|---|
|  |  |  | return this.getIdObj(principalObject, pincipalIdGetter); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private Method getPrincipalIdGetter(Object principalObject) { | 
|---|
|  |  |  | Method pincipalIdGetter; | 
|---|
|  |  |  | String principalIdMethodName = this.getPrincipalIdMethodName(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | pincipalIdGetter = principalObject.getClass().getMethod(principalIdMethodName); | 
|---|
|  |  |  | return pincipalIdGetter; | 
|---|
|  |  |  | } catch (NoSuchMethodException e) { | 
|---|
|  |  |  | throw new SerializationException(e.getMessage(), e); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private String getIdObj(Object principalObject, Method pincipalIdGetter) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | Object idObj = pincipalIdGetter.invoke(principalObject); | 
|---|
|  |  |  | String redisKey = idObj.toString(); | 
|---|
|  |  |  | return redisKey; | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | throw new SerializationException(e.getMessage(), e); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private String getPrincipalIdMethodName() { | 
|---|
|  |  |  | return "getId"; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|