5、加入缓存支持

我们希望为项目增加缓存支持,我们选择Redis做为缓存数据库。

首先,我们在Services目录增加一个缓存接口类ICacheService:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

namespace ChainStoreAPI.Services

{

public interface ICacheService

{

/// <summary>

/// 验证缓存项是否存在

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

bool Exists(string key);

/// <summary>

/// 验证缓存项是否存在(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

Task<bool> ExistsAsync(string key);

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <returns></returns>

bool Add(string key, object value);

/// <summary>

/// 添加缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <returns></returns>

Task<bool> AddAsync(string key, object value);

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);

/// <summary>

/// 添加缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <returns></returns>

bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false);

/// <summary>

/// 添加缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <returns></returns>

Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);

/// <summary>

/// 删除缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

bool Remove(string key);

/// <summary>

/// 删除缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

Task<bool> RemoveAsync(string key);

/// <summary>

/// 批量删除缓存

/// </summary>

/// <param name="key">缓存Key集合</param>

/// <returns></returns>

void RemoveAll(IEnumerable<string> keys);

/// <summary>

/// 批量删除缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key集合</param>

/// <returns></returns>

Task RemoveAllAsync(IEnumerable<string> keys);

/// <summary>

/// 获取缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

T Get<T>(string key) where T : class;

/// <summary>

/// 获取缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

Task<T> GetAsync<T>(string key) where T : class;

/// <summary>

/// 获取缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

object Get(string key);

/// <summary>

/// 获取缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

Task<object> GetAsync(string key);

/// <summary>

/// 获取缓存集合

/// </summary>

/// <param name="keys">缓存Key集合</param>

/// <returns></returns>

IDictionary<string, object> GetAll(IEnumerable<string> keys);

/// <summary>

/// 获取缓存集合(异步方式)

/// </summary>

/// <param name="keys">缓存Key集合</param>

/// <returns></returns>

Task<IDictionary<string, object>> GetAllAsync(IEnumerable<string> keys);

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <returns></returns>

bool Replace(string key, object value);

/// <summary>

/// 修改缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <returns></returns>

Task<bool> ReplaceAsync(string key, object value);

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);

/// <summary>

/// 修改缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <returns></returns>

bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false);

/// <summary>

/// 修改缓存(异步方式)

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <returns></returns>

Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);

}

}

然后,在增加实现类之前,先引入Redis的依赖项:

选择Microsoft.Extensions.Caching.Redis,版本选择2.1.2,安装一下。

在Services\Impl目录增加Redis的缓存实现类RedisCacheService:

using Microsoft.Extensions.Caching.Redis;

using Newtonsoft.Json;

using StackExchange.Redis;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace ChainStoreAPI.Services.Impl

{

public class RedisCacheService : ICacheService

{

protected IDatabase _cache;

private ConnectionMultiplexer _connection;

private readonly string _instance;

/// <summary>

/// 构造函数

/// </summary>

/// <param name="options"></param>

/// <param name="database"></param>

public RedisCacheService(RedisCacheOptions options, int database = 0)

{

_connection = ConnectionMultiplexer.Connect(options.Configuration);

_cache = _connection.GetDatabase(database);

_instance = options.InstanceName;

}

/// <summary>

/// 为Key添加实例名

/// </summary>

/// <param name="key"></param>

/// <returns></returns>

public string GetKeyForRedis(string key)

{

return _instance + ":" + key;

}

#region 验证缓存项是否存在

/// <summary>

/// 验证缓存项是否存在

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

public bool Exists(string key)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

return _cache.KeyExists(GetKeyForRedis(key));

}

public async Task<bool> ExistsAsync(string key)

{

bool result = await Task.Run(() => Exists(key));

return result;

}

#endregion

#region 添加缓存

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <returns></returns>

public bool Add(string key, object value)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));

}

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiressAbsoulte);

}

/// <summary>

/// 添加缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>

/// <returns></returns>

public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiresIn);

}

public async Task<bool> AddAsync(string key, object value)

{

bool result = await Task.Run(() => Add(key, value));

return result;

}

public async Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)

{

bool result = await Task.Run(() => Add(key, value, expiresSliding, expiressAbsoulte));

return result;

}

public async Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)

{

bool result = await Task.Run(() => Add(key, value, expiresIn, isSliding));

return result;

}

#endregion

#region 删除缓存

/// <summary>

/// 删除缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

public bool Remove(string key)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

return _cache.KeyDelete(GetKeyForRedis(key));

}

/// <summary>

/// 批量删除缓存

/// </summary>

/// <param name="key">缓存Key集合</param>

/// <returns></returns>

public void RemoveAll(IEnumerable<string> keys)

{

if (keys == null)

{

throw new ArgumentNullException(nameof(keys));

}

keys.ToList().ForEach(item => Remove(item));

}

