以前给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. springboot超级详细的日志配置(基于logback)

    前言   java web 下有好几种日志框架,比如:logback,log4j,log4j2(slj4f 并不是一种日志框架,它相当于定义了规范,实现了这个规范的日志框架就能够用 slj4f 调用) ...

  2. H5调起IOS原生商店支付

    参考文档:http://www.html5plus.org/doc/zh_cn/payment.html 申请内购项目摘自 https://www.jianshu.com/p/1e79bfbe46e2 ...

  3. centos7开启80端口及其他端口

    首先centos7的防火墙由iptables改为了firewalld 1. 执行命令:firewall-cmd --zone=public --add-port=80/tcp  --permanent ...

  4. 多选文件批量上传前端(ajax*formdata)+后台(Request.Files[i])---input+ajax原生上传

    1.配置Web.config;设定上传文件大小 <system.web> <!--上传1000M限制(https://www.cnblogs.com/Joans/p/4315411. ...

  5. postgressql启动与关闭

    POSTGRESSQL启动和停止数据库可以通过service方式 .POSTGRESSQL的命令行工具进行启动与停止. 1.使有SERVICE方式 启动数据库服务的命令如下·: #service po ...

  6. 转载-企业环境下MySQL5.5调优

    转载-企业环境下MySQL5.5调优 参照 腾讯云 和ucloud my.cnf 以及网上找的资料 整理出来的 my.cnf , 以后修改任何参数都会继续更新,目前是在测试阶段; 物理机 : ubun ...

  7. 关于RGBDSLAMV2学习、安装、调试过程

    Step1:https://github.com/felixendres/rgbdslam_v2/wiki/Instructions-for-Compiling-Rgbdslam-(V2)-on-a- ...

  8. GooglePlay测试支付遇到的问题

    推荐谷歌安装器,可以方便地安装谷歌框架及服务 问题列表 1.测试支付时出现:需要验证身份.您需要登录自己google账号 解决:我是使用VPN,VPN地区是日本,但我在google后台设置的发布(下载 ...

  9. 适用于在线服务的A/B测试方法论

    适用于在线服务的A/B测试方法论 简介: 这篇文章旨在介绍适用于为在线服务进行A/B测试(A/B Test)的方法论.中文网络中目前还缺乏全面的入门级介绍. 我将首先讨论在线服务业进行A/B测试所考虑 ...

  10. Mysql 查询当天、昨天、近7天、一周内、本月、上一月等的数据(函数执行日期的算术运算)

    注:where语句后中的字段last_login_time 替换成 时间字段名 即可 #查询昨天登录用户的账号 ; #查询当天登录用户的账号 ; #查询所有last_login_time值在最后1天内 ...