分享

我的shiro之旅: 八 shiro session 共享的进一步

 WindySky 2017-12-27

在第七篇文章说了一下如何实现shiro的共享。那个共享并不只是session的共享,也包括了Authorization的共享。如果读者还没看过文章七,建议先看看。

在文章七的ShiroCacheManager类继承了AbstractCacheManager,我们来看看AbstractCacheManager类的源码。

  1. public abstract class AbstractCacheManager implements CacheManager, Destroyable {  
  2.   
  3.     /** 
  4.      * Retains all Cache objects maintained by this cache manager. 
  5.      */  
  6.     private final ConcurrentMap<String, Cache> caches;  
  7.   
  8.     /** 
  9.      * Default no-arg constructor that instantiates an internal name-to-cache {@code ConcurrentMap}. 
  10.      */  
  11.     public AbstractCacheManager() {  
  12.         this.caches = new ConcurrentHashMap<String, Cache>();  
  13.     }  
  14.   
  15.     /** 
  16.      * Returns the cache with the specified {@code name}.  If the cache instance does not yet exist, it will be lazily 
  17.      * created, retained for further access, and then returned. 
  18.      * 
  19.      * @param name the name of the cache to acquire. 
  20.      * @return the cache with the specified {@code name}. 
  21.      * @throws IllegalArgumentException if the {@code name} argument is {@code null} or does not contain text. 
  22.      * @throws CacheException           if there is a problem lazily creating a {@code Cache} instance. 
  23.      */  
  24.     public <K, V> Cache<K, V> getCache(String name) throws IllegalArgumentException, CacheException {  
  25.         if (!StringUtils.hasText(name)) {  
  26.             throw new IllegalArgumentException("Cache name cannot be null or empty.");  
  27.         }  
  28.   
  29.         Cache cache;  
  30.   
  31.         cache = caches.get(name);  
  32.         if (cache == null) {  
  33.             cache = createCache(name);  
  34.             Cache existing = caches.putIfAbsent(name, cache);  
  35.             if (existing != null) {  
  36.                 cache = existing;  
  37.             }  
  38.         }  
  39.   
  40.         //noinspection unchecked  
  41.         return cache;  
  42.     }  
  43.   
  44.     /** 
  45.      * Creates a new {@code Cache} instance associated with the specified {@code name}. 
  46.      * 
  47.      * @param name the name of the cache to create 
  48.      * @return a new {@code Cache} instance associated with the specified {@code name}. 
  49.      * @throws CacheException if the {@code Cache} instance cannot be created. 
  50.      */  
  51.     protected abstract Cache createCache(String name) throws CacheException;  
  52.   
  53.     /** 
  54.      * Cleanup method that first {@link LifecycleUtils#destroy destroys} all of it's managed caches and then 
  55.      * {@link java.util.Map#clear clears} out the internally referenced cache map. 
  56.      * 
  57.      * @throws Exception if any of the managed caches can't destroy properly. 
  58.      */  
  59.     public void destroy() throws Exception {  
  60.         while (!caches.isEmpty()) {  
  61.             for (Cache cache : caches.values()) {  
  62.                 LifecycleUtils.destroy(cache);  
  63.             }  
  64.             caches.clear();  
  65.         }  
  66.     }  
  67.   
  68.     public String toString() {  
  69.         Collection<Cache> values = caches.values();  
  70.         StringBuilder sb = new StringBuilder(getClass().getSimpleName())  
  71.                 .append(" with ")  
  72.                 .append(caches.size())  
  73.                 .append(" cache(s)): [");  
  74.         int i = 0;  
  75.         for (Cache cache : values) {  
  76.             if (i > 0) {  
  77.                 sb.append(", ");  
  78.             }  
  79.             sb.append(cache.toString());  
  80.             i++;  
  81.         }  
  82.         sb.append("]");  
  83.         return sb.toString();  
  84.     }  
  85. }  

其中有个很重要的方法就是getCache方法,有个很重要的属性就是private final ConcurrentMap<String, Cache> caches;caches是一个线程安全的ConcurrentMap类型,用是存放Cache的,在这里,至少存放两个Cache,一个是用来存放session的,一个是用来存放权限(Authorization)的。从getCache方法我们可以知道,shiro先从caches里拿,如果拿不到相应的Cache,就调用createCache创建一个,createCache是抽象方法,由子类实现。创建完之后,放到Map中。

如果我们在getCache方法debug就可以知道,shiro创建两个Cache放到ConcurrentMap中,一个name中ShiroCasRealm.authorizationCache(这个名字的命名规则是自定义的realm的名字加".authorizationCache",realm的定义可以参考我的shiro之旅: 二 让Shiro保护你的应用),这个是shiro启动的时候创建的,用来保存认证信息,一个叫shiro-activeSessionCache,这个是第一次创建session的时候创建的,用来保存session。当用户登录的时候,将会把用户的权限信息保存到name为ShiroCasRealm.authorizationCache的Cache中,以后需要再使用权限信息,直接从Cache中拿而不需要再从数据库中查询。这样也有一个问题,就是当用户权限改变时,就需要用户重新登录把权限信息从新load到Cache中。不过既然我们知道Cache的名字,我们就可以拿到这个Cache,然后把用户的权限信息删除,让shiro在授权时找不到权限而shiro自己从新去load,甚至我们可以删除了,然后再从新load到Cache中。这些将在以后的文章有介绍。

session我们是放到了缓存中(memcached),那自然我们就可以在多个应用去使用它。只要从个应用的ShiroMemcachedCache连的都是一个memcached,就可以把session保存到一个memcached中,就可以从同一个memcached去得到session。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多