打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
shiro安全框架扩展教程--如何扩展实现我们的缓存机制(第三方容器redis,memcached)

            上一章我们讲解了如何扩展集中式的session管理方便我们集群的应用项目,无须再使用复制session的方式来完善用户体系;下面我主要分享如何扩展shiro里的缓存实现,

大家都知道有点规模的项目都必须会使用缓存这个好东西,所以一个好的框架基本都会包含一套多级缓存的机制,例如spring,hibernate等也会有自己一套,象第三方的oscache,ehcache等等;


不扯没营养的话了,还是说回shiro的缓存,shiro的缓存比较简单,我们可以看看shiro定义的cache接口源码


  1. package org.apache.shiro.cache;  
  2.   
  3. import java.util.Collection;  
  4. import java.util.Set;  
  5.   
  6. // Referenced classes of package org.apache.shiro.cache:  
  7. //            CacheException  
  8.   
  9. public interface Cache  
  10. {  
  11.   
  12.     public abstract Object get(Object obj)  
  13.         throws CacheException;  
  14.   
  15.     public abstract Object put(Object obj, Object obj1)  
  16.         throws CacheException;  
  17.   
  18.     public abstract Object remove(Object obj)  
  19.         throws CacheException;  
  20.   
  21.     public abstract void clear()  
  22.         throws CacheException;  
  23.   
  24.     public abstract int size();  
  25.   
  26.     public abstract Set keys();  
  27.   
  28.     public abstract Collection values();  
  29. }  

很明显看到跟我们普通的cache差不多,也是CRUD等等方法,然后看看有shiro写的有哪些实现类

一个是org.apache.shiro.cache.ehcache.EhCache

一个是org.apache.shiro.cache.MapCache

然后看着名字我们就大概知道一个是基于encache框架来作为实现类基础,一个是以本地map来装载数据到内存达到缓存的效果,这里类的源码可以自己看看,比较简单,shiro入门后的都能看懂,但是这些实现类都不适合我用,我想要的是用memcached或是redis作为数据的缓存容器


下面我就来分享下自己的实现流程



上面我们已经看过shiro的cache接口,下面我们就实现一个序列化的cache实现类


  1. /**  
  2.  *   
  3.  * 缓存实现类,实现序列 接口方便对象存储于第三方容器(Map存放键值对)  
  4.  *   
  5.  *   
  6.  */  
  7. @SuppressWarnings("serial")  
  8. public class SimpleMapCache implements Cache<Object, Object>, Serializable {  
  9.   
  10.     private final Map<Object, Object> attributes;  
  11.     private final String name;  
  12.   
  13.     public SimpleMapCache(String name, Map<Object, Object> backingMap) {  
  14.         if (name == null)  
  15.             throw new IllegalArgumentException("Cache name cannot be null.");  
  16.         if (backingMap == null) {  
  17.             throw new IllegalArgumentException("Backing map cannot be null.");  
  18.         } else {  
  19.             this.name = name;  
  20.             attributes = backingMap;  
  21.         }  
  22.     }  
  23.   
  24.     public Object get(Object key) throws CacheException {  
  25.         return attributes.get(key);  
  26.     }  
  27.   
  28.     public Object put(Object key, Object value) throws CacheException {  
  29.         return attributes.put(key, value);  
  30.     }  
  31.   
  32.     public Object remove(Object key) throws CacheException {  
  33.         return attributes.remove(key);  
  34.     }  
  35.   
  36.     public void clear() throws CacheException {  
  37.         attributes.clear();  
  38.     }  
  39.   
  40.     public int size() {  
  41.         return attributes.size();  
  42.     }  
  43.   
  44.     public Set<Object> keys() {  
  45.         Set<Object> keys = attributes.keySet();  
  46.         if (!keys.isEmpty())  
  47.             return Collections.unmodifiableSet(keys);  
  48.         else  
  49.             return Collections.emptySet();  
  50.     }  
  51.   
  52.     public Collection<Object> values() {  
  53.         Collection<Object> values = attributes.values();  
  54.         if (!CollectionUtils.isEmpty(values))  
  55.             return Collections.unmodifiableCollection(values);  
  56.         else  
  57.             return Collections.emptySet();  
  58.     }  
  59.   
  60.     public String toString() {  
  61.         return (new StringBuilder("SimpleMapCache '")).append(name).append("' (").append(attributes.size()).append(  
  62.                 " entries)").toString();  
  63.     }  
  64.   
  65. }  


其实上面的cache实现我直接用mapcache实现类的源码然后增加实现序列化的接口,比较方便


然后我们把自己的资源搞到一个map里,然后new SimpleMapCache(Map)就生成一个缓存堆,最后添加到缓存管理器里面即可


下面我们看看如何实现缓存管理器


