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

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

            上一章我们讲解了如何扩展集中式的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("Cache name cannot be null.");
		if (backingMap == null) {
			throw new IllegalArgumentException("Backing map cannot be null.");
		} 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("SimpleMapCache '")).append(name).append("' (").append(attributes.size()).append(
				" entries)").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("必须存在memcached客户端实例");
		}
		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="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="sessionManager" ref="sessionManager" />
		<property name="cacheManager" ref="shiroCacheManager" />
		<property name="realm" ref="simpleUserRealm" />
	</bean>

	<!-- 安全框架缓存管理器 -->
	<bean id="shiroCacheManager" class="com.silvery.security.shiro.cache.ShiroCacheManager">
		<property name="simpleCacheManager" ref="simpleCacheManager" />
	</bean>

	<!-- 扩展缓存管理器 -->
	<bean id="simpleCacheManager"
		class="com.silvery.security.shiro.cache.extend.impl.SimpleCacheManagerImpl">
		<constructor-arg ref="memcachedClient" />
	</bean>


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


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


欢迎拍砖...


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
10月前
|
Java 数据库连接 uml
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
47 0
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
|
10月前
|
XML Java 程序员
Spring官网阅读(八)容器的扩展点(三)(BeanPostProcessor)
Spring官网阅读(八)容器的扩展点(三)(BeanPostProcessor)
78 0
Spring官网阅读(八)容器的扩展点(三)(BeanPostProcessor)
|
10月前
|
XML 缓存 Java
Spring官网阅读(七)容器的扩展点(二)FactoryBean
Spring官网阅读(七)容器的扩展点(二)FactoryBean
79 0
Spring官网阅读(七)容器的扩展点(二)FactoryBean
|
XML Java 程序员
spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)
学习如何通过自己写代码的方式,向spring容器中注册bean
151 0
spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)
|
Java 程序员 网络安全
spring4.1.8扩展实战之四:感知spring容器变化(SmartLifecycle接口)
如果业务上需要在spring容器启动和关闭的时候做一些操作,可以自定义SmartLifecycle接口的实现类来扩展,本章我们通过先分析再实战的方法,来掌握这种扩展方式
145 1
spring4.1.8扩展实战之四:感知spring容器变化(SmartLifecycle接口)
|
SQL 人工智能 Kubernetes
微软为容器扩展 Azure 服务组合,发展基于微服务的云原生应用程序
在Microsoft Build 2022大会上,微软宣布基于 Kubernetes 的无服务器计算框架Azure Container Apps已全面上线。
119 0
|
XML Java 数据库
Spring5参考指南:容器扩展
Spring5参考指南:容器扩展
|
负载均衡 Kubernetes 网络协议
谁说docker-compose不能水平扩展容器、服务多实例?
虽说我已经从docker-compose走上了docker swarm的邪门歪道,目前被迫走在k8s这条康庄大道, 但是我还是喜欢docker-compose简洁有效的部署方式。
谁说docker-compose不能水平扩展容器、服务多实例?
|
网络协议 Unix API
iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
229 0
iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
|
网络协议 Unix API
进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
320 0
进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)
相关产品
容器镜像服务
容器服务Kubernetes版
推荐文章
更多