|  |  | 
 |  |  | package doumeemes.config.shiro; | 
 |  |  |  | 
 |  |  | import doumeemes.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 2022/04/18 18:12 | 
 |  |  |  * @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"; | 
 |  |  |     } | 
 |  |  | } |