public async Task<bool> RemoveAsync(string key)

{

bool result = await Task.Run(() => Remove(key));

return result;

}

public async Task RemoveAllAsync(IEnumerable<string> keys)

{

await Task.Run(() => RemoveAll(keys));

}

#endregion

#region 获取缓存

/// <summary>

/// 获取缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

public T Get<T>(string key) where T : class

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

var value = _cache.StringGet(GetKeyForRedis(key));

if (!value.HasValue)

{

return default(T);

}

return JsonConvert.DeserializeObject<T>(value);

}

/// <summary>

/// 获取缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <returns></returns>

public object Get(string key)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

var value = _cache.StringGet(GetKeyForRedis(key));

if (!value.HasValue)

{

return null;

}

return JsonConvert.DeserializeObject(value);

}

/// <summary>

/// 获取缓存集合

/// </summary>

/// <param name="keys">缓存Key集合</param>

/// <returns></returns>

public IDictionary<string, object> GetAll(IEnumerable<string> keys)

{

if (keys == null)

{

throw new ArgumentNullException(nameof(keys));

}

var dict = new Dictionary<string, object>();

keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));

return dict;

}

public async Task<T> GetAsync<T>(string key) where T : class

{

T result = await Task.Run(() => Get(key)) as T;

return result;

}

public async Task<object> GetAsync(string key)

{

object result = await Task.Run(() => Get(key));

return result;

}

public async Task<IDictionary<string, object>> GetAllAsync(IEnumerable<string> keys)

{

IDictionary<string, object> result = await Task.Run(() => GetAll(keys));

return result;

}

#endregion

#region 修改缓存

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <returns></returns>

public bool Replace(string key, object value)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

if (Exists(key))

if (!Remove(key))

return false;

return Add(key, value);

}

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <param name="expiressAbsoulte">绝对过期时长</param>

/// <returns></returns>

public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

if (Exists(key))

if (!Remove(key))

return false;

return Add(key, value, expiresSliding, expiressAbsoulte);

}

/// <summary>

/// 修改缓存

/// </summary>

/// <param name="key">缓存Key</param>

/// <param name="value">新的缓存Value</param>

/// <param name="expiresIn">缓存时长</param>

/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>

/// <returns></returns>

public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)

{

if (key == null)

{

throw new ArgumentNullException(nameof(key));

}

if (Exists(key))

if (!Remove(key)) return false;

return Add(key, value, expiresIn, isSliding);

}

public async Task<bool> ReplaceAsync(string key, object value)

{

bool result = await Task.Run(() => Replace(key, value));

return result;

}

public async Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)

{

bool result = await Task.Run(() => Replace(key, value, expiresSliding, expiressAbsoulte));

return result;

}

public async Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)

{

bool result = await Task.Run(() => Replace(key, value, expiresIn, isSliding));

return result;

}

#endregion

/// <summary>

/// 释放

/// </summary>

public void Dispose()

{

if (_connection != null)

_connection.Dispose();

GC.SuppressFinalize(this);

}

}

}

在配置文件appsettings.json中加入Redis的链接字符串:

"RedisConnectionString": "127.0.0.1:6379"

然后打开Startup.cs,引入缓存服务类:

当然,现在我们需要安装好Redis并启动:

运行run.bat即可:

我们将控制器TestController.cs重命名为MemberController.cs:

再新增测试控制器,将来我们的测试代码都在这里面实现:

我们只保留Get方法,其他全删除:

修改BaseController,加入缓存支持:

这样,我们就可以在所有继承BaseController的控制器中使用缓存了。

修改MemberController和TestController的构造函数:

下面我们在测试控制器中写代码测试一下缓存的写入和读取:

// GET: api/Test

[HttpGet]

public ResultInfo Get()

{

cache.Add("test", "这是一个测试字符串");

string value = cache.Get<string>("test");

return new ResultInfo() { Code = "0", Message = "成功", Data = value };

}

运行看一下效果:

打开RedisDesktopManager看一下Redis数据库中是否写入:

