From 7629527ee987b3d2d081a7423f9a2873cd48d2ee Mon Sep 17 00:00:00 2001
From: LemonNoCry <773596523@qq.com>
Date: Thu, 1 Jun 2023 17:54:54 +0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=F0=9F=8E=A8=20=E7=BC=93=E5=AD=98?=
=?UTF-8?q?=E7=9A=84=E5=AE=8C=E5=96=84=E4=BC=98=E5=8C=96=201.=E7=BB=9F?=
=?UTF-8?q?=E4=B8=80=E5=B0=81=E8=A3=85=E5=9F=BA=E4=BA=8E=E5=BE=AE=E8=BD=AF?=
=?UTF-8?q?=E5=88=86=E5=B8=83=E5=BC=8F=E7=BC=93=E5=AD=98=E6=8E=A5=E5=8F=A3?=
=?UTF-8?q?IDistributedCache=E4=BD=BF=E7=94=A8=202.IDistributedCache?=
=?UTF-8?q?=E5=8F=AA=E9=80=82=E5=90=88=E6=99=AE=E9=80=9A=E7=9A=84=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E4=BD=BF=E7=94=A8,=E5=A6=82=E6=9E=9C=E8=A6=81?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8redis=E9=98=9F=E5=88=97=E3=80=81=E8=AE=A2?=
=?UTF-8?q?=E9=98=85redis=E6=B6=88=E6=81=AF=E7=AD=89,=E5=B0=B1=E8=A6=81?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8redis=E5=8E=9F=E7=94=9F=E5=BA=93=203.?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BC=93=E5=AD=98=E7=AE=A1=E7=90=86=E6=8E=A5?=
=?UTF-8?q?=E5=8F=A3[Systems/CacheManageController]=204.=E7=9B=AE=E5=89=8D?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E5=86=85=E5=AD=98=E3=80=81redis=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E5=AE=9E=E7=8E=B0,=E7=90=86=E8=AE=BA=E5=8F=AF?=
=?UTF-8?q?=E9=9A=8F=E6=84=8F=E6=89=A9=E5=B1=95=E7=94=9A=E8=87=B3=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=AE=9E=E7=8E=B0=205.=E9=BB=98=E8=AE=A4?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=86=85=E5=AD=98=E7=BC=93=E5=AD=98,?=
=?UTF-8?q?=E5=8F=AF=E5=9C=A8appsetting.json=E4=B8=AD=E9=85=8D=E7=BD=AERed?=
=?UTF-8?q?is?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
切换到IDistributedCache好处如下
默认session使用IDistributedCache进行存储,如果你搭配使用IDistributedCache+外部缓存(如Redis),可实现应用程序重启session不丢失
更直观就是,调试的时候登录swagger后即使重启调试也无需在登陆
---
Blog.Core.Api/Blog.Core.Api.csproj | 1 -
Blog.Core.Api/Blog.Core.xml | 35 ++
.../Systems/CacheManageController.cs | 81 ++++
Blog.Core.Api/Program.cs | 3 +-
Blog.Core.Api/Startup.cs | 5 +-
Blog.Core.Api/appsettings.json | 4 +-
Blog.Core.Common/Blog.Core.Common.csproj | 1 -
Blog.Core.Common/Caches/Caching.cs | 328 ++++++++++++++++
Blog.Core.Common/Caches/ICaching.cs | 53 +++
.../Caches/SqlSugarCacheService.cs | 62 +++
Blog.Core.Common/Const/CacheConst.cs | 87 +++++
Blog.Core.Common/DB/BaseDBConfig.cs | 1 -
.../Extensions/ExpressionExtensions.cs | 354 +++++++++---------
.../MemoryCache/ICachingProvider.cs | 12 -
Blog.Core.Common/MemoryCache/MemoryCaching.cs | 30 --
Blog.Core.Common/Option/RedisOptions.cs | 24 ++
Blog.Core.Extensions/AOP/BlogCacheAOP.cs | 8 +-
.../Blog.Core.Extensions.csproj | 1 +
.../Redis/IRedisBasketRepository.cs | 1 +
.../Redis/RedisBasketRepository.cs | 1 +
.../ServiceExtensions/CacheSetup.cs | 45 +++
.../ServiceExtensions/HttpRuntimeCache.cs | 67 ----
.../ServiceExtensions/MemoryCacheSetup.cs | 27 --
.../ServiceExtensions/RedisCacheSetup.cs | 34 --
.../ServiceExtensions/SqlsugarSetup.cs | 12 +-
.../Helper/CustomJwtTokenAuthMiddleware.cs | 1 +
.../Utility/SerilogRequestUtility.cs | 104 ++---
27 files changed, 964 insertions(+), 418 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/Systems/CacheManageController.cs
create mode 100644 Blog.Core.Common/Caches/Caching.cs
create mode 100644 Blog.Core.Common/Caches/ICaching.cs
create mode 100644 Blog.Core.Common/Caches/SqlSugarCacheService.cs
create mode 100644 Blog.Core.Common/Const/CacheConst.cs
delete mode 100644 Blog.Core.Common/MemoryCache/ICachingProvider.cs
delete mode 100644 Blog.Core.Common/MemoryCache/MemoryCaching.cs
create mode 100644 Blog.Core.Common/Option/RedisOptions.cs
create mode 100644 Blog.Core.Extensions/ServiceExtensions/CacheSetup.cs
delete mode 100644 Blog.Core.Extensions/ServiceExtensions/HttpRuntimeCache.cs
delete mode 100644 Blog.Core.Extensions/ServiceExtensions/MemoryCacheSetup.cs
delete mode 100644 Blog.Core.Extensions/ServiceExtensions/RedisCacheSetup.cs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 2f8c41e..f3f9bef 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -106,7 +106,6 @@
-
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 672ea21..69d3f9b 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1299,6 +1299,41 @@
+
+
+ 缓存管理
+
+
+
+
+ 获取全部缓存
+
+
+
+
+
+ 获取缓存
+
+
+
+
+
+ 新增
+
+
+
+
+
+ 删除全部缓存
+
+
+
+
+
+ 删除缓存
+
+
+
数据库管理
diff --git a/Blog.Core.Api/Controllers/Systems/CacheManageController.cs b/Blog.Core.Api/Controllers/Systems/CacheManageController.cs
new file mode 100644
index 0000000..4f400e8
--- /dev/null
+++ b/Blog.Core.Api/Controllers/Systems/CacheManageController.cs
@@ -0,0 +1,81 @@
+using Blog.Core.Common.Caches;
+using Blog.Core.Controllers;
+using Blog.Core.Model;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Api.Controllers.Systems;
+
+///
+/// 缓存管理
+///
+[Route("api/Systems/[controller]")]
+[ApiController]
+[Authorize(Permissions.Name)]
+public class CacheManageController : BaseApiController
+{
+ private readonly ICaching _caching;
+
+ public CacheManageController(ICaching caching)
+ {
+ _caching = caching;
+ }
+
+ ///
+ /// 获取全部缓存
+ ///
+ ///
+ [HttpGet]
+ public async Task>> Get()
+ {
+ return Success(await _caching.GetAllCacheKeysAsync());
+ }
+
+ ///
+ /// 获取缓存
+ ///
+ ///
+ [HttpGet("{key}")]
+ public async Task> Get(string key)
+ {
+ return Success(await _caching.GetStringAsync(key));
+ }
+
+ ///
+ /// 新增
+ ///
+ ///
+ [HttpPost]
+ public async Task Post([FromQuery] string key, [FromQuery] string value, [FromQuery] int? expire)
+ {
+ if (expire.HasValue)
+ await _caching.SetStringAsync(key, value, TimeSpan.FromMilliseconds(expire.Value));
+ else
+ await _caching.SetStringAsync(key, value);
+
+ return Success();
+ }
+
+ ///
+ /// 删除全部缓存
+ ///
+ ///
+ [HttpDelete]
+ public async Task Delete()
+ {
+ await _caching.RemoveAllAsync();
+ return Success();
+ }
+
+ ///
+ /// 删除缓存
+ ///
+ ///
+ [Route("{key}")]
+ [HttpDelete]
+ public async Task Delete(string key)
+ {
+ await _caching.RemoveAsync(key);
+ return Success();
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index b4929cc..4311c97 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -57,8 +57,7 @@ RoutePrefix.Name = AppSettings.app(new string[] { "AppSettings", "SvcName" }).Ob
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
-builder.Services.AddMemoryCacheSetup();
-builder.Services.AddRedisCacheSetup();
+builder.Services.AddCacheSetup();
builder.Services.AddSqlsugarSetup();
builder.Services.AddDbSetup();
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index 64e5ee7..2911625 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -8,6 +8,7 @@ using Blog.Core.Common.LogHelper;
using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
using Blog.Core.Extensions.Middlewares;
+using Blog.Core.Extensions.ServiceExtensions;
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
@@ -49,9 +50,7 @@ namespace Blog.Core
// 确保从认证中心返回的ClaimType不被更改,不使用Map映射
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- services.AddMemoryCacheSetup();
- services.AddRedisCacheSetup();
-
+ services.AddCacheSetup();
services.AddSqlsugarSetup();
services.AddDbSetup();
services.AddAutoMapperSetup();
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index cef87be..d220a03 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -18,7 +18,9 @@
},
"AllowedHosts": "*",
"Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
+ "Enable": true,
+ "ConnectionString": "127.0.0.1:6379",
+ "InstanceName": "" //前缀
},
"RabbitMQ": {
"Enabled": false,
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index aeba847..5f24987 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -51,7 +51,6 @@
-
diff --git a/Blog.Core.Common/Caches/Caching.cs b/Blog.Core.Common/Caches/Caching.cs
new file mode 100644
index 0000000..e7b4ab0
--- /dev/null
+++ b/Blog.Core.Common/Caches/Caching.cs
@@ -0,0 +1,328 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Blog.Core.Common.Const;
+using Microsoft.Extensions.Caching.Distributed;
+using Newtonsoft.Json;
+
+namespace Blog.Core.Common.Caches;
+
+public class Caching : ICaching
+{
+ private readonly IDistributedCache _cache;
+
+ public Caching(IDistributedCache cache)
+ {
+ _cache = cache;
+ }
+
+ private byte[] GetBytes(T source)
+ {
+ return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(source));
+ }
+
+ public IDistributedCache Cache => _cache;
+
+ public void AddCacheKey(string cacheKey)
+ {
+ var res = _cache.GetString(CacheConst.KeyAll);
+ var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JsonConvert.DeserializeObject>(res);
+ if (!allkeys.Any(m => m == cacheKey))
+ {
+ allkeys.Add(cacheKey);
+ _cache.SetString(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+ }
+
+ ///
+ /// 增加缓存Key
+ ///
+ ///
+ ///
+ public async Task AddCacheKeyAsync(string cacheKey)
+ {
+ var res = await _cache.GetStringAsync(CacheConst.KeyAll);
+ var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JsonConvert.DeserializeObject>(res);
+ if (!allkeys.Any(m => m == cacheKey))
+ {
+ allkeys.Add(cacheKey);
+ await _cache.SetStringAsync(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+ }
+
+ public void DelByPattern(string key)
+ {
+ var allkeys = GetAllCacheKeys();
+ if (allkeys == null) return;
+
+ var delAllkeys = allkeys.Where(u => u.Contains(key)).ToList();
+ delAllkeys.ForEach(u => { _cache.Remove(u); });
+
+ // 更新所有缓存键
+ allkeys = allkeys.Where(u => !u.Contains(key)).ToList();
+ _cache.SetString(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+
+ ///
+ /// 删除某特征关键字缓存
+ ///
+ ///
+ ///
+ public async Task DelByPatternAsync(string key)
+ {
+ var allkeys = await GetAllCacheKeysAsync();
+ if (allkeys == null) return;
+
+ var delAllkeys = allkeys.Where(u => u.Contains(key)).ToList();
+ delAllkeys.ForEach(u => { _cache.Remove(u); });
+
+ // 更新所有缓存键
+ allkeys = allkeys.Where(u => !u.Contains(key)).ToList();
+ await _cache.SetStringAsync(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+
+ public void DelCacheKey(string cacheKey)
+ {
+ var res = _cache.GetString(CacheConst.KeyAll);
+ var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JsonConvert.DeserializeObject>(res);
+ if (allkeys.Any(m => m == cacheKey))
+ {
+ allkeys.Remove(cacheKey);
+ _cache.SetString(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+ }
+
+ ///
+ /// 删除缓存
+ ///
+ ///
+ ///
+ public async Task DelCacheKeyAsync(string cacheKey)
+ {
+ var res = await _cache.GetStringAsync(CacheConst.KeyAll);
+ var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JsonConvert.DeserializeObject>(res);
+ if (allkeys.Any(m => m == cacheKey))
+ {
+ allkeys.Remove(cacheKey);
+ await _cache.SetStringAsync(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+ }
+
+ public bool Exists(string cacheKey)
+ {
+ var res = _cache.Get(cacheKey);
+ return res != null;
+ }
+
+ ///
+ /// 检查给定 key 是否存在
+ ///
+ /// 键
+ ///
+ public async Task ExistsAsync(string cacheKey)
+ {
+ var res = await _cache.GetAsync(cacheKey);
+ return res != null;
+ }
+
+ public List GetAllCacheKeys()
+ {
+ var res = _cache.GetString(CacheConst.KeyAll);
+ return string.IsNullOrWhiteSpace(res) ? null : JsonConvert.DeserializeObject>(res);
+ }
+
+ ///
+ /// 获取所有缓存列表
+ ///
+ ///
+ public async Task> GetAllCacheKeysAsync()
+ {
+ var res = await _cache.GetStringAsync(CacheConst.KeyAll);
+ return string.IsNullOrWhiteSpace(res) ? null : JsonConvert.DeserializeObject>(res);
+ }
+
+ public T Get(string cacheKey)
+ {
+ var res = _cache.Get(cacheKey);
+ return res == null ? default : JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ }
+
+ ///
+ /// 获取缓存
+ ///
+ ///
+ ///
+ ///
+ public async Task GetAsync(string cacheKey)
+ {
+ var res = await _cache.GetAsync(cacheKey);
+ return res == null ? default : JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res));
+ }
+
+ public string GetString(string cacheKey)
+ {
+ return _cache.GetString(cacheKey);
+ }
+
+ ///
+ /// 获取缓存
+ ///
+ ///
+ ///
+ public async Task GetStringAsync(string cacheKey)
+ {
+ return await _cache.GetStringAsync(cacheKey);
+ }
+
+ public void Remove(string key)
+ {
+ _cache.Remove(key);
+ DelCacheKey(key);
+ }
+
+ ///
+ /// 删除缓存
+ ///
+ ///
+ ///
+ public async Task RemoveAsync(string key)
+ {
+ await _cache.RemoveAsync(key);
+ await DelCacheKeyAsync(key);
+ }
+
+ public void RemoveAll()
+ {
+ var catches = GetAllCacheKeys();
+ foreach (var @catch in catches) Remove(@catch);
+
+ catches.Clear();
+ _cache.SetString(CacheConst.KeyAll, JsonConvert.SerializeObject(catches));
+ }
+
+ public async Task RemoveAllAsync()
+ {
+ var catches = await GetAllCacheKeysAsync();
+ foreach (var @catch in catches) await RemoveAsync(@catch);
+
+ catches.Clear();
+ await _cache.SetStringAsync(CacheConst.KeyAll, JsonConvert.SerializeObject(catches));
+ }
+
+
+ public void Set(string cacheKey, T value, TimeSpan? expire = null)
+ {
+ _cache.Set(cacheKey, GetBytes(value), expire == null ? new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(6)} : new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = expire});
+
+ AddCacheKey(cacheKey);
+ }
+
+ ///
+ /// 增加对象缓存
+ ///
+ ///
+ ///
+ ///
+ public async Task SetAsync(string cacheKey, T value)
+ {
+ await _cache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(6)});
+
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+ ///
+ /// 增加对象缓存,并设置过期时间
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task SetAsync(string cacheKey, T value, TimeSpan expire)
+ {
+ await _cache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = expire});
+
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+ public void SetPermanent(string cacheKey, T value)
+ {
+ _cache.Set(cacheKey, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
+ AddCacheKey(cacheKey);
+ }
+ public async Task SetPermanentAsync(string cacheKey, T value)
+ {
+ await _cache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+ public void SetString(string cacheKey, string value, TimeSpan? expire = null)
+ {
+ if (expire == null)
+ _cache.SetString(cacheKey, value, new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(6)});
+ else
+ _cache.SetString(cacheKey, value, new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = expire});
+
+ AddCacheKey(cacheKey);
+ }
+
+ ///
+ /// 增加字符串缓存
+ ///
+ ///
+ ///
+ ///
+ public async Task SetStringAsync(string cacheKey, string value)
+ {
+ await _cache.SetStringAsync(cacheKey, value, new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(6)});
+
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+ ///
+ /// 增加字符串缓存,并设置过期时间
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task SetStringAsync(string cacheKey, string value, TimeSpan expire)
+ {
+ await _cache.SetStringAsync(cacheKey, value, new DistributedCacheEntryOptions() {AbsoluteExpirationRelativeToNow = expire});
+
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+
+ ///
+ /// 缓存最大角色数据范围
+ ///
+ ///
+ ///
+ ///
+ public async Task SetMaxDataScopeType(long userId, int dataScopeType)
+ {
+ var cacheKey = CacheConst.KeyMaxDataScopeType + userId;
+ await SetStringAsync(cacheKey, dataScopeType.ToString());
+
+ await AddCacheKeyAsync(cacheKey);
+ }
+
+ ///
+ /// 根据父键清空
+ ///
+ ///
+ ///
+ public async Task DelByParentKeyAsync(string key)
+ {
+ var allkeys = await GetAllCacheKeysAsync();
+ if (allkeys == null) return;
+
+ var delAllkeys = allkeys.Where(u => u.StartsWith(key)).ToList();
+ delAllkeys.ForEach(Remove);
+ // 更新所有缓存键
+ allkeys = allkeys.Where(u => !u.StartsWith(key)).ToList();
+ await SetStringAsync(CacheConst.KeyAll, JsonConvert.SerializeObject(allkeys));
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Caches/ICaching.cs b/Blog.Core.Common/Caches/ICaching.cs
new file mode 100644
index 0000000..f856aeb
--- /dev/null
+++ b/Blog.Core.Common/Caches/ICaching.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Caching.Distributed;
+
+namespace Blog.Core.Common.Caches;
+
+///
+/// 缓存抽象接口,基于IDistributedCache封装
+///
+public interface ICaching
+{
+ public IDistributedCache Cache { get; }
+ void AddCacheKey(string cacheKey);
+ Task AddCacheKeyAsync(string cacheKey);
+
+ void DelByPattern(string key);
+ Task DelByPatternAsync(string key);
+
+ void DelCacheKey(string cacheKey);
+ Task DelCacheKeyAsync(string cacheKey);
+
+ bool Exists(string cacheKey);
+ Task ExistsAsync(string cacheKey);
+
+ List GetAllCacheKeys();
+ Task> GetAllCacheKeysAsync();
+
+ T Get(string cacheKey);
+ Task GetAsync(string cacheKey);
+
+ string GetString(string cacheKey);
+ Task GetStringAsync(string cacheKey);
+
+ void Remove(string key);
+ Task RemoveAsync(string key);
+
+ void RemoveAll();
+ Task RemoveAllAsync();
+
+ void Set(string cacheKey, T value, TimeSpan? expire = null);
+ Task SetAsync(string cacheKey, T value);
+ Task SetAsync(string cacheKey, T value, TimeSpan expire);
+
+ void SetPermanent(string cacheKey, T value);
+ Task SetPermanentAsync(string cacheKey, T value);
+
+ void SetString(string cacheKey, string value, TimeSpan? expire = null);
+ Task SetStringAsync(string cacheKey, string value);
+ Task SetStringAsync(string cacheKey, string value, TimeSpan expire);
+
+ Task DelByParentKeyAsync(string key);
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Caches/SqlSugarCacheService.cs b/Blog.Core.Common/Caches/SqlSugarCacheService.cs
new file mode 100644
index 0000000..c26a164
--- /dev/null
+++ b/Blog.Core.Common/Caches/SqlSugarCacheService.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using SqlSugar;
+
+namespace Blog.Core.Common.Caches;
+
+///
+/// 实现SqlSugar的ICacheService接口
+///
+public class SqlSugarCacheService : ICacheService
+{
+ private readonly Lazy _caching = new(() => App.GetService(false));
+ private ICaching Caching => _caching.Value;
+
+ public void Add(string key, V value)
+ {
+ Caching.Set(key, value);
+ }
+
+ public void Add(string key, V value, int cacheDurationInSeconds)
+ {
+ Caching.Set(key, value, TimeSpan.FromSeconds(cacheDurationInSeconds));
+ }
+
+ public bool ContainsKey(string key)
+ {
+ return Caching.Exists(key);
+ }
+
+ public V Get(string key)
+ {
+ return Caching.Get(key);
+ }
+
+ public IEnumerable GetAllKey()
+ {
+ return Caching.GetAllCacheKeys();
+ }
+
+ public V GetOrCreate(string cacheKey, Func create, int cacheDurationInSeconds = int.MaxValue)
+ {
+ if (!ContainsKey(cacheKey))
+ {
+ var value = create();
+ Caching.Set(cacheKey, value, TimeSpan.FromSeconds(cacheDurationInSeconds));
+ return value;
+ }
+
+ return Caching.Get(cacheKey);
+ }
+
+ public void Remove(string key)
+ {
+ Caching.Remove(key);
+ }
+
+ public bool RemoveAll()
+ {
+ Caching.RemoveAll();
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Const/CacheConst.cs b/Blog.Core.Common/Const/CacheConst.cs
new file mode 100644
index 0000000..92f0e63
--- /dev/null
+++ b/Blog.Core.Common/Const/CacheConst.cs
@@ -0,0 +1,87 @@
+namespace Blog.Core.Common.Const;
+
+///
+/// 缓存相关常量
+///
+public class CacheConst
+{
+ ///
+ /// 用户缓存
+ ///
+ public const string KeyUser = "user:";
+
+ ///
+ /// 用户部门缓存
+ ///
+ public const string KeyUserDepart = "userDepart:";
+
+ ///
+ /// 菜单缓存
+ ///
+ public const string KeyMenu = "menu:";
+
+ ///
+ /// 菜单
+ ///
+ public const string KeyPermissions = "permissions";
+
+ ///
+ /// 权限缓存
+ ///
+ public const string KeyPermission = "permission:";
+
+ ///
+ /// 接口路由
+ ///
+ public const string KeyModules = "modules";
+
+ ///
+ /// 系统配置
+ ///
+ public const string KeySystemConfig = "sysConfig";
+
+ ///
+ /// 查询过滤器缓存
+ ///
+ public const string KeyQueryFilter = "queryFilter:";
+
+ ///
+ /// 机构Id集合缓存
+ ///
+ public const string KeyOrgIdList = "org:";
+
+ ///
+ /// 最大角色数据范围缓存
+ ///
+ public const string KeyMaxDataScopeType = "maxDataScopeType:";
+
+ ///
+ /// 验证码缓存
+ ///
+ public const string KeyVerCode = "verCode:";
+
+ ///
+ /// 所有缓存关键字集合
+ ///
+ public const string KeyAll = "keys";
+
+ ///
+ /// 定时任务缓存
+ ///
+ public const string KeyTimer = "timer:";
+
+ ///
+ /// 在线用户缓存
+ ///
+ public const string KeyOnlineUser = "onlineuser:";
+
+ ///
+ /// 常量下拉框
+ ///
+ public const string KeyConstSelector = "selector:";
+
+ ///
+ /// swagger登录缓存
+ ///
+ public const string SwaggerLogin = "swaggerLogin:";
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/BaseDBConfig.cs b/Blog.Core.Common/DB/BaseDBConfig.cs
index 495414f..b715376 100644
--- a/Blog.Core.Common/DB/BaseDBConfig.cs
+++ b/Blog.Core.Common/DB/BaseDBConfig.cs
@@ -3,7 +3,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using SqlSugar;
namespace Blog.Core.Common.DB
{
diff --git a/Blog.Core.Common/Extensions/ExpressionExtensions.cs b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
index 4058b95..6591923 100644
--- a/Blog.Core.Common/Extensions/ExpressionExtensions.cs
+++ b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
@@ -4,211 +4,213 @@ using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
+using Blog.Core.Common.Caches;
namespace Blog.Core.Common.Helper
{
- ///
- /// Linq扩展
- ///
- public static class ExpressionExtensions
- {
- #region HttpContext
+ ///
+ /// Linq扩展
+ ///
+ public static class ExpressionExtensions
+ {
+ #region HttpContext
- ///
- /// 返回请求上下文
- ///
- ///
- ///
- ///
- ///
- ///
- public static async Task Cof_SendResponse(this HttpContext context, System.Net.HttpStatusCode code, string message, string ContentType = "text/html;charset=utf-8")
- {
- context.Response.StatusCode = (int)code;
- context.Response.ContentType = ContentType;
- await context.Response.WriteAsync(message);
- }
+ ///
+ /// 返回请求上下文
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task Cof_SendResponse(this HttpContext context, System.Net.HttpStatusCode code, string message,
+ string ContentType = "text/html;charset=utf-8")
+ {
+ context.Response.StatusCode = (int) code;
+ context.Response.ContentType = ContentType;
+ await context.Response.WriteAsync(message);
+ }
- #endregion
+ #endregion
- #region ICaching
+ #region ICaching
- ///
- /// 从缓存里取数据,如果不存在则执行查询方法,
- ///
- /// 类型
- /// ICaching
- /// 键值
- /// 查询方法
- /// 有效期 单位分钟/param>
- ///
- public static T Cof_GetICaching(this ICaching cache, string key, Func GetFun, int timeSpanMin) where T : class
- {
- var obj = cache.Get(key);
- obj = GetFun();
- if (obj == null)
- {
- obj = GetFun();
- cache.Set(key, obj, timeSpanMin);
- }
+ ///
+ /// 从缓存里取数据,如果不存在则执行查询方法,
+ ///
+ /// 类型
+ /// ICaching
+ /// 键值
+ /// 查询方法
+ /// 有效期 单位分钟/param>
+ ///
+ public static T Cof_GetICaching(this ICaching cache, string key, Func GetFun, int timeSpanMin) where T : class
+ {
+ var obj = cache.Get(key);
+ if (obj == null)
+ {
+ obj = GetFun();
+ cache.Set(key, obj, TimeSpan.FromMinutes(timeSpanMin));
+ }
- return obj as T;
- }
+ return obj;
+ }
- ///
- /// 异步从缓存里取数据,如果不存在则执行查询方法
- ///
- /// 类型
- /// ICaching
- /// 键值
- /// 查询方法
- /// 有效期 单位分钟/param>
- ///
- public static async Task Cof_AsyncGetICaching(this ICaching cache, string key, Func> GetFun, int timeSpanMin) where T : class
- {
- var obj = cache.Get(key);
- if (obj == null)
- {
- obj = await GetFun();
- cache.Set(key, obj, timeSpanMin);
- }
+ ///
+ /// 异步从缓存里取数据,如果不存在则执行查询方法
+ ///
+ /// 类型
+ /// ICaching
+ /// 键值
+ /// 查询方法
+ /// 有效期 单位分钟/param>
+ ///
+ public static async Task Cof_AsyncGetICaching(this ICaching cache, string key, Func> GetFun, int timeSpanMin) where T : class
+ {
+ var obj = await cache.GetAsync(key);
+ if (obj == null)
+ {
+ obj = await GetFun();
+ cache.Set(key, obj, TimeSpan.FromMinutes(timeSpanMin));
+ }
- return obj as T;
- }
+ return obj;
+ }
- #endregion
+ #endregion
- #region 常用扩展方法
+ #region 常用扩展方法
- public static bool Cof_CheckAvailable(this IEnumerable Tlist)
- {
- return Tlist != null && Tlist.Count() > 0;
- }
+ public static bool Cof_CheckAvailable(this IEnumerable Tlist)
+ {
+ return Tlist != null && Tlist.Count() > 0;
+ }
- ///
- /// 调用内部方法
- ///
- public static Expression Call(this Expression instance, string methodName, params Expression[] arguments)
- {
- if (instance.Type == typeof(string))
- return Expression.Call(instance, instance.Type.GetMethod(methodName, new Type[] { typeof(string) }), arguments); //修复string contains 出现的问题 Ambiguous match found.
- else
- return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments);
- }
+ ///
+ /// 调用内部方法
+ ///
+ public static Expression Call(this Expression instance, string methodName, params Expression[] arguments)
+ {
+ if (instance.Type == typeof(string))
+ return Expression.Call(instance, instance.Type.GetMethod(methodName, new Type[] {typeof(string)}),
+ arguments); //修复string contains 出现的问题 Ambiguous match found.
+ else
+ return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments);
+ }
- ///
- /// 获取内部成员
- ///
- public static Expression Property(this Expression expression, string propertyName)
- {
- // Todo:左边条件如果是dynamic,
- // 则Expression.Property无法获取子内容
- // 报错在这里,由于expression内的对象为Object,所以无法解析到
- // var x = (expression as IQueryable).ElementType;
- var exp = Expression.Property(expression, propertyName);
- if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- return Expression.Convert(exp, exp.Type.GetGenericArguments()[0]);
- }
+ ///
+ /// 获取内部成员
+ ///
+ public static Expression Property(this Expression expression, string propertyName)
+ {
+ // Todo:左边条件如果是dynamic,
+ // 则Expression.Property无法获取子内容
+ // 报错在这里,由于expression内的对象为Object,所以无法解析到
+ // var x = (expression as IQueryable).ElementType;
+ var exp = Expression.Property(expression, propertyName);
+ if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ return Expression.Convert(exp, exp.Type.GetGenericArguments()[0]);
+ }
- return exp;
- }
+ return exp;
+ }
- ///
- /// 转Lambda
- ///
- public static Expression ToLambda(this Expression body,
- params ParameterExpression[] parameters)
- {
- return Expression.Lambda(body, parameters);
- }
+ ///
+ /// 转Lambda
+ ///
+ public static Expression ToLambda(this Expression body,
+ params ParameterExpression[] parameters)
+ {
+ return Expression.Lambda(body, parameters);
+ }
- #endregion
+ #endregion
- #region 常用运算符 [ > , >= , == , < , <= , != , || , && ]
+ #region 常用运算符 [ > , >= , == , < , <= , != , || , && ]
- ///
- /// &&
- ///
- public static Expression AndAlso(this Expression left, Expression right)
- {
- return Expression.AndAlso(left, right);
- }
+ ///
+ /// &&
+ ///
+ public static Expression AndAlso(this Expression left, Expression right)
+ {
+ return Expression.AndAlso(left, right);
+ }
- ///
- /// ||
- ///
- public static Expression OrElse(this Expression left, Expression right)
- {
- return Expression.OrElse(left, right);
- }
+ ///
+ /// ||
+ ///
+ public static Expression OrElse(this Expression left, Expression right)
+ {
+ return Expression.OrElse(left, right);
+ }
- ///
- /// Contains
- ///
- public static Expression Contains(this Expression left, Expression right)
- {
- return left.Call("Contains", right);
- }
+ ///
+ /// Contains
+ ///
+ public static Expression Contains(this Expression left, Expression right)
+ {
+ return left.Call("Contains", right);
+ }
- public static Expression StartContains(this Expression left, Expression right)
- {
- return left.Call("StartsWith", right);
- }
+ public static Expression StartContains(this Expression left, Expression right)
+ {
+ return left.Call("StartsWith", right);
+ }
- public static Expression EndContains(this Expression left, Expression right)
- {
- return left.Call("EndsWith", right);
- }
+ public static Expression EndContains(this Expression left, Expression right)
+ {
+ return left.Call("EndsWith", right);
+ }
- ///
- /// >
- ///
- public static Expression GreaterThan(this Expression left, Expression right)
- {
- return Expression.GreaterThan(left, right);
- }
+ ///
+ /// >
+ ///
+ public static Expression GreaterThan(this Expression left, Expression right)
+ {
+ return Expression.GreaterThan(left, right);
+ }
- ///
- /// >=
- ///
- public static Expression GreaterThanOrEqual(this Expression left, Expression right)
- {
- return Expression.GreaterThanOrEqual(left, right);
- }
+ ///
+ /// >=
+ ///
+ public static Expression GreaterThanOrEqual(this Expression left, Expression right)
+ {
+ return Expression.GreaterThanOrEqual(left, right);
+ }
- ///
- /// <
- ///
- public static Expression LessThan(this Expression left, Expression right)
- {
- return Expression.LessThan(left, right);
- }
+ ///
+ /// <
+ ///
+ public static Expression LessThan(this Expression left, Expression right)
+ {
+ return Expression.LessThan(left, right);
+ }
- ///
- /// <=
- ///
- public static Expression LessThanOrEqual(this Expression left, Expression right)
- {
- return Expression.LessThanOrEqual(left, right);
- }
+ ///
+ /// <=
+ ///
+ public static Expression LessThanOrEqual(this Expression left, Expression right)
+ {
+ return Expression.LessThanOrEqual(left, right);
+ }
- ///
- /// ==
- ///
- public static Expression Equal(this Expression left, Expression right)
- {
- return Expression.Equal(left, right);
- }
+ ///
+ /// ==
+ ///
+ public static Expression Equal(this Expression left, Expression right)
+ {
+ return Expression.Equal(left, right);
+ }
- ///
- /// !=
- ///
- public static Expression NotEqual(this Expression left, Expression right)
- {
- return Expression.NotEqual(left, right);
- }
+ ///
+ /// !=
+ ///
+ public static Expression NotEqual(this Expression left, Expression right)
+ {
+ return Expression.NotEqual(left, right);
+ }
- #endregion
- }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Blog.Core.Common/MemoryCache/ICachingProvider.cs b/Blog.Core.Common/MemoryCache/ICachingProvider.cs
deleted file mode 100644
index e6a0652..0000000
--- a/Blog.Core.Common/MemoryCache/ICachingProvider.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Blog.Core.Common
-{
- ///
- /// 简单的缓存接口,只有查询和添加,以后会进行扩展
- ///
- public interface ICaching
- {
- object Get(string cacheKey);
-
- void Set(string cacheKey, object cacheValue, int timeSpan);
- }
-}
diff --git a/Blog.Core.Common/MemoryCache/MemoryCaching.cs b/Blog.Core.Common/MemoryCache/MemoryCaching.cs
deleted file mode 100644
index fc9a60c..0000000
--- a/Blog.Core.Common/MemoryCache/MemoryCaching.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using Microsoft.Extensions.Caching.Memory;
-using System;
-
-namespace Blog.Core.Common
-{
- ///
- /// 实例化缓存接口ICaching
- ///
- public class MemoryCaching : ICaching
- {
- //引用Microsoft.Extensions.Caching.Memory;这个和.net 还是不一样,没有了Httpruntime了
- private readonly IMemoryCache _cache;
- //还是通过构造函数的方法,获取
- public MemoryCaching(IMemoryCache cache)
- {
- _cache = cache;
- }
-
- public object Get(string cacheKey)
- {
- return _cache.Get(cacheKey);
- }
-
- public void Set(string cacheKey, object cacheValue,int timeSpan)
- {
- _cache.Set(cacheKey, cacheValue, TimeSpan.FromSeconds(timeSpan * 60));
- }
- }
-
-}
diff --git a/Blog.Core.Common/Option/RedisOptions.cs b/Blog.Core.Common/Option/RedisOptions.cs
new file mode 100644
index 0000000..2732659
--- /dev/null
+++ b/Blog.Core.Common/Option/RedisOptions.cs
@@ -0,0 +1,24 @@
+using Blog.Core.Common.Option.Core;
+
+namespace Blog.Core.Common.Option;
+
+///
+/// 缓存配置选项
+///
+public sealed class RedisOptions : IConfigurableOptions
+{
+ ///
+ /// 是否启用
+ ///
+ public bool Enable { get; set; }
+
+ ///
+ /// Redis连接
+ ///
+ public string ConnectionString { get; set; }
+
+ ///
+ /// 键值前缀
+ ///
+ public string InstanceName { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/AOP/BlogCacheAOP.cs b/Blog.Core.Extensions/AOP/BlogCacheAOP.cs
index a3a52f5..d872bab 100644
--- a/Blog.Core.Extensions/AOP/BlogCacheAOP.cs
+++ b/Blog.Core.Extensions/AOP/BlogCacheAOP.cs
@@ -1,6 +1,8 @@
-using Blog.Core.Common;
+using System;
+using Blog.Core.Common;
using Castle.DynamicProxy;
using System.Linq;
+using Blog.Core.Common.Caches;
namespace Blog.Core.AOP
{
@@ -28,7 +30,7 @@ namespace Blog.Core.AOP
//获取自定义缓存键
var cacheKey = CustomCacheKey(invocation);
//根据key获取相应的缓存值
- var cacheValue = _cache.Get(cacheKey);
+ var cacheValue = _cache.Get