.NET Core教程--给API加一个服务端缓存啦
以前给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加一个服务端缓存啦的更多相关文章
- 多个微信小程序一个服务端架构
由于某些特定的业务场景,当多个小程序需要一个服务端后台提供数据时,大家可能想到是HTTP路由.是的,实际上我们使用微服务的GateWay网关也是一样的,如下图微服务架构: 网关GateWay的作用在于 ...
- chkconfig-增加一个服务设置服务自启动
参考 http://www.cnblogs.com/panjun-Donet/archive/2010/08/10/1796873.html 如何增加一个服务: 1.服务脚本必须存放在/etc/ini ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
- ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析
ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...
- 基于 springMVC 的 RESTful HTTP API 实践(服务端)
理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他2000年 ...
- socket基础实例(一个服务端对应一个客户端情形)
服务端处理1个客户端的例子 运行结果: (1) while(accept+if(recv)) 情形 执行服务端进程: [root@localhost single_link]# ./server [s ...
- 简单服务端缓存API设计
Want 我们希望设计一套缓存API,适应不同的缓存产品,并且基于Spring框架完美集成应用开发. 本文旨在针对缓存产品定义一个轻量级的客户端访问框架,目标支持多种缓存产品,面向接口编程,目前支持简 ...
- java基于socket的网络通信,实现一个服务端多个客户端的群聊,传输文件功能,界面使用Swing
最近在复习java的io流及网络编程.但复习写那些样板程序总是乏味的.便准备写个项目来巩固.想来想去还是聊天项目比较好玩.如果日后完成的比较好自己也可以用(哈哈哈).并且自己后面也要继续巩固java多 ...
- WebService或HTTP服务端接收请求转发消息到另一个服务端-实现思路
1.需求结构(WebService) A客户端<->B服务端<->C服务端 说明: a.在B服务端上面添加配置项(1.是否转发消息到C服务端:2.C服务端IP和端口): b.A ...
随机推荐
- ubuntu安装mysql数据库方法
ubuntu基于linux的免费开源桌面PC操作系统,十分契合英特尔的超极本定位,支持x86.64位和ppc架构.一个比较流行的Linux操作系统,不仅简单易用,而且和Windows相容性非常好.那么 ...
- vue-element-admin 前端框架 使用感触
感触: 不搜不知道,一搜吓一跳!经常百度很重要. 美国有gitgub:https://github.com/search?q=vue-element-admin 中国有码云:https://gitee ...
- SetCurrentCellAddressCore 函数的可重入调用
绑定数据在线程中 private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { if (Di ...
- 阿里P7整理20个非常有用的Java程序片段,你知道吗?
1.字符串有整型的相互转换 String a = String.valueOf(2); //integer to numeric string int i = Integer.parseInt( ...
- Flink使用(二)——Flink集群资源规划
前言 本文主要译自Flink Forward 2017的柏林站中Robert Metzger的有关集群规划的How to size your flink cluster一文.该文中主要是考虑网络资源, ...
- js对属性的操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- XML知识学习
第一部分[基础篇]: https://www.w3school.com.cn/xml/xml_intro.asp W3C教程地址 什么是 XML? XML 指可扩展标记语言(EXtensible Ma ...
- 宁波市第二届CTF之cripto1
密码学第一题 给的是一个shadow文件,16进制编辑器打开 是一串Linux root用户密码的密文,猜测密码可能就是flag,于是将这一串字符放到文本. linux下爆破用户密码的工具没接触过(还 ...
- mysql主从-ms
一.环境准备 1.准备两台安装有mysql的linux服务器 2.安装的mysql版本最好相同 3.配置两台服务器的主机名和IP地址,主机名:master和slave,IP地址:192.168.0.2 ...
- 完成N!的程序编写: 1、用循环算法编写; 2、用递归算法编写;
完成N!的程序编写 1.用循环算法编写 #include<iostream> using namespace std; int main(){ int n; long result = 1 ...