基于.Net Core的API框架的搭建(3)的更多相关文章

  1. 基于.Net Core的API框架的搭建(1)

    目标 我们的目标是要搭建一个API控制器的项目,API控制器提供业务服务. 一.开发框架搭建 1.开发前准备 开发前,我们需要下载如下软件,安装过程略: (1) 开发工具:VS2017 (2) 数据库 ...

  2. 基于.Net Core的API框架的搭建(2)

    4.加入数据库支持 下面我们为项目加入数据库支持,修改appsettings.json: 然后我们要生成实体类,打开VS工具->NuGet包管理器->程序包管理器控制台: 输入命令: Sc ...

  3. 基于.Net Core的API框架的搭建(4)

    6.加入日志功能 日志我们选用log4net,首先引入程序包: 选择2.0.8版本安装.然后在项目根目录新增log4net的配置文件log4net.config: <?xml version=& ...

  4. 基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)

    一.前言 至今为止编程开发已经11个年头,从 VB6.0,ASP时代到ASP.NET再到MVC, 从中见证了.NET技术发展,从无畏无知的懵懂少年,到现在的中年大叔,从中的酸甜苦辣也只有本人自知.随着 ...

  5. 基于.NET CORE微服务框架 -谈谈surging API网关

    1.前言 对于最近surging更新的API 网关大家也有所关注,也收到了不少反馈提出是否能介绍下Api网关,那么我们将在此篇文章中剥析下surging的Api 网关 开源地址:https://git ...

  6. 基于DotNet Core的RPC框架(一) DotBPE.RPC快速开始

    0x00 简介 DotBPE.RPC是一款基于dotnet core编写的RPC框架,而它的爸爸DotBPE,目标是实现一个开箱即用的微服务框架,但是它还差点意思,还仅仅在构思和尝试的阶段.但不管怎么 ...

  7. 基于.net core 2.0+mysql+AceAdmin搭建一套快速开发框架

    前言 .net core已经出来一段时间了,相信大家对.net core的概念已经很清楚了,这里就不再赘述.笔者目前也用.net core做过一些项目,并且将以前framework下的一些经验移植到了 ...

  8. Ocelot——初识基于.Net Core的API网关

    前言 前不久看到一篇<.NET Core 在腾讯财付通的企业级应用开发实践>,给现在研究.Net Core及想往微服务方向发展的人来了一剂强心针.于是我也就立刻去下Ocelot的源码及去阅 ...

  9. 一个轻量级的基于 .NET Core 的 ORM 框架 HSQL

    HSQL 是一种轻量级的基于 .NET Core 的数据库对象关系映射「ORM」框架 HSQL 是一种可以使用非常简单且高效的方式进行数据库操作的一种框架,通过简单的语法,使数据库操作不再成为难事.目 ...

随机推荐

  1. 【NOIP2017】宝藏(状压DP)

    题意: 思路:n<=12,考虑状压DP 生成树中深度相同的点可以一次性转移完毕 设dp[sta,i]为已转移完sta状态的点,当前深度为i的最小花费 dp[sta or v,i+1]=min(d ...

  2. 【NOIP2016】蚯蚓(单调队列)

    题意: 思路: 我们发现,对于任意两次切割i和j,i<j,在进行完第j次切割后,第i次切割的u/v部分一定大于等于第j次切割的u/v部分,第i次的1-u/v部分也一定大于等于第j次的1-u/v部 ...

  3. codevs 3971 航班

    题目描述 Description B 国有N 座城市,其中1 号是这座国家的首都. N 座城市之间有M 趟双向航班.i 号点的转机次数定义为:从1 号点到i ,最少需要转机几 次.如果1 根本无法到达 ...

  4. [bzoj1485][HNOI2009]有趣的数列_卡特兰数_组合数

    有趣的数列 bzoj-1485 HNOI-2009 题目大意:求所有1~2n的排列满足奇数项递增,偶数项递增.相邻奇数项大于偶数项的序列个数%P. 注释:$1\le n\le 10^6$,$1\le ...

  5. [bzoj4827][Hnoi2017]礼物_FFT

    礼物 bzoj-4827 Hnoi-2017 题目大意:给定两个长度为$n$的手环,第一个手环上的$n$个权值为$x_i$,第二个为$y_i$.现在我可以同时将所有的$x_i$同时加上自然数$c$.我 ...

  6. JSON/xml、Processing 以及收集Java的设计模型

    JSON简介: 1.基本介绍 JSON(JavaScriptObject Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于ECMAScript(欧洲计算机协会制定的js规范)的 ...

  7. 洛谷 P2064 奇妙的汽车

    P2064 奇妙的汽车 题目描述 你有着一辆奇妙的汽车,这辆汽车有着自动加速的功能.打个比方吧,第1天你驾驶着它可以行驶a路程,那么第2天你可以让它所走的路程增加到第1天的2~9倍(必须是其中一个整数 ...

  8. 【结果发布】第六届SeedCoder编程大赛初赛结果发布

    微软俱乐部科技文化月seedcoder2014编程大赛已经初审完成. 评审小组选出最棒的作品进入决赛(现场答辩+陈述环节,由评委现场打分).终于排名由"初赛分数+现场答辩分"决定. ...

  9. 013 IPv6

    Router>en Router#config t Enter configuration commands, one per line.  End with CNTL/Z. Router(co ...

  10. onenstack 简介

    一.云计算的前世今生 所有的新事物都不是突然冒出来的,都有前世和今生.云计算也是IT技术不断发展的产物. 要理解云计算,需要对IT系统架构的发展过程有所认识. 请看下 IT系统架构的发展到目前为止大致 ...