本文3.0版本文章
Redis 部分的内容,和netcore2.0一样,不需要更新。
代码已上传Github+Gitee,文末有地址
传统的缓存是在Controller中,将获取到的数据手动处理,然后当另一个controller中又使用的时候,还是Get,Set相关操作,当然如果小项目,有两三个缓存还好,如果是特别多的接口调用,面向Service服务层还是很有必要的,不需要额外写多余代码,只需要正常调取Service层的接口就行,AOP结合Autofac注入,会自动的查找,然后返回数据,不继续往下走Repository仓储了。
昨天我发布文章后,有一个网友提出了一个问题,他想的很好,就是如果面向到了Service层,那BaseService中的CURD等基本方法都被注入了,这样会造成太多的代理类,不仅没有必要,甚至还有问题,比如把Update也缓存了,这个就不是很好了,嗯,我也发现了这个问题,所以需要给AOP增加验证特性,只针对Service服务层中特定的常使用的方法数据进行缓存等。这样既能保证切面缓存的高效性,又能手动控制,不知道大家有没有其他的好办法,如果有的话,欢迎留言,或者加群咱们一起讨论,一起解决平时的问题。
零、今天完成的大红色部分
一、给缓存增加验证筛选特性
1、自定义缓存特性
在解决方案中添加新项目Blog.Core.Common,然后在该Common类库中添加 特性文件夹 和 特性实体类,以后特性就在这里
//CachingAttribute
///
/// 这个Attribute就是使用时候的验证,把它添加到要缓存数据的方法中,即可完成缓存的操作。注意是对Method验证有效
///
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public classCachingAttribute : Attribute
{
//缓存绝对过期时间
public int AbsoluteExpiration { get; set; } = 30;
}
2、在AOP拦截器中进行过滤
添加Common程序集引用,然后修改缓存AOP类方法 BlogCacheAOP=》Intercept,简单对方法的方法进行判断
//qCachingAttribute 代码
//Intercept方法是拦截的关键所在,也是IInterceptor接口中的唯一定义
public voidIntercept(IInvocation invocation)
{
var method = invocation.MethodInvocationTarget ??invocation.Method;
//对当前方法的特性验证
var qCachingAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CachingAttribute)) as CachingAttribute;
//只有那些指定的才可以被缓存,需要验证
if (qCachingAttribute != null)
{
//获取自定义缓存键
var cacheKey =CustomCacheKey(invocation);
//根据key获取相应的缓存值
var cacheValue =_cache.Get(cacheKey);
if (cacheValue != null)
{
//将当前获取到的缓存值,赋值给当前执行方法
invocation.ReturnValue =cacheValue;
return;
}
//去执行当前的方法
invocation.Proceed();
//存入缓存
if (!string.IsNullOrWhiteSpace(cacheKey))
{
_cache.Set(cacheKey, invocation.ReturnValue);
}
}
else{
invocation.Proceed();//直接执行被拦截方法
}
}
可见在invocation参数中,包含了几乎所有的方法,大家可以深入研究下,获取到自己需要的数据
3、在service层中增加缓存特性
在指定的Service层中的某些类的某些方法上增加特性(一定是方法,不懂的可以看定义特性的时候AttributeTargets.Method)
///
/// 获取博客列表
///
///
///
[Caching(AbsoluteExpiration = 10)]//增加特性
public async Task>getBlogs()
{
var bloglist = await dal.Query(a => a.bID > 0, a =>a.bID);
returnbloglist;
}
4、特定缓存效果展示
运行项目,打断点,就可以看到,普通的Query或者CURD等都不继续缓存了,只有咱们特定的 getBlogs()方法,带有缓存特性的才可以
当然,这里还有一个小问题,就是所有的方法还是走的切面,只是增加了过滤验证,大家也可以直接把那些需要的注入,不需要的干脆不注入Autofac容器,我之所以需要都经过的目的,就是想把它和日志结合,用来记录Service层的每一个请求,包括CURD的调用情况。
二、什么是Redis,为什么使用它
我个人有一个理解,关于Session或Cache等,在普通单服务器的项目中,很简单,有自己的生命周期等,想获取Session就获取,想拿啥就拿啥,但是在大型的分布式集群中,有可能这一秒的点击的页面和下一秒的都不在一个服务器上,对不对!想想如果普通的办法,怎么保证session的一致性,怎么获取相同的缓存数据,怎么有效的进行消息队列传递?
这个时候就用到了Redis,这些内容,网上已经到处都是,但是还是做下记录吧
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。它内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。在此基础上,Redis支持各种不同方式的排序。为