设为首页 收藏本站
查看: 2082|回复: 0

[经验分享] shiro安全框架扩展教程--如何扩展实现我们的缓存机制(第三方容器redis,memcached)

[复制链接]

尚未签到

发表于 2015-11-12 12:01:58 | 显示全部楼层 |阅读模式
  上一章我们讲解了如何扩展集中式的session管理方便我们集群的应用项目,无须再使用复制session的方式来完善用户体系;下面我主要分享如何扩展shiro里的缓存实现,
  大家都知道有点规模的项目都必须会使用缓存这个好东西,所以一个好的框架基本都会包含一套多级缓存的机制,例如spring,hibernate等也会有自己一套,象第三方的oscache,ehcache等等;
  


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


  package org.apache.shiro.cache;
import java.util.Collection;
import java.util.Set;
// Referenced classes of package org.apache.shiro.cache:
//            CacheException
public interface Cache
{
public abstract Object get(Object obj)
throws CacheException;
public abstract Object put(Object obj, Object obj1)
throws CacheException;
public abstract Object remove(Object obj)
throws CacheException;
public abstract void clear()
throws CacheException;
public abstract int size();
public abstract Set keys();
public abstract Collection values();
}

很明显看到跟我们普通的cache差不多,也是CRUD等等方法,然后看看有shiro写的有哪些实现类
  一个是org.apache.shiro.cache.ehcache.EhCache
  一个是org.apache.shiro.cache.MapCache
  然后看着名字我们就大概知道一个是基于encache框架来作为实现类基础,一个是以本地map来装载数据到内存达到缓存的效果,这里类的源码可以自己看看,比较简单,shiro入门后的都能看懂,但是这些实现类都不适合我用,我想要的是用memcached或是redis作为数据的缓存容器
  


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


  


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


  /**
*
* 缓存实现类,实现序列 接口方便对象存储于第三方容器(Map存放键值对)
*
*
*/
@SuppressWarnings("serial")
public class SimpleMapCache implements Cache<Object, Object>, Serializable {
private final Map<Object, Object> attributes;
private final String name;
public SimpleMapCache(String name, Map<Object, Object> backingMap) {
if (name == null)
throw new IllegalArgumentException(&quot;Cache name cannot be null.&quot;);
if (backingMap == null) {
throw new IllegalArgumentException(&quot;Backing map cannot be null.&quot;);
} else {
this.name = name;
attributes = backingMap;
}
}
public Object get(Object key) throws CacheException {
return attributes.get(key);
}
public Object put(Object key, Object value) throws CacheException {
return attributes.put(key, value);
}
public Object remove(Object key) throws CacheException {
return attributes.remove(key);
}
public void clear() throws CacheException {
attributes.clear();
}
public int size() {
return attributes.size();
}
public Set<Object> keys() {
Set<Object> keys = attributes.keySet();
if (!keys.isEmpty())
return Collections.unmodifiableSet(keys);
else
return Collections.emptySet();
}
public Collection<Object> values() {
Collection<Object> values = attributes.values();
if (!CollectionUtils.isEmpty(values))
return Collections.unmodifiableCollection(values);
else
return Collections.emptySet();
}
public String toString() {
return (new StringBuilder(&quot;SimpleMapCache '&quot;)).append(name).append(&quot;' (&quot;).append(attributes.size()).append(
&quot; entries)&quot;).toString();
}
}




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


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


  


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


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


  /**
*
* 缓存管理器接口
*
* @author shadow
*
*/
public interface SimpleCacheManager {
/**
* 新增缓存堆到管理器
*
* @param name
* @param cache
*/
public abstract void createCache(String name, Cache<Object, Object> cache) throws CacheException;
/**
* 获取缓存堆
*
* @param name
* @return
* @throws CacheException
*/
public abstract Cache<Object, Object> getCache(String name) throws CacheException;
/**
* 移除缓存堆
*
* @param name
* @throws CacheException
*/
public abstract void removeCache(String name) throws CacheException;
/**
* 更新缓存堆
*
* @param name
* @param cache
*/
public abstract void updateCahce(String name, Cache<Object, Object> cache) throws CacheException;
/**
* 注销管理器
*/
public abstract void destroy() throws CacheException;
}


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


  /**
*
* 缓存管理器实现类
*
* @author shadow
*
*/
public class SimpleCacheManagerImpl implements SimpleCacheManager {
private MemcachedClient memcachedClient;
public SimpleCacheManagerImpl(MemcachedClient memcachedClient) {
if (memcachedClient == null) {
throw new RuntimeException(&quot;必须存在memcached客户端实例&quot;);
}
this.memcachedClient = memcachedClient;
}
@Override
public void createCache(String name, Cache<Object, Object> cache) throws CacheException {
try {
memcachedClient.set(name, 0, cache);
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public Cache<Object, Object> getCache(String name) throws CacheException {
try {
return memcachedClient.get(name);
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public void removeCache(String name) throws CacheException {
try {
memcachedClient.delete(name);
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public void updateCahce(String name, Cache<Object, Object> cache) throws CacheException {
try {
memcachedClient.replace(name, 0, cache);
} catch (Exception e) {
throw new CacheException(e);
}
}
@Override
public void destroy() throws CacheException {
try {
memcachedClient.shutdown();
} catch (Exception e) {
throw new CacheException(e);
}
}
}




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


  /**
*
* 安全框架缓存管理器实现类
*
* @author shadow
*
*/
public class ShiroCacheManager implements CacheManager, Destroyable {
private SimpleCacheManager simpleCacheManager;
@Override
public Cache<Object, Object> getCache(String name) throws CacheException {
return simpleCacheManager.getCache(name);
}
@Override
public void destroy() throws Exception {
simpleCacheManager.destroy();
}
public SimpleCacheManager getSimpleCacheManager() {
return simpleCacheManager;
}
public void setSimpleCacheManager(SimpleCacheManager simpleCacheManager) {
this.simpleCacheManager = simpleCacheManager;
}
}




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


  <!-- 安全管理器 -->
<bean id=&quot;securityManager&quot; class=&quot;org.apache.shiro.web.mgt.DefaultWebSecurityManager&quot;>
<property name=&quot;sessionManager&quot; ref=&quot;sessionManager&quot; />
<property name=&quot;cacheManager&quot; ref=&quot;shiroCacheManager&quot; />
<property name=&quot;realm&quot; ref=&quot;simpleUserRealm&quot; />
</bean>
<!-- 安全框架缓存管理器 -->
<bean id=&quot;shiroCacheManager&quot; class=&quot;com.silvery.security.shiro.cache.ShiroCacheManager&quot;>
<property name=&quot;simpleCacheManager&quot; ref=&quot;simpleCacheManager&quot; />
</bean>
<!-- 扩展缓存管理器 -->
<bean id=&quot;simpleCacheManager&quot;
class=&quot;com.silvery.security.shiro.cache.extend.impl.SimpleCacheManagerImpl&quot;>
<constructor-arg ref=&quot;memcachedClient&quot; />
</bean>




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


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


  欢迎拍砖...


  



版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-138302-1-1.html 上篇帖子: redis读写分离下的高可用设计与实现(上) 下篇帖子: redis客户端PhpRedis介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表