本篇博客记录一下我在实习的公司的后台管理系统开发框架中学习到的一种关于网站的缓存(Cache)的实现方法,我会在弄懂的基础上,将该方法在.net core上进行实现。因为公司开发都是基于.net framework的,但是在.net 这一块,.net framework正在逐渐被.net core所取代,而目前公司的前辈们由于开发任务较重,并没有着手使用.net core的打算,所以,我自己打算为公司搭建一个基于.net core的后台开发框架,这对自己是一个挑战,但收获还是很大的,在这个过程中,我学到了很多。下面我记录一下我们公司关于网站设计中Cache的一种设计与实现方法(先说在.net mvc下的实现方法,后续会写另一篇.net core的实现方法):

  • 总体设计:

  我们知道的缓存一般分为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
{
/// <summary>
/// 缓存操作类
/// </summary>
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(, , ), 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(, , ), 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
{
/// <summary>
/// 缓存操作类
/// </summary>
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(, , ), 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";
/// <summary>
/// 获取或设置当前登录用户
/// </summary>
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 下的实现方式有些区别,这个,我会另起一篇博客去记录。

说明:本片博客并没有完整的demo,所有的代码都已贴出。

一种小型后台管理系统通用开发框架中的Cache缓存设计的更多相关文章

  1. Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)

    Ajax跨域问题及解决方案   目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...

  2. ASP.NET Core中使用Cache缓存

    ASP.NET Core中使用Cache缓存 缓存介绍: 通过减少生成内容所需的工作,缓存可以显著提高应用的性能和可伸缩性. 缓存对不经常更改的数据效果最佳. 缓存生成的数据副本的返回速度可以比从原始 ...

  3. Svelte Ui Admin后台管理系统|svelte3+svelteUI中后台前端解决方案

    基于svelte3.x+svelteKit+svelte-ui网页后台管理系统SvelteAdmin. Svelte-Ui-Admin 基于svelte3.x+svelteKit+vite3+echa ...

  4. 后台管理系统·快速开发框架JSite

    平台介绍 框架基于Maven构建,拆分成多个子模块,层次结构清晰.可用于所有Web应用,如企业后台管理系统.OA系统.CMS.CRM等. 框架本身集成了最新的 Flowable工作流引擎 https: ...

  5. 【共享单车】—— React后台管理系统开发手记:主页面架构设计

    前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录.最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star. ...

  6. c#中的Cache缓存技术

    1.HttpRuntime.Cache 相当于就是一个缓存具体实现类,这个类虽然被放在了 System.Web 命名空间下了.但是非 Web 应用也是可以拿来用的. 2.HttpContext.Cac ...

  7. 释放linux内存中的cache缓存

    echo 3 > /proc/sys/vm/drop_caches 记一次 经常用  exp 导出oracle全量数据库,发现linux内存一直在减小没有释放,即使 oracle重启也不行,只有 ...

  8. ASP.NET 中HttpRuntime.Cache缓存数据

    最近在开始一个微信开发,发现微信的Access_Token获取每天次数是有限的,然后想到缓存,正好看到微信教程里面推荐HttpRuntime.Cache缓存就顺便看了下. 写了(Copy)了一个辅助类 ...

  9. React版/Vue版都齐了,开源一套【特别】的后台管理系统...

    本项目主要基于Elux+Antd构建,包含React版本和Vue版本,旨在提供给大家一个简单基础.开箱即用的后台管理系统通用模版,主要包含运行环境.脚手架.代码风格.基本Layout.状态管理.路由管 ...

随机推荐

  1. 安装教程-VMware 12 安装Ubuntu 19.04 桌面版

    VMware 12 安装Ubuntu 19.04 桌面版 1.实验描述 在虚拟机中,手动安装 Ubuntu 19.04 操作系统,为学习 Linux 桌面版提供平台,因此,有的参数有些差异,请勿较真. ...

  2. 十五、Mysql字符集的那些事

    1. 设置默认字符集 #vim /etc/mysql/my.cnf .(5.5以后系统)如下修改: [client] default-character-set=utf8 [mysqld] defau ...

  3. Rust语言中的常量,变量,运算符,数据类型

    简单练练, 夏天太热. const MAX_POINTS: u32 = 100_100; fn main() { let mut x = 5; let y = 5; let y = y + 1; le ...

  4. Python Treelib 多叉树 数据结构 中文使用帮助文档

    树,对于计算机编程语言来说是一个重要的数据结构.它具有广泛的应用,比如文件系统的分层数据结构和机器学习中的一些算法.这里创建了treelib来提供Python中树数据结构的高效实现. 官方文档:htt ...

  5. c# 第一节 .net与c#区分

    本节内容: 三个概念:1:.net 和c# 区分2:c# 可以做的事情3:.net 的两种交互模式 1:.net 和c# 区分 .net 一般指.Net Framework框架,是Microsoft为 ...

  6. mysql基础sql进阶

    回顾前面的基础命令语句 修改数据表 添加字段: alter table 表名 add 字段名 列类型[not null|null][primary key][unique][auto_incremen ...

  7. 01-numpy-笔记-empty

    import numpy as np >>> a = np.empty([2,3]) >>> a array([[0.00000000e+000, 4.935933 ...

  8. zz2019年主动学习有哪些进展?答案在这三篇论文里

    2019年主动学习有哪些进展?答案在这三篇论文里 目前推广应用的机器学习方法或模型主要解决分类问题,即给定一组数据(文本.图像.视频等),判断数据类别或将同类数据归类等,训练过程依赖于已标注类别的训练 ...

  9. USACO Score Inflation

    洛谷 P2722 总分 Score Inflation https://www.luogu.org/problem/P2722 JDOJ 1697: Score Inflation https://n ...

  10. TYVJ1071 LCIS 线性DP+决策集优化

    问题描述 TYVJ1071 题解 暴力\(\mathrm{DP}\) 首先,一个\(O(n^3)\)的解法: 设\(opt_{i,j}\)代表\(a\)的前\(i\)个和\(b\)的前\(j\)个的\ ...