所以我们先实现一个自定义的缓存管理器接口方便我们操作每一个缓存堆


  1. /**  
  2.  *   
  3.  * 缓存管理器接口  
  4.  *   
  5.  * @author shadow  
  6.  *   
  7.  */  
  8. public interface SimpleCacheManager {  
  9.   
  10.     /**  
  11.      * 新增缓存堆到管理器  
  12.      *   
  13.      * @param name  
  14.      * @param cache  
  15.      */  
  16.     public abstract void createCache(String name, Cache<Object, Object> cache) throws CacheException;  
  17.   
  18.     /**  
  19.      * 获取缓存堆  
  20.      *   
  21.      * @param name  
  22.      * @return  
  23.      * @throws CacheException  
  24.      */  
  25.     public abstract Cache<Object, Object> getCache(String name) throws CacheException;  
  26.   
  27.     /**  
  28.      * 移除缓存堆  
  29.      *   
  30.      * @param name  
  31.      * @throws CacheException  
  32.      */  
  33.     public abstract void removeCache(String name) throws CacheException;  
  34.   
  35.     /**  
  36.      * 更新缓存堆  
  37.      *   
  38.      * @param name  
  39.      * @param cache  
  40.      */  
  41.     public abstract void updateCahce(String name, Cache<Object, Object> cache) throws CacheException;  
  42.   
  43.     /**  
  44.      * 注销管理器  
  45.      */  
  46.     public abstract void destroy() throws CacheException;  
  47. }  

接口已经定义好,我们就写一个实现类完成我们的逻辑,并且这个逻辑是把缓存堆对象放到memcached里面


  1. /**  
  2.  *   
  3.  * 缓存管理器实现类  
  4.  *   
  5.  * @author shadow  
  6.  *   
  7.  */  
  8. public class SimpleCacheManagerImpl implements SimpleCacheManager {  
  9.   
  10.     private MemcachedClient memcachedClient;  
  11.   
  12.     public SimpleCacheManagerImpl(MemcachedClient memcachedClient) {  
  13.         if (memcachedClient == null) {  
  14.             throw new RuntimeException("必须存在memcached客户端实例");  
  15.         }  
  16.         this.memcachedClient = memcachedClient;  
  17.     }  
  18.   
  19.     @Override  
  20.     public void createCache(String name, Cache<Object, Object> cache) throws CacheException {  
  21.         try {  
  22.             memcachedClient.set(name, 0, cache);  
  23.         } catch (Exception e) {  
  24.             throw new CacheException(e);  
  25.         }  
  26.     }  
  27.   
  28.     @Override  
  29.     public Cache<Object, Object> getCache(String name) throws CacheException {  
  30.         try {  
  31.             return memcachedClient.get(name);  
  32.         } catch (Exception e) {  
  33.             throw new CacheException(e);  
  34.         }  
  35.     }  
  36.   
  37.     @Override  
  38.     public void removeCache(String name) throws CacheException {  
  39.         try {  
  40.             memcachedClient.delete(name);  
  41.         } catch (Exception e) {  
  42.             throw new CacheException(e);  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     public void updateCahce(String name, Cache<Object, Object> cache) throws CacheException {  
  48.         try {  
  49.             memcachedClient.replace(name, 0, cache);  
  50.         } catch (Exception e) {  
  51.             throw new CacheException(e);  
  52.         }  
  53.     }  
  54.   
  55.     @Override  
  56.     public void destroy() throws CacheException {  
  57.         try {  
  58.             memcachedClient.shutdown();  
  59.         } catch (Exception e) {  
  60.             throw new CacheException(e);  
  61.         }  
  62.     }  
  63.   
  64. }  


然后我们就开始把这自定义的管理器接入到shiro的缓存管理器


  1. /**  
  2.  *   
  3.  * 安全框架缓存管理器实现类  
  4.  *   
  5.  * @author shadow  
  6.  *   
  7.  */  
  8. public class ShiroCacheManager implements CacheManager, Destroyable {  
  9.   
  10.     private SimpleCacheManager simpleCacheManager;  
  11.   
  12.     @Override  
  13.     public Cache<Object, Object> getCache(String name) throws CacheException {  
  14.         return simpleCacheManager.getCache(name);  
  15.     }  
  16.   
  17.     @Override  
  18.     public void destroy() throws Exception {  
  19.         simpleCacheManager.destroy();  
  20.     }  
  21.   
  22.     public SimpleCacheManager getSimpleCacheManager() {  
  23.         return simpleCacheManager;  
  24.     }  
  25.   
  26.     public void setSimpleCacheManager(SimpleCacheManager simpleCacheManager) {  
  27.         this.simpleCacheManager = simpleCacheManager;  
  28.     }  
  29.   
  30. }  


最后配置下这个shiro的管理器实现类注入到需要的地方即可


  1. <!-- 安全管理器 -->  
  2.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  3.         <property name="sessionManager" ref="sessionManager" />  
  4.         <property name="cacheManager" ref="shiroCacheManager" />  
  5.         <property name="realm" ref="simpleUserRealm" />  
  6.     </bean>  
  7.   
  8.     <!-- 安全框架缓存管理器 -->  
  9.     <bean id="shiroCacheManager" class="com.silvery.security.shiro.cache.ShiroCacheManager">  
  10.         <property name="simpleCacheManager" ref="simpleCacheManager" />  
  11.     </bean>  
  12.   
  13.     <!-- 扩展缓存管理器 -->  
  14.     <bean id="simpleCacheManager"  
  15.         class="com.silvery.security.shiro.cache.extend.impl.SimpleCacheManagerImpl">  
  16.         <constructor-arg ref="memcachedClient" />  
  17.     </bean>  


配置好了之后,我们在需要地方把实例化的SimpeMapCache添加到我们的自己的管理器里面即可...


这个章节已经讲完了,谢谢大家的支持


欢迎拍砖...


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
第十章:Shiro的Cache
DataCache.GetCache是什么?-搜索墙
C# 数据缓存操作Cache
JAVA中用动态代理类实现记忆功能
XMemcached与Spring3.2缓存框架集成
Memcached笔记
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服