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添加到我们的自己的管理器里面即可...


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


欢迎拍砖...


目录
相关文章
|
5月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
352 86
|
4月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
614 5
|
11月前
|
数据采集 存储 数据可视化
分布式爬虫框架Scrapy-Redis实战指南
本文介绍如何使用Scrapy-Redis构建分布式爬虫系统,采集携程平台上热门城市的酒店价格与评价信息。通过代理IP、Cookie和User-Agent设置规避反爬策略,实现高效数据抓取。结合价格动态趋势分析,助力酒店业优化市场策略、提升服务质量。技术架构涵盖Scrapy-Redis核心调度、代理中间件及数据解析存储,提供完整的技术路线图与代码示例。
1143 0
分布式爬虫框架Scrapy-Redis实战指南
|
10月前
|
缓存 并行计算 PyTorch
PyTorch CUDA内存管理优化:深度理解GPU资源分配与缓存机制
本文深入探讨了PyTorch中GPU内存管理的核心机制,特别是CUDA缓存分配器的作用与优化策略。文章分析了常见的“CUDA out of memory”问题及其成因,并通过实际案例(如Llama 1B模型训练)展示了内存分配模式。PyTorch的缓存分配器通过内存池化、延迟释放和碎片化优化等技术,显著提升了内存使用效率,减少了系统调用开销。此外,文章还介绍了高级优化方法,包括混合精度训练、梯度检查点技术及自定义内存分配器配置。这些策略有助于开发者在有限硬件资源下实现更高性能的深度学习模型训练与推理。
1935 0
|
11月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
1047 79
|
9月前
|
缓存 NoSQL 算法
Redis数据库的键值过期和删除机制
我们需要注意的是,虽然Redis提供了这么多高级的缓存机制,但在使用过程中,必须理解应用的特性,选择合适的缓存策略,才能最大化Redis的性能。因此,在设计和实施应用程序时,理解应用的数据访问模式,以及这些模式如何与Redis的缓存机制相互作用,尤为重要。
297 24
|
11月前
|
缓存 NoSQL Java
Redis应用—8.相关的缓存框架
本文介绍了Ehcache和Guava Cache两个缓存框架及其使用方法,以及如何自定义缓存。主要内容包括:Ehcache缓存框架、Guava Cache缓存框架、自定义缓存。总结:Ehcache适合用作本地缓存或与Redis结合使用,Guava Cache则提供了更灵活的缓存管理和更高的并发性能。自定义缓存可以根据具体需求选择不同的数据结构和引用类型来实现特定的缓存策略。
693 16
Redis应用—8.相关的缓存框架
|
12月前
|
存储 缓存 分布式计算
【赵渝强老师】Spark RDD的缓存机制
Spark RDD通过`persist`或`cache`方法可将计算结果缓存,但并非立即生效,而是在触发action时才缓存到内存中供重用。`cache`方法实际调用了`persist(StorageLevel.MEMORY_ONLY)`。RDD缓存可能因内存不足被删除,建议结合检查点机制保证容错。示例中,读取大文件并多次调用`count`,使用缓存后执行效率显著提升,最后一次计算仅耗时98ms。
347 0
【赵渝强老师】Spark RDD的缓存机制
|
缓存 NoSQL Java
Redis的操作以及SpringCache框架
以及如何在Spring Boot应用中使用Spring Cache框架集成Redis。Redis提供了丰富的数据结构和高效的内存存储能力,结合Spring Cache框架,可以显著提高应用的性能和响应速度。
385 7
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
858 26