ASP.NET Core Web API中实现缓存
在.NET 6中,你可以使用几种方式来实现缓存,但最直接的方法之一是使用ResponseCaching
中间件或自定义的ActionFilterAttribute
(动作过滤器)。
1. 使用ResponseCaching中间件
ASP.NET Core 提供了一个内置的ResponseCaching
中间件,它可以很容易地配置来缓存HTTP响应。这对于静态内容和一些动态内容(如基于查询参数的响应)非常有用。
首先,在Program.cs
或Startup.cs
中启用响应缓存中间件:
// 在Program.cs中(针对.NET 6)
var builder = WebApplication.CreateBuilder(args); // 添加响应缓存服务
builder.Services.AddResponseCaching(); var app = builder.Build(); // 使用响应缓存中间件
if (!app.Environment.IsDevelopment())
{ app.UseResponseCaching();
} // 其余配置... app.Run();
然后,你可以通过属性或中间件配置来控制哪些响应应该被缓存。例如,在Controller或Action上使用[ResponseCache]
属性:
[ApiController]
[Route("[controller]")]
public class ValuesController : ControllerBase
{ [HttpGet] [ResponseCache(Duration = 10, Location = ResponseCacheLocation.Client)] public IActionResult Get() { // 假设这里是一些耗时的操作 return Ok(new string[] { "value1", "value2" }); }
}
2. 自定义ActionFilterAttribute实现缓存
如果你需要更复杂的缓存逻辑(比如基于缓存键的动态内容),你可能需要实现一个自定义的ActionFilterAttribute
。
public class CacheFilterAttribute : ActionFilterAttribute
{ private readonly IMemoryCache _cache; public CacheFilterAttribute(IMemoryCache cache) { _cache = cache; } public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 假设这里有一个简单的缓存键生成逻辑 var cacheKey = $"CacheFilter-{context.HttpContext.Request.Path}-{context.HttpContext.Request.QueryString}"; if (_cache.TryGetValue(cacheKey, out var cachedResponse)) { // 缓存命中,返回缓存的内容 context.Result = new ObjectResult(cachedResponse) { StatusCode = StatusCodes.Status200OK }; } else { // 缓存未命中,继续执行Action var resultContext = await next(); // 将结果缓存起来 _cache.Set(cacheKey, await resultContext.Result.ExecuteAsync(context.HttpContext.Response.Body), TimeSpan.FromMinutes(10)); // 注意:这里实际上并没有改变执行流程,只是为了演示如何缓存结果 // 正常情况下,你应该直接返回resultContext.Result } }
} // 在Controller或Action上应用
[ServiceFilter(typeof(CacheFilterAttribute))]
注意:上面的自定义缓存过滤器示例为了简化,直接在OnActionExecutionAsync
中进行了缓存逻辑的处理,但这种方式实际上并不推荐用于生产环境,因为它会改变正常的请求处理流程(如直接返回缓存结果而不是执行Action)。通常,你可能需要在OnResultExecutionAsync
中处理缓存逻辑,并在缓存未命中时调用next()
来执行Action。
另外,请注意,当使用自定义过滤器进行缓存时,务必处理好并发和缓存失效等问题。