ABP+AdminLTE+Bootstrap Table权限管理系统一期 Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMShtml
为何要用缓存呢,说缓存以前先说使用缓存的优势。git
- 减小寄宿服务器的往返调用(round-trips)。
- 若是缓存在客户端或是代理,将减小对服务器的请求,减小带宽。
- 减小对数据库服务器的往返调用(round-trips)。
- 当内容缓存在web服务器,可以减轻对数据库的请求。
- 减小网络带宽。
- 避免了从新生成可重用内容的时耗。
- 提升性能
- 由于缓存减小了round-trips, network traffic(网络带宽),并避免- 了生成可重用内容的时耗,因此对性能有巨大的提升。
传统的缓存方式以下面这张图 github
<%@ OutputCache Duration="60" VaryByParam="none" %>
Duration 表示缓存的时间秒,必选,不然报错。if (this.Cache["Keys"] == null) { this.Cache.Insert("Keys", List, null, DateTime.Now.AddHours(2), TimeSpan.Zero); }
这里是检查缓存中Keys是否存在,若是不存在,则写入一个新的值List.还有其余的一些使用方法。 web
上面两种方式显然不在如今使用范畴,也不在我想说的范畴以内。,年代貌似有点久远,不用webform基本用不到。如今咱们更可能是的使用MVC。 咱们想说的是MVC输出缓存。redis
输出缓存:Outputcache
,分为Action输出缓存和Controller输出缓存。使用的场景包括某个页面的数据更新不是很频繁,不须要每次都从数据库区查询。缓存起来从内存中读取。数据库
数据缓存:是相对于全局的。任何地方须要调用的时候均可以去调用。使用的场景包括权限管理这种模块的。每一个角色对于菜单的访问都是固定的,因此有必要将角色,权限,菜单这种数据作一个全局的数据缓存。修改时再作缓存的更新。windows
输出缓存和数据缓存区别:打个比方输出缓存就像是“局部变量”,数据缓存就像是全局变量(只是个比喻)。缓存
Controller输出缓存和 Action缓存使用方式是同样的,就是Controller 或Action上打[OutPutCache]特性标签。可是他们之间又是有区别的。安全
1、控制器缓存服务器
Control缓存的做用域是整个控制器,因此在这个控制器下的全部Action都会被缓存起来。Control缓存的粒度比较粗,应用也比较少些。 [OutputCache(Duration = 10)] public class HomeController : Controller { public ActionResult Index() { ViewBag.CurrentTime = DateTime.Now; return View(); } }
2、Action缓存 将[OutPutCache]特性标签打在Action上,这样,只有加缓存的Action才会有缓存,其余的Action是没有的。
名称 | 描述 |
---|---|
AllowMultiple | 获取或设置一个值,该值指示是否可指定筛选器特性的多个实例。 |
CacheProfile | 获取或设置缓存配置文件名称。 |
ChildActionCache | 获取或设置子操做缓存。 |
Duration | 获取或设置缓存持续时间(以秒为单位)。 |
Location | 获取或设置位置。 |
NoStore | 获取或设置一个值,该值指示是否存储缓存。 |
Order | 获取或者设置执行操做筛选器的顺序。 |
SqlDependency | 获取或设置 SQL 依赖项。 |
TypeId | (从Attribute继承。) |
VaryByContentEncoding | 获取或设置基于内容变化的编码。 |
VaryByCustom | 获取或设置基于自定义项变化的值。 |
VaryByHeader | 获取或设置基于标头变化的值。 |
VaryByParam | 获取或设置基于参数变化的值。 |
举例其中的CacheProfile,这种方式便于统一配置,固然也能够设置参数duration、location 、varybyparam等。咱们须要在system.web 节点下加入这些
`
其实做用和效果仍是同样,无非就是方便点,统一的配置参数都直接写webconfig文件里面。其实也能够Controller中写。 配置好了以后咱们直接在控制器调用相应的名字的
OutputCache特性标签便可。
[OutputCache(CacheProfile= "TestConfigCache")] public ActionResult Index() { ViewBag.CurrentTime = DateTime.Now; return View(); } ` 更多的方式,须要下去再研究下。
ABP中有两种cache的实现方式:MemroyCache
和RedisCache
,二者都继承至ICache接口(准确说是CacheBase
抽象类)。ABP核心模块封装了MemroyCache
来实现ABP中的默认缓存功能。 Abp.RedisCache
这个模块封装RedisCache
来实现缓存(经过StackExchange.Redis
这个类库访问redis)。
ABP给出了一个抽象缓存基类。并在内部使用了该抽象基类。使用 MemoryCache 来实现了该抽象基类。它可以被任何其它的缓存类来扩展。Abp.RedisCache 包就扩展了该缓存基类。 ABP对外提供了一个缓存接口ICacheMananger。咱们经过构造函数注入这个接口来获取缓存。示例以下:
在这个示例中,咱们注入了 ICacheManager接口,s而且获取了一个名称为ControllerCache的缓存。首先咱们先对ControllerCache进行清除,而后存入缓存,缓存的名字是大小写敏感的,那就是"ControllerCache"和"CONTROLLERCACHE"取得的缓存内容是不一样的。
注意:GetCache方法 千万不要在你的构造函数中使用GetCache方法。若是类不是一个单例对象那么该缓存可能会被dispose掉。
ICacheManager.GetCache
方法返回了一个ICache
对象。每个缓存都是基于名称单例存在的。只有首次访问时才会被建立,之后你每次用相同的名称去获取的缓存都是相同的。因此咱们能够在不一样的类中使用相同的名称来共享相同的缓存。
在示例代码中,咱们简单的使用了ICache.Get
方法,它有两个参数:
ICache接口还有其它方法,如前面Clear()
,Get()
,GetOrDefault
,Set
,Remove
和Clear
。固然也有这些方法的异步(async)版本。以下图,我就懒得写了。
ICache
接口用key(字符串类型)来获取缓存value(object类型)。ITypedCache
为ICahe
提供了一个 类型安全 的包装;为了使类型安全转换(ICache
到ITypedCache
),咱们能够用扩展方法 AsTyped
,而不须要写其它强制类型转换的代码,以下所示: ITypedCache<int, Item> myCache = _cacheManager.GetCache("MyCache").AsTyped<int, Item>();
缓存的过时时间默认是60分钟。它是变化的。若是你在60分钟内没有使用该缓存,该缓存会被自动的移除。若是你想改变全部的缓存或者指定的缓存来的默认过时时间,你能够这样作,实现以下: //对全部缓存的配置 Configuration.Caching.ConfigureAll(cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2); });
//对指定缓存的配置 Configuration.Caching.Configure("MyCache", cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(8); });
这段代码你应该放在模块(module)的 PreInitialize
方法中。如上所示:MyCache
将会在8小时后过时,而其余的缓存将在2小时后过时。
这些配置将会在首次建立缓存的时候生效。配置不只仅局限于DefaultSlidingExpireTime
,你能够利用ICache
接口中的属性获取方法来自由的配置而且初始化它们。
ABP的缓存系统是以通用为目的,它有一个 EntityCache
基类,若是你须要的话,这个基类能够帮助你缓存实体。使用这个基类,咱们能够经过ID取得实体,而且咱们经过ID来缓存实体,这样之后就不须要频繁的查询数据库去取得实体。假设咱们有个Person
实体,像下面同样: public class Person : Entity { public string Name { get; set; } public int Age { get; set; } }
而且,假设咱们经过该实体的Id,须要频繁调用取得Person实体的Name。首先,咱们应该建立一个类来存储 cache items: [AutoMapFrom(typeof(Person))] public class PersonCacheItem { public string Name { get; set; } }
咱们 不该该直接存储实体到缓存中 由于缓存的时候须要序列化缓存对象而实体可能不能被序列化(尤为是实体的导航属性)。这就是为何咱们定义了一个简单的像DTO的类来存储数据到缓存中。咱们添加了 AutoMapFrom 特性,这是由于咱们想使用 AutoMapper 来自动的转换 Person 实体为 PersonCacheItem 对象。若是咱们不使用 AutoMapper,那么咱们应该重写 EntityCache 类的 MapToCacheItem 方法手动转换/映射它。
然而这不是必须的,咱们可能想定义一个接口为缓存类: public interface IPersonCache : IEntityCache<PersonCacheItem> { }
最后,咱们能够建立缓存类来缓存Person实体: public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency { public PersonCache(ICacheManager cacheManager, IRepository<Person> repository) : base(cacheManager, repository) { } }
这样就OK了,咱们的person缓存已经准备好可使用了。缓存类可使瞬时(如同这个例子)或者是单例。这不是说缓存数据是瞬态的。在你的应用程序中它一直是全局缓存而且是线程安全的。
如今,不管在什么地方咱们须要取得Person的Name,咱们能够经过Person的Id从缓存中取得它。以下所示: public class MyPersonService : ITransientDependency { private readonly IPersonCache _personCache; public MyPersonService(IPersonCache personCache) { _personCache = personCache; } public string GetPersonNameById(int id) { return _personCache[id].Name; //alternative: _personCache.Get(id).Name; } }
咱们很容易的注入 IPersonCache 接口,经过该接口取得缓存项和Name属性。
那么EntityCache是怎么工做的?
Redis是什么,Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它能够用做数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)与范围查询、bitmaps、hyperloglogs和地理空间(geospatial)索引半径查询。 Redis 是彻底开源免费的,遵照BSD协议,是一个高性能的key-value数据库。 Redis 与其余 key - value 缓存产品有如下三个特色:
(1)首先,咱们前往github.com/dmajkic/red…下载安装包,直接下一步下一步就能够了。 而后打开安装的地址就能够看到以下的文件:
redis-server.exe redis.windows.conf
就会看到下面的画面证实咱们启动服务成功。
<add key="Abp.Redis.Cache.DatabaseId" value="2"/>
在同一个服务器上使用不一样的数据库Id是很是有用的这能够建立不一样的Key Spaces(隔离缓存)。
UseRedis有一个重载方法,你能够经过这个方法来传入配置参数,这能够覆盖掉配置文件中的配置。关于Redis的其余配置能够查看
Redis文档。
在下面UserList打下断点调试进去。
Github项目地址:github.com/Jimmey-Jian…
ABP+AdminLTE+Bootstrap Table权限管理系统一期 [Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS](https://github.com/Jimmey-Jiang/ABP-