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

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的控制器中使用缓存了。

修改MemberControllerTestController的构造函数:

 

 

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

// 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数据库中是否写入:

 

猜你喜欢

转载自www.cnblogs.com/yzqnet/p/10941575.html