以前给API接口写缓存基本都是这样写代码:

// redis key
var bookRedisKey = ConstRedisKey.RecommendationBooks.CopyOne(bookId);
// 获取缓存数据
var cacheBookIds = _redisService.ReadCache<List<string>>(bookRedisKey);
if (cacheBookIds != null)
{
// return
}
else
{
// 执行另外的逻辑获取数据, 然后写入缓存
}

然后把这一坨坨代码都散落在每个地方。

某一天,突然想起我这边的缓存基本时间都差不多,而且都是给Web API用的,

直接在API层支持缓存不就完事了。

所以, 这里用什么来做呢。

在.NET Core Web API这里的话, 两种思路:Middleware 或者ActionFilter.

不了解的同学可以看下面的文档:

ASP.NET Core 中文文档 第四章 MVC(4.3)过滤器

ASP.NET Core 中文文档 第三章 原理(2)中间件

基于我这边只是部分接口支持缓存的话, 直接还是用ActionFilter实现就可以.

没撒说的, 直接上代码.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json.Linq; namespace XXXAPI.Filters
{
public class DefaultCacheFilterAttribute : ActionFilterAttribute
{
// 这个时间用于给子类重写,实现不同时间级别的缓存
protected TimeSpan _expireTime; // redis读写的类,没撒看的
private readonly RedisService _redisService; public DefaultCacheFilterAttribute(RedisService redisService)
{
_redisService = redisService; } public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Request.Query.ContainsKey("refresh"))
{
return;
}
KeyConfig redisKey = GetRequestRedisKey(context.HttpContext);
var redisCache = _redisService.ReadCache<JToken>(redisKey);
if (redisCache != null)
{
context.Result = new ObjectResult(redisCache);
}
return;
} public override void OnActionExecuted(ActionExecutedContext context)
{
KeyConfig redisKey = GetRequestRedisKey(context.HttpContext);
var objResult = (ObjectResult)context.Result;
if (objResult == null)
{
return;
}
var jToken = JToken.FromObject(objResult.Value);
_redisService.WriteCache(redisKey, jToken);
} private KeyConfig GetRequestRedisKey(HttpContext httpContext)
{
var requestPath = httpContext.Request.Path.Value;
if (!string.IsNullOrEmpty(httpContext.Request.QueryString.Value))
{
requestPath = requestPath + httpContext.Request.QueryString.Value;
}
if (httpContext.Request.Query.ContainsKey("refresh"))
{
if (httpContext.Request.Query.Count == 1)
{
requestPath = requestPath.Replace("?refresh=true", "");
}
else
{
requestPath = requestPath.Replace("refresh=true", "");
}
}
// 这里也就一个redis key的类
var redisKey = ConstRedisKey.HTTPRequest.CopyOne(requestPath);
if (_expireTime != default(TimeSpan))
{
redisKey.ExpireTime = _expireTime;
}
return redisKey;
}
} public static class ConstRedisKey
{
public readonly static KeyConfig HTTPRequest = new KeyConfig()
{
Key = "lemon_req_",
ExpireTime = new TimeSpan(TimeSpan.TicksPerMinute * 30),
DBName = 5
};
} public class KeyConfig
{
public string Key { get; set; } public TimeSpan ExpireTime { get; set; } public int DBName { get; set; } public KeyConfig CopyOne(string state)
{
var one = new KeyConfig();
one.DBName = this.DBName;
one.Key = !string.IsNullOrEmpty(this.Key) ? this.Key + state : state;
one.ExpireTime = this.ExpireTime;
return one;
} }
}

然后使用的地方, 直接给Controller的Action方法加上注解即可.

如:

        [HttpGet("v1/xxx/latest")]
[ServiceFilter(typeof(DefaultCacheFilterAttribute))]
public IActionResult GetLatestList([FromQuery] int page = 0, [FromQuery]int pageSize = 30)
{
return Ok(new
{
data = _service.LoadLatest(page, pageSize),
code = 0
});
}

完事...

哦, 记得在Startup.cs注入 DefaultCacheFilterAttribute.

这个注入就不用我来写的吧.

美中不足的地方在于暂时还不知道怎么直接在注解上面支持自定义缓存时间,

凑合先用了.

完结, 拜.....

.NET Core教程--给API加一个服务端缓存啦的更多相关文章

  1. 多个微信小程序一个服务端架构

    由于某些特定的业务场景,当多个小程序需要一个服务端后台提供数据时,大家可能想到是HTTP路由.是的,实际上我们使用微服务的GateWay网关也是一样的,如下图微服务架构: 网关GateWay的作用在于 ...

  2. chkconfig-增加一个服务设置服务自启动

    参考 http://www.cnblogs.com/panjun-Donet/archive/2010/08/10/1796873.html 如何增加一个服务: 1.服务脚本必须存放在/etc/ini ...

  3. react+redux教程(六)redux服务端渲染流程

    今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...

  4. ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析

    ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...

  5. 基于 springMVC 的 RESTful HTTP API 实践(服务端)

    理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他2000年 ...

  6. socket基础实例(一个服务端对应一个客户端情形)

    服务端处理1个客户端的例子 运行结果: (1) while(accept+if(recv)) 情形 执行服务端进程: [root@localhost single_link]# ./server [s ...

  7. 简单服务端缓存API设计

    Want 我们希望设计一套缓存API,适应不同的缓存产品,并且基于Spring框架完美集成应用开发. 本文旨在针对缓存产品定义一个轻量级的客户端访问框架,目标支持多种缓存产品,面向接口编程,目前支持简 ...

  8. java基于socket的网络通信,实现一个服务端多个客户端的群聊,传输文件功能,界面使用Swing

    最近在复习java的io流及网络编程.但复习写那些样板程序总是乏味的.便准备写个项目来巩固.想来想去还是聊天项目比较好玩.如果日后完成的比较好自己也可以用(哈哈哈).并且自己后面也要继续巩固java多 ...

  9. WebService或HTTP服务端接收请求转发消息到另一个服务端-实现思路

    1.需求结构(WebService) A客户端<->B服务端<->C服务端 说明: a.在B服务端上面添加配置项(1.是否转发消息到C服务端:2.C服务端IP和端口): b.A ...

随机推荐

  1. chrome滚动条颜色尺寸设置

    <style> /*chrome滚动条颜色设置*/ *::-webkit-scrollbar { width: 5px; height: 10px; background-color: t ...

  2. 如何在Hybris commerce里创建一个media对象

    进入backoffice的Media中心, 首先新建一个文件夹,用于存放即将创建的media对象: 取名为jerryimage: 然后创建一个新的media对象,取名jerryproductimage ...

  3. Android笔记(五十一) 短信验证码集成——mob平台

    官方网站:www.mob.com 注册帐号,下载SDK,导入SDK就不说了,主要写一下简单集成如何使用,以后忘记了也可以翻着看看. 详细的可以参考官方文档: http://wiki.mob.com/a ...

  4. Jackson动态处理返回字段

    有时候业务需要动态返回字段,比如, 场景一:返回 name , birthday, createDate 场景二:返回name, birthday, age 现做个备忘录,以便参考. 下面是引入的PO ...

  5. docker 安装及使用介绍

    docker 安装及使用用介绍 安装docker所依赖的基础环境 1 64 bits CPU 2 Linux Kernel 3.10+ //如果低于则需要手动给内核打补丁.因为分层构建联合挂载系统得在 ...

  6. Microsoft Edge设置socks代理

    自已摸的,非官方: 直接修改注册表: REGEDIT4 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Se ...

  7. MongoDB的关闭

    关闭 1,非后台运行时,关闭对话,或者ctrl+c 2,登录数据库执行:db.shutdownServer(); 3,带数据目录,关闭服务器,安全   mongod --shutdown --dbpa ...

  8. 加速 Unity 不同平台打包的一种思路

    Unity打包总的来说还不是一件特别复杂的事情, 但是我们知道任何关于跨平台(多线程等)这类问题, 总是会把事情搞得复杂起来. 以前项目的打包是通过Jenkins对一个工程下对不同平台多次打包, 不可 ...

  9. weighted—-LR的理解与推广

    在YouTube团队推荐系统Rank阶段,DNN输出层使用了weighted-LR,这既是这篇论文的一大创新点,也是一大难点.在这里,重新梳理下该算法的思路与推导,并进行推广. 理解 先说下常见的逻辑 ...

  10. linux系统编程之信号(二)

    经过了漫长的间歇,对于c语言的学习也被中断了很久,现实确实有很多的无耐,计划中的事情总会被打乱,但不管怎样,学习的道路是不能休止的,所以经过了一断温习后现在继续学习C语言,话不多说,进入正题: 信号分 ...