Apache Shiro Cluster Implementation (VII)---cache sharing under distributed cluster system

Source: Internet
Author: User
Tags throwable

Apache Shiro Cluster Implementation (i) Shiro introduction

Apache Shiro cluster Implementation (ii) INI configuration of Shiro

Apache Shiro cluster Implementation (III) Shiro identity authentication (Shiro authentication)

Apache Shiro cluster Implementation (IV) Shiro authorization (authentication)-access control

Apache Shiro Cluster Implementation (v) High Availability session solution under distributed cluster system

Apache Shiro Cluster Implementation (VI) High-availability session solution under distributed cluster system---session sharing

Apache Shiro Cluster Implementation (VII)---cache sharing under distributed cluster system
Apache Shiro Cluster Implementation (eight) 3 methods of Session synchronization during Web cluster


The previous article has solved the first problem, session sharing, now we solve the second problem of cache sharing.

Let's take a look at spring's configuration file, which is already mentioned in the previous article.


<span style= "FONT-SIZE:18PX;" ><bean id= "SecurityManager" class= "Org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on= " Userrepository,rolerepository ">      <property name=" SessionManager "ref=" Defaultwebsessionmanager "/>      <property name= "Realm" ref= "Shirodbrealm"/>      <property name= "CacheManager" ref= " Memoryconstrainedcachemanager "/>  </bean>  <bean id=" Memoryconstrainedcachemanager "class=" Org.apache.shiro.cache.MemoryConstrainedCacheManager "/></span>


Here CacheManager we injected Shiro custom native memory implementation of CacheManager class, of course, this certainly does not meet the needs of our cluster, so we have to implement the CacheManager class, here I still use Redis as the cache storage , create the Rediscachemanager implementation class first


<span style= "FONT-SIZE:18PX;" >package Com.tgb.itoo.authority.cache;import Java.util.concurrent.concurrenthashmap;import Java.util.concurrent.concurrentmap;import Org.apache.shiro.cache.cache;import Org.apache.shiro.cache.cacheexception;import Org.apache.shiro.cache.cachemanager;import Org.slf4j.Logger;import Org.slf4j.loggerfactory;public class Rediscachemanager implements cachemanager{private static final Logger Logger = Loggerfactory.getlogger (Rediscachemanager.class);//Fast lookup by name Mapprivate final concurrentmap<string, cache> caches = new concurrenthashmap<string, cache> ();p rivate redismanager redismanager;/** * The Redis key pref IX for caches */private String keyprefix = "Shiro_redis_cache:";/** * Returns the Redis session keys * prefix. * @return The prefix */public String getkeyprefix () {return keyprefix;} /** * Sets the Redis sessions key * prefix. * @param keyprefix the prefix */public void Setkeyprefix (String keyprefix) {this.keyprefix = Keyprefix;}@Overridepublic <k, v> cache<k, v> getcache (String name) throws Cacheexception {logger.debug ("Get Name:" + Name + "Rediscache instance"); Cache C = caches.get (name), if (c = = null) {//Initialize the Redis manager instanceredismanager.init ();//Create a new CAC He instancec = new rediscache<k, v> (Redismanager, keyprefix);//Add it to the cache Collectioncaches.put (name, c);} return c;} Public Redismanager Getredismanager () {return redismanager;} public void Setredismanager (Redismanager redismanager) {this.redismanager = Redismanager;}} </span>

Of course, here is only GetCache, I first read the source, there is such a doubt, the cache add, remove and so on where to implement the method? Let's keep looking at Shiro's source code and we'll know the answer.

This is the way of Relm Authorizingrealm.


<span style= "FONT-SIZE:18PX;" > Protected Authorizationinfo getauthorizationinfo (principalcollection principals) {if (Principa              ls = = null) {return null;                    } authorizationinfo info = null; if (log.istraceenabled ()) {Log.trace ("Retrieving Authorizationinfo for Principals [" + Principals + "]")              ;              } cache<object, authorizationinfo> Cache = Getavailableauthorizationcache (); if (cache! = null) {if (log.istraceenabled ()) {Log.trace ("attempting to retrieve T                  He authorizationinfo from cache. ");                  Object key = Getauthorizationcachekey (principals);                  info = cache.get (key); if (log.istraceenabled ()) {if (info = = null) {log.trace ("No Authorizationi NFO found in the cache for principals ["+ priNcipals + "]");                      } else {log.trace ("Authorizationinfo found in the cache for principals [" + Principals + "]"); }}} if (info = = null) {//Call template Me Thod if the info is not found in a cache info = <STRONG>doGetAuthorizationInfo</STRONG> (pri                  Ncipals);                   If the info is not null and the cache have been created, then cache the authorization info. if (info! = NULL && cache! = null) {if (log.istraceenabled ()) {log                      . Trace ("Caching Authorization info for principals: [" + Principals + "].");                      Object key = Getauthorizationcachekey (principals);                  <STRONG>cache.put</STRONG> (key, info);          }} return info; } </span>


If we go to check the introduction to know that our custom Relm to implement a method called Dogetauthorizationinfo (), its role is to query the authorization information, we pay attention to the bold 2 lines, found that the cache's put method is actually the cache storage core class, The implementation is in the cache, so we need to implement our own cache to create the Rediscache class


<span style= "FONT-SIZE:18PX;" >package Com.tgb.itoo.authority.cache;import Java.util.arraylist;import Java.util.collection;import Java.util.collections;import Java.util.hashset;import Java.util.list;import Java.util.set;import Org.apache.shiro.cache.cache;import Org.apache.shiro.cache.cacheexception;import Org.apache.shiro.util.collectionutils;import Org.slf4j.logger;import Org.slf4j.loggerfactory;public Class Rediscache<k,v> implements cache<k,v> {private Logger Logger = Loggerfactory.getlogger (This.getclass ());     * * The wrapped Jedis instance. */private Redismanager cache;/** * The Redis key prefix for the sessions */private String keyprefix = "Shiro_redis_sessio N: ";/** * Returns the Redis session keys * prefix. * @return The prefix */public String getkeyprefix () {return keyprefix;} /** * Sets the Redis sessions key * prefix. * @param keyprefix the prefix */public void Setkeyprefix (String keyprefix) {this.keyprefix = Keyprefix;} /** * Constructed from a Jedismanager instance RediScache */public Rediscache (Redismanager cache) {if (cache = = null) {throw new IllegalArgumentException ("Cache arg     Ument cannot be null. "); This.cache = cache;} /** * Constructs a cache instance with the specified * Redis Manager and using a custom key prefix. * @param cache the Cache manager instance * @param prefix the Redis key prefix */public rediscache (redismanager cache, STR ing prefix) {this (cache);//Set the Prefixthis.keyprefix = prefix;} /** * Get byte[] Type key * @param key * @return */private byte[] Getbytekey (K key) {if (key instanceof String) {string prekey = th    Is.keyprefix + key;    return Prekey.getbytes ();    }else{return Serializeutils.serialize (key); }} @Overridepublic V get (K key) throws Cacheexception {Logger.debug ("Get Object key from Redis based on key [" + Key + "]"); try {if (key = =        NULL) {return null;        }else{byte[] RawValue = Cache.get (Getbytekey (key)); @SuppressWarnings ("unchecked") V value = (V) serializeutils.deserialize (RawValue);        return value; }} catch (Throwable t) {throw new cacheexception (t);}} @Overridepublic v put (K key, V value) throws Cacheexception {Logger.debug ("store key from key [" + Key + "]");            try {cache.set (Getbytekey (key), serializeutils.serialize (value));        return value;        } catch (Throwable t) {throw new cacheexception (t); }} @Overridepublic V remove (K key) throws Cacheexception {logger.debug ("Remove key from Redis [" + Key + "]"); try {v PR            Evious = Get (key);            Cache.del (Getbytekey (key));        return previous;        } catch (Throwable t) {throw new cacheexception (t);        }} @Overridepublic void Clear () throws Cacheexception {Logger.debug ("Remove all elements from Redis"), try {cache.flushdb ();        } catch (Throwable t) {throw new cacheexception (t);            }} @Overridepublic int size () {try {long longsize = new Long (cache.dbsize ());        return Longsize.intvalue (); } catch (Throwable t) {THrow new Cacheexception (t); }} @SuppressWarnings ("Unchecked") @Overridepublic set<k> keys () {try {set<byte[]> keys = Cache.keys (            This.keyprefix + "*");            if (Collectionutils.isempty (keys)) {return collections.emptyset ();            }else{set<k> Newkeys = new hashset<k> ();            For (byte[] key:keys) {Newkeys.add ((K) key);            } return Newkeys;        }} catch (Throwable t) {throw new cacheexception (t); }} @Overridepublic collection<v> values () {try {set<byte[]> keys = Cache.keys (This.keyprefix + "*")            ; if (!                Collectionutils.isempty (keys)) {list<v> values = new arraylist<v> (Keys.size ());                    For (byte[] key:keys) {@SuppressWarnings ("unchecked") V value = Get ((K) key);                if (value = null) {Values.add (value);    }} return Collections.unmodifiablelist (values);            } else {return collections.emptylist ();        }} catch (Throwable t) {throw new cacheexception (t); }}}</span>


Finally, modify the spring configuration file


<span style= "FONT-SIZE:18PX;" ><!--Third: Shiro Management Center class start-Li--><bean id= "SecurityManager" class= " Org.apache.shiro.web.mgt.DefaultWebSecurityManager "><property name=" Realm "ref=" Shirorealm "></ Property><property name= "SessionMode" value= "http" ></property><property name= "SubjectFactory" ref= "Cassubjectfactory" ></property><!--Ehcahe cache Shiro comes with--><!--<property name= "CacheManager" ref= "Shiroehcachemanager" ></property>--><!--redis cache--><property name= "CacheManager" ref= " Rediscachemanager "/><!--sessionmanager--><property name=" SessionManager "ref=" SessionManager "> </property></bean></span>

This completes the configuration of the entire Shiro cluster

Apache Shiro Cluster Implementation (VII)---cache sharing under distributed cluster system

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.