一种小型后台管理系统通用开发框架中的Cache缓存设计
作者:互联网
我们知道的缓存一般分为3种,分别是 Cookies,Session和Cache,这三种的区别和使用场景我在这里就不说了,网上有大神的博客说的很清楚。Cookies主要用于客户端,Session和Cache用于服务端,本篇主要讲Cahe的使用。Cache存储于服务器的内存中,允许自定义如何缓存数据项,以及缓存时间有多长。当系统内存缺乏时,缓存会自动移除很少使用或者使用优先级较低的缓存项以释放内存。Cache的使用可以提高整个系统的运行效率。
Cache在使用上也是(key,value)形式的,关于插入、获取、移除什么的,都可以在Cache类中去查看,这里贴出Cache这个类的内容:
复制代码
#region 程序集 System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\System.Web.dll
#endregion
using System.Collections;
using System.Reflection;
namespace System.Web.Caching
{
//
// 摘要:
// Implements the cache for a Web application. This class cannot be inherited.
[DefaultMember(“Item”)]
public sealed class Cache : IEnumerable
{
public static readonly DateTime NoAbsoluteExpiration;
public static readonly TimeSpan NoSlidingExpiration;
public Cache();
public object this[string key] { get; set; }
public int Count { get; }
public long EffectivePrivateBytesLimit { get; }
public long EffectivePercentagePhysicalMemoryLimit { get; }
public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
public object Get(string key);
public IDictionaryEnumerator GetEnumerator();
public void Insert(string key, object value);
public void Insert(string key, object value, CacheDependency dependencies);
public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
public object Remove(string key);
}
}
复制代码
可以看到里面有Add,Get,Insert之类的东西,这些用法网上也有很清楚的讲述,我也不赘述,也说不清楚,哈哈。
下面,结合上面那张示意图,来说明一下我要讲的缓存设计,个人感觉还是比较好的。
<key,value>的形式,就是一个value对应一个key,通过key可以设置value的值,也可以获取value的值。在这里我们把 每个用户登录时生成的一个唯一的 id 做为 cache的key,然后把希望放到缓存中的数据作为value,进行缓存数据的处理。但是,我们放到value中的值,可能是有不同用途不同种类的一些值,比如,登录用户的基本信息,该系统存储的菜单数据,这两个就是用途完全不相干的两类数据,怎么存储呢?再另外使用一个key值不同的cache,这应该也是可以的。但是,我们这里讲的方法只使用一个Cache。
具体做法呢,就是把这个value定义为一个 Dictionary<key,value>类型的值,这样在value里面,我们就可以通过设置不同的key值,来存储不同用途的缓存数据了。
第一步
首先,先定义一个存储value数据的类,代码如下:
UserCache.cs
复制代码
using System.Collections.Generic;
namespace Common
{
public class UserCache
{
private readonly Dictionary<string, object> cacheDictionary = new Dictionary<string, object>();
private readonly object lockObj = new object();
/// <summary>
/// 索引器
/// </summary>
/// <param name="key">key</param>
/// <returns>缓存对象</returns>
public object this[string key]
{
get
{
lock (lockObj)
{
return cacheDictionary.ContainsKey(key) ? cacheDictionary[key] : null;
}
}
set
{
lock(lockObj)
{
if (cacheDictionary.ContainsKey(key))
{
cacheDictionary[key] = value;
}
else
{
cacheDictionary.Add(key, value);
}
}
}
}
public void Remove(string key)
{
lock (lockObj)
{
if(cacheDictionary.ContainsKey(key))
{
cacheDictionary.Remove(key);
}
}
}
public void Clear()
{
lock(lockObj)
{
cacheDictionary.Clear();
}
}
}
}
复制代码
上面的代码,用到了一个索引器,这使得我们可以像数组那样用 XXX[index]这样的方法访问和设置数据,从代码中我们可以看到,这个类最终都实现对 cacheDictionary 这个字典的操作,因为我们的数据都存储在这个字典中。不管你想存储什么数据只需要定义一个key值,然后存储到字典中即可。
第二步
定义好UserCache.cs后,我们再来写关于缓存操作的类:
先定义缓存操作类,然后书写关于缓存操作的代码:
WebCache.cs(部分)
复制代码
using System;
using System.Web;
using System.Web.Caching;
using Common;
namespace Console
{
///
/// 缓存操作类
///
public class WebCache
{
#region 私有变量
private const string UserIdentifyKey = "CacheUserIdentifyKey";
#endregion
#region 私有方法
private static string GetUserIdentify()
{
if (HttpContext.Current.Session[UserIdentifyKey] != null)
return HttpContext.Current.Session[UserIdentifyKey].ToString();
var identify = Guid.NewGuid().ToString();
HttpContext.Current.Session[UserIdentifyKey] = identify;
return identify;
}
private static UserCache GetUserCache()
{
var identify = GetUserIdentify();
if (HttpContext.Current.Cache.Get(identify) == null)
{
HttpContext.Current.Cache.Insert(identify, new UserCache(), null, Cache.NoAbsoluteExpiration,
new TimeSpan(0, 20, 0), CacheItemPriority.High, CacheRemovedCallback);
}
return HttpContext.Current.Cache.Get(identify) as UserCache;
}
/// <summary>
/// 缓存被移除时触发
/// </summary>
/// <param name="key">被移除的缓存的key</param>
/// <param name="value">被移除的缓存的值</param>
/// <param name="reason">移除原因</param>
private static void CacheRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
// 缓存被移除时执行的操作
// 如果是手动移除,则不处理
//if (reason == CacheItemRemovedReason.Removed)
// return;
// 此处访问页面会报错,暂时注释掉
// ShowNotification(MessageType.Warning, "警告", "由于您太久没操作页面已过期,请重新登录!", true);
}
#endregion
}
}
复制代码
首先看上面的代码:
上面三段代码中,核心的代码是第二段,需要注意的是,都是静态方法:
GetUserCache() 方法
当然,我们还是从第一段代码开始说起,
GetUserIdentify()
复制代码
private static string GetUserIdentify()
{
if (HttpContext.Current.Session[UserIdentifyKey] != null)
return HttpContext.Current.Session[UserIdentifyKey].ToString();
var identify = Guid.NewGuid().ToString();
HttpContext.Current.Session[UserIdentifyKey] = identify;
return identify;
}
复制代码
在一个用户登录之初,我们首先给这个用户生成一个唯一的用户 id ,然后把这个id保存到 Session中 (Session也是<key,value>形式的)。在第二段代码中,通过 GetUserIdentify()方法获取用户的唯一 id,然后把这个唯一 id作为 Cache的key值。
然后,我们来看第二段代码:
GetUserCache():
复制代码
private static UserCache GetUserCache()
{
var identify = GetUserIdentify();
if (HttpContext.Current.Cache.Get(identify) == null)
{
HttpContext.Current.Cache.Insert(identify, new UserCache(), null, Cache.NoAbsoluteExpiration,
new TimeSpan(0, 20, 0), CacheItemPriority.High, CacheRemovedCallback);
}
return HttpContext.Current.Cache.Get(identify) as UserCache;
}
复制代码
这段代码,首先判断Cache中是否有值(是否存在这个key的Cache),若不存在,则创建一个(代码中的 new UserCache())。.net framework中Cache操作使用 HttpContext.Current.Cache,Insert后有若干个参数,意思分别是:
identify:key值;
new UserCache():value值;
第三个参数是:缓存依赖项 CacheDependency ,这里是 null;
Cache.NoAbsoluteExpiration:绝对过期时间 ,这里设置为无绝对过期时间;
new TimeSpan(0, 20, 0):这是滑动过期时间,此处设置为 20 minite;
CacheItemPriority.High:缓存优先级,此处为 high;
CacheRemovedCallback: 缓存移除时的回调函数,这个回调函数的参数是固定写法,必须按照规定写,三个参数以及参数类型 不可缺少也不可写错,否则会报错;(具体可见上面的第三段代码)
上面说到,若不存在,则创建一个 ,若存在,那么就直接返回即可。
接下来,在WebCache.cs中定义一些公共方法,用来供外界的方法调用,以实现对缓存的操作,代码如下:
WebCache.cs(全):
复制代码
using System;
using System.Web;
using System.Web.Caching;
using Common;
namespace Console
{
///
/// 缓存操作类
///
public class WebCache
{
#region 私有变量
private const string UserIdentifyKey = "CacheUserIdentifyKey";
#endregion
#region 公共方法
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
public static object GetCache(string key)
{
return GetUserCache()[key];
}
/// <summary>
/// 设置缓存
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns></returns>
public static bool SetCache(string key, object value)
{
try
{
var userCache = GetUserCache();
userCache[key] = value;
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 清空缓存
/// </summary>
/// <returns></returns>
public static bool ClearCache()
{
try
{
// 只清除缓存内容
// GetUserCache().Clear();
// 直接从Cache里移除
var identify = GetUserIdentify();
HttpContext.Current.Cache.Remove(identify);
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 移除缓存
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
public static bool RemoveCache(string key)
{
try
{
GetUserCache().Remove(key);
return true;
}
catch
{
return false;
}
}
#endregion
#region 私有方法
private static string GetUserIdentify()
{
if (HttpContext.Current.Session[UserIdentifyKey] != null)
return HttpContext.Current.Session[UserIdentifyKey].ToString();
var identify = Guid.NewGuid().ToString();
HttpContext.Current.Session[UserIdentifyKey] = identify;
return identify;
}
private static UserCache GetUserCache()
{
var identify = GetUserIdentify();
if (HttpContext.Current.Cache.Get(identify) == null)
{
HttpContext.Current.Cache.Insert(identify, new UserCache(), null, Cache.NoAbsoluteExpiration,
new TimeSpan(0, 20, 0), CacheItemPriority.High, CacheRemovedCallback);
}
return HttpContext.Current.Cache.Get(identify) as UserCache; // as是一种强制类型转化的方式
}
/// <summary>
/// 缓存被移除时触发
/// </summary>
/// <param name="key">被移除的缓存的key</param>
/// <param name="value">被移除的缓存的值</param>
/// <param name="reason">移除原因</param>
private static void CacheRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
// 缓存被移除时执行的操作
// 如果是手动移除,则不处理
//if (reason == CacheItemRemovedReason.Removed)
// return;
// 此处访问页面会报错,暂时注释掉
// ShowNotification(MessageType.Warning, "警告", "由于您太久没操作页面已过期,请重新登录!", true);
}
#endregion
}
}
复制代码
依次定义了GetCache(),SetCache(),RemoveCache(),ClearCache()四个方法,供外界调用,来实现对缓存的操作。
到这里,基本上关于这个Cache的实现就已经讲完了,下面,给出一段代码,做一个使用的示例。
复制代码
private const string LoginUserKey = “CacheKey-LoginUserCacheKey”;
///
/// 获取或设置当前登录用户
///
public static User LoginUser
{
get { return WebCache.GetCache(LoginUserKey) as User; }
set { WebCache.SetCache(LoginUserKey, value); }
}
复制代码
SetCache():
WebCache.SetCache(key, value);
RemoveCache():
RemoveCache(key); //移除字典中某个缓存值
ClearCache();
ClearCache(); //清空缓存的字典
关于这个缓存设计,就记录到这里了,关于.net core下的实现,因为.net core下并没有System.Web这个类,所以它的Cache实现方式,与.net 下的实现方式有些区别,这个,我会另起一篇博客去记录。
深圳网站建设 https://www.sz886.com/
标签:缓存,管理系统,Cache,value,identify,key,public 来源: https://blog.csdn.net/weixin_45032957/article/details/90081192