在WebApi中想使用缓存,对一些结果集进行缓存,这样可以减小数据库服务器的压力。缓存可以看情况使用,一般缓存哪些经常被查询到并且一般不会更新的数据。
该文章使用MemoryCache来达到缓存数据目的,当然缓存技术有很多种,例如redis,memcache等待。
下面用示例说明MemoryCache的用法
1.自定义类CustomResourceFilterAttribute,继承Attribute,并实现接口IResourceFilter
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using System;
namespace MyBlog.WebApi.Utility.FilterUtil
{
/// <summary>
/// 自定义资源过滤器 作为特性使用
/// </summary>
public class CustomResourceFilterAttribute : Attribute, IResourceFilter
{
private IMemoryCache _memoryCache;
public CustomResourceFilterAttribute(IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
}
/// <summary>
/// 此方法在执行action后被调用
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuted(ResourceExecutedContext context)
{
string path = context.HttpContext.Request.Path;//api/test/GetCacheTest
string route = context.HttpContext.Request.QueryString.Value;//?name='11'
string key = path + route;
//将路径作为key,结果集作为value放到MemoryCache中,此处的context.Result是指action的返回值
_memoryCache.Set(key, context.Result);
}
/// <summary>
/// 此方法在执行action前被调用
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuting(ResourceExecutingContext context)
{
string path = context.HttpContext.Request.Path;//api/test/GetCacheTest
string route = context.HttpContext.Request.QueryString.Value;//?name='11'
string key = path + route;
//检查MemoryCache中是否存在相同的key值,存在则直接从缓存中返回数据;不存在则调用action
if (_memoryCache.TryGetValue(key, out object value))
{
context.Result = value as IActionResult; //执行到此行时,直接返回缓存中的结果,action和OnResourceExecuted都不会被执行
}
}
}
}
自定义一个资源过滤器的类,继承Attribute类,是为了该类可以作为特性在方法中使用;实现IResourceFilter接口,是为了实现资源过滤器的方法,在action执行前后执行自定义的逻辑。
2.在Startup.cs中对MemoryCache进行注入,这里不需要额外引用程序集,因为在新建WebApi项目时,框架已经引入了相关的方法,直接调用即可。
3.在控制器的action中使用缓存
[TypeFilter(typeof(CustomResourceFilterAttribute))]
[HttpGet("GetCacheTest")]
public IActionResult GetCacheTest(string strName)
{
//模拟从数据库查询数据
return new JsonResult(new
{
name = strName,
age = 18,
sex = "男"
});
}
下面展示下代码的执行过程:
第一次调用,数据没有被缓存过:
代码的执行过程:
①先执行过滤器的OnResourceExecuting方法,尝试从缓存中根据key值读取数据,发现缓存中没有对应key值的数据。
②接着执行控制器中的action方法GetCacheTest。
③action执行完毕,获取到数据后执行过滤器的OnResourceExecuted方法,将action返回的数据添加到缓存中。
第二次调用,数据已经在缓存中,查询缓存中的数据:
代码的执行过程:
①先执行过滤器的OnResourceExecuting方法,尝试从缓存中根据key值读取数据,发现缓存中有对应key值的数据,直接将缓存中的数据返回给调用者。没有执行控制器的action方法,也没有执行过滤器的OnResourceExecuted方法。
缓存的key是由'路径+请求参数'一起组成的一个字符串,只有当路径和请求参数同时变化时,才会重新查询数据库,返回新的数据,并将新的数据添加到缓存中。
也可以设置数据在缓存中的过期时间,当数据过期后,再去缓存中查询就查不到了,这时候就会自动调用action,从数据库查询最新的记录。
为缓存数据设置过期时间:
缓存过期时间的单位可以为:毫秒、秒、分钟、小时、天。