TinyFrame升级之五:全局缓存的设计及实现
2014-04-15 22:41
337 查看
在任何框架中,缓存都是不可或缺的一部分,本框架亦然。在这个框架中,我们的缓存分为两部分:内存缓存和单次请求缓存。简单说来,就是一个使用微软提供的MemoryCache做扩展,并提供全局唯一实例;另一个使用微软提供的HttpContextBase做扩展,用户每发送一次请求,HttpContextBase都会被关联创建。先来看下接口约束:
[code]usingSystem.Collections.Generic;
[/code]
方法不多,但是包含了缓存的增删查。其中Get泛型方法可以通过Key返回缓存对象;Set方法可以添加缓存;IsSet方法可以检测缓存是否存在;Remove方法可以清除已有的单个缓存;RemoveByPattern可以通过正则匹配清除缓存;Clear方法则清除全部缓存。
首先是MemoryCacheManager的实现:
[code]usingSystem.Collections.Generic;
[/code]
然后是PerRequestCacheManager的实现:
[code]usingSystem.Collections.Generic;
[/code]
二者的实现方式差不多。这里我就不做过多的解释了。
如果想使用的话,直接在Autofac容器中注册一下就行了。在这次演示中,我们使用MemoryCacheManager来做缓存容器。
这里我以一个分页为例:
[code]//分页查询
[/code]
第1行:定义了一个Cache的Key,用于标识保存ID
第23行:利用get方法检查缓存容器,如果缓存中数据不存在,则将查询数据添加到缓存;否则直接从缓存中拿出数据来。
我们来看看效果:
首先打开页面,我们换换页,目的是让页面被缓存住:
然后我们打开SQL的SQLServerProfile来进行追踪,现在,我们点击页面的刷新按钮,看看测试效果:
当我们连续刷新页面好几次,但是并未见到有新的分页查询被追踪到,说明我们的数据被缓存住了。
最后我们加个断点调试一下缓存对象,可以找到被缓存的数据:
usingSystem;
[code]usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceTinyFrame.Framework.Caching
{
publicinterfaceICacheManager
{
//根据key获取缓存对象
TGet<T>(stringkey);
//设置缓存对象
voidSet(stringkey,objectdata,intcacheTime);
//查询key是否被缓存
boolIsSet(stringkey);
//从缓存移除
voidRemove(stringkey);
//缓存移除匹配
voidRemoveByPattern(stringpattern);
//清空所有缓存
voidClear();
}
}
[/code]
方法不多,但是包含了缓存的增删查。其中Get泛型方法可以通过Key返回缓存对象;Set方法可以添加缓存;IsSet方法可以检测缓存是否存在;Remove方法可以清除已有的单个缓存;RemoveByPattern可以通过正则匹配清除缓存;Clear方法则清除全部缓存。
首先是MemoryCacheManager的实现:
usingSystem;
[code]usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Runtime.Caching;
usingSystem.Text.RegularExpressions;
namespaceTinyFrame.Framework.Caching
{
publicclassMemoryCacheManager:ICacheManager
{
protectedObjectCacheCache
{
get{returnMemoryCache.Default;}
}
publicTGet<T>(stringkey)
{
return(T)Cache[key];
}
publicvoidSet(stringkey,objectdata,intcacheTime)
{
if(data==null)
return;
varpolicy=newCacheItemPolicy();
policy.AbsoluteExpiration=DateTime.Now+TimeSpan.FromMinutes(cacheTime);
Cache.Add(newCacheItem(key,data),policy);
}
publicboolIsSet(stringkey)
{
returnCache.Contains(key);
}
publicvoidRemove(stringkey)
{
Cache.Remove(key);
}
publicvoidRemoveByPattern(stringpattern)
{
varregex=newRegex(pattern,RegexOptions.Singleline
|RegexOptions.Compiled
|RegexOptions.IgnoreCase);
varkeysToRemove=newList<string>();
foreach(variteminCache)
if(regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach(stringkeyinkeysToRemove)
{
Remove(key);
}
}
publicvoidClear()
{
foreach(variteminCache)
{
Remove(item.Key);
}
}
}
}
[/code]
然后是PerRequestCacheManager的实现:
usingSystem;
[code]usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Web;
usingSystem.Collections;
usingSystem.Text.RegularExpressions;
namespaceTinyFrame.Framework.Caching
{
publicclassPerRequestCacheManager:ICacheManager
{
publicPerRequestCacheManager(HttpContextBasecontext)
{
this.context=context;
}
privatereadonlyHttpContextBasecontext;
protectedvirtualIDictionaryGetItems()
{
if(context!=null)
returncontext.Items;
returnnull;
}
publicTGet<T>(stringkey)
{
varitems=GetItems();
if(items==null)
returndefault(T);
return(T)items[key];
}
publicvoidSet(stringkey,objectdata,intcacheTime)
{
varitems=GetItems();
if(items==null)
return;
if(data!=null)
{
if(items.Contains(key))
items[key]=data;
else
items.Add(key,data);
}
}
publicboolIsSet(stringkey)
{
varitems=GetItems();
if(items==null)
returnfalse;
returnitems[key]!=null;
}
publicvoidRemove(stringkey)
{
varitems=GetItems();
if(items==null)
return;
items.Remove(key);
}
publicvoidRemoveByPattern(stringpattern)
{
varitems=GetItems();
if(items==null)
return;
varenumerator=items.GetEnumerator();
varregex=newRegex(pattern,RegexOptions.Singleline
|RegexOptions.Compiled
|RegexOptions.IgnoreCase);
varkeysToRemove=newList<string>();
while(enumerator.MoveNext())
{
if(regex.IsMatch(enumerator.Key.ToString()))
{
keysToRemove.Add(enumerator.Key.ToString());
}
}
foreach(stringkeyinkeysToRemove)
{
items.Remove(key);
}
}
publicvoidClear()
{
varitems=GetItems();
if(items==null)
return;
varenumerator=items.GetEnumerator();
varkeysToRemove=newList<string>();
while(enumerator.MoveNext())
{
keysToRemove.Add(enumerator.Key.ToString());
}
foreach(stringkeyinkeysToRemove)
{
items.Remove(key);
}
}
}
}
[/code]
二者的实现方式差不多。这里我就不做过多的解释了。
如果想使用的话,直接在Autofac容器中注册一下就行了。在这次演示中,我们使用MemoryCacheManager来做缓存容器。
这里我以一个分页为例:
stringBookPaggerKey="Books-{0}-{1}-{2}-{3}";
[code]//分页查询
publicIList<Book>GetBooksPagger(intpageCount
,intcurrentIndex
,outinttotalCount
,stringpropertyName=""
,stringpropertyValue=""
)
{
IQueryable<Book>bookList=null;
intskipRows=0;
if(currentIndex>0)skipRows=currentIndex*pageCount;
if(!string.IsNullOrEmpty(propertyName))
bookList=GetBooksByConstruct(propertyName,propertyValue);
else
bookList=bookRepository.GetMany(m=>m.ID>=0);
totalCount=bookList.Count();
//returnbookList.OrderBy(p=>p.ID).Skip(skipRows).Take(pageCount).ToList();
stringkey=string.Format(BookPaggerKey,pageCount,currentIndex,propertyName,propertyValue);
returncacheManager.Get(key,()=>bookList.OrderBy(p=>p.ID).Skip(skipRows).Take(pageCount).ToList());
}
[/code]
第1行:定义了一个Cache的Key,用于标识保存ID
第23行:利用get方法检查缓存容器,如果缓存中数据不存在,则将查询数据添加到缓存;否则直接从缓存中拿出数据来。
我们来看看效果:
首先打开页面,我们换换页,目的是让页面被缓存住:
然后我们打开SQL的SQLServerProfile来进行追踪,现在,我们点击页面的刷新按钮,看看测试效果:
当我们连续刷新页面好几次,但是并未见到有新的分页查询被追踪到,说明我们的数据被缓存住了。
最后我们加个断点调试一下缓存对象,可以找到被缓存的数据:
相关文章推荐
- TinyFrame升级之八:实现简易插件化开发
- TinyFrame升级之六:全局日志的设计及实现
- uboot 下基于usb 和 fat32 升级模块的设计和实现
- bzoj 4008(浅谈全局整体考虑设计状态实现期望dp)
- iOS开发:一个瀑布流的设计与实现(已实现缓存池功能,该功能使得瀑布流cell可以循环利用)
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- SSM 之《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理(六)》 MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
- 【Leetcode】:LRU Cache_缓存淘汰算法LRU的设计与实现
- Mybatis源码研究7:缓存的设计和实现
- 项目实战之中小网站数据缓存的设计与实现
- iOS开发:一个高仿美团的团购ipad客户端的设计和实现(功能:根据拼音进行检索并展示数据,离线缓存团购数据,浏览记录与收藏记录的批量删除等)
- vc动态升级模块的设计与实现[网络中的虚拟实验平台]
- atitit。全局变量的设计与实现 java php的异同
- codeigniter读取数据库的公共配置并全局缓存的实现方案
- 自动升级系统OAUS的设计与实现(续) (附最新源码)
- TinySTL设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现