AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法)
我的依赖包的主要版本以及Redis依赖如下
1:添加依赖
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="3.0.5" /> <ItemGroup> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" /> <PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.2.0" /> <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" /> <PackageReference Include="SqlSugar.IOC" Version="1.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.5.1" /> <PackageReference Include="Volo.Abp.AspNetCore" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="3.0.5" /> <PackageReference Include="Volo.Abp.Autofac" Version="3.0.5" /> <PackageReference Include="Volo.Abp.UI.Navigation" Version="3.0.5" /> //添加AbpVnext分布式redis缓存依赖包 <PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="3.0.5" /> </ItemGroup>
2:配置信息。默认在appsetting.json中配置即可,格式如下:
"Redis": { //Redis:Configuration "IsEnabled": "true",
//该服务将会吧数据存储在DB7的数据库中
"Configuration": "171.74.78.153:6379,password=9966686@,defaultdatabase=7"
}
3:在hosting模块中添加依赖
using Volo.Abp.Caching.StackExchangeRedis; namespace GDBS.MonitoringService.HttpApi.Hosting { [DependsOn( typeof(AbpAutofacModule), typeof(AbpAspNetCoreMvcModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule) , typeof(IdentityEntityFrameworkCoreModule) , typeof(MonitoringHttpApiModule) , typeof(MonitoringApplicationContractsModule) , typeof(SharedToolKitsModule) , typeof(JketSharedDomainModule) , typeof(AbpCachingStackExchangeRedisModule)//这里新增依赖模块 )] public class MonitoringHttpApiHostingModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { //测试时下面配置了还出不来,写入没有效果??这里就直接在配置文件中处理了。 //service.AddStackExchangeRedisCache(redisoptions => //{ // redisoptions.Configuration = configuration["Redis:Configuration"]; // redisoptions.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions // { // ConnectTimeout = 10 // //EndPoints=new StackExchange.Redis.EndPointCollection { // //} // }; //}); } }
4:Controller中的主要代码
namespace GDBS.ProvincialLevelService.HttpApi.Controller { /// <summary> /// ProvincialLevelService 省级服务 /// </summary> [Authorize] [Area("ProvincialLevelService")] [Route("api/ProvincialLevelService/[Controller]")] public class ProvincialLevelDataInfoController : AbpController { private readonly IBridgeTestDataService _service; private readonly IBridgeTestDataService _service; private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContext; private readonly IFilesInfoService _filesInfoservice; /// <summary> /// /// </summary> /// <param name="service"></param> /// <param name="httpClientFactory"></param> /// <param name="httpContext"></param> public ProvincialLevelDataInfoController(IBridgeTestDataService service, IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContext, IFilesInfoService filesInfoservice) { _service = service; _httpClientFactory = httpClientFactory; _httpContext = httpContext; _filesInfoservice = filesInfoservice; } /// <summary> /// TestRedisAddString /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <returns></returns> [HttpGet("TestRedisAddString")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString(string key, string redisvalue) { try { await _service.DoTestRedis(key, redisvalue); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } } } }
5:Application中,通常我们在这里来注入分布式接口
using Microsoft.Extensions.Caching.Distributed; namespace GDBS.ProvincialLevelService.Application.AppService { public class BridgeTestDataService : ApplicationService, IBridgeTestDataService { private readonly IDistributedCache _distributedCache; public BridgeTestDataService(IDistributedCache distributedCache) { _distributedCache = distributedCache; } public async Task<string> DoTestRedis(string key, string redisvalue) { try { await _distributedCache.SetStringAsync(key,redisvalue); return "ok"; } catch (Exception ex) { return $"错误{ex.Message}"; } } } }
6:为了方便直接在Controller中注入测试,通常我们需要在Application中注入使用
/// <summary> /// _cacheServer 通常我们在Application里面注册,这里只是测试 /// </summary> private readonly IDistributedCache _cacheServer; public ProvincialLevelDataInfoController(IDistributedCache cacheServer) { _cacheServer = cacheServer; } /// <summary> /// TestRedisAddString /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <param name="ab_hd">true绝对过期,false:滑动过期</param> /// <returns></returns> [HttpGet("TestRedisAddString2")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString2(string key, string redisvalue, bool ab_hd = true) { try { await _cacheServer.SetStringAsync(key, redisvalue, RedisPolicyHelper.GetRedisProcily(ab_hd,60)); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } }
7:分布式缓存的策略,使用绝对还是滑动过期,不使用策略就默认为长期保存,可以使用控制方法
using Microsoft.Extensions.Caching.Distributed; using System; namespace GDBS.Shared.ToolKits.Tool { public class RedisPolicyHelper { /// <summary> /// 使用绝对还是滑动过期,不使用策略就默认为长期保存 /// </summary> /// <param name="ab_hd">true绝对过期; false:滑动过期</param> /// <param name="Seconds">默认60秒过期</param> /// <returns></returns> public static DistributedCacheEntryOptions GetRedisProcily(bool ab_hd, int Seconds = 60) { var policy = new DistributedCacheEntryOptions(); Seconds = Seconds <= 1 ? 60 : Seconds; if (ab_hd) policy.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Seconds); else policy.SlidingExpiration = TimeSpan.FromSeconds(Seconds); return policy; } } }
8:自定义分布式缓存扩展方法
using System; using System.Threading.Tasks; using Newtonsoft.Json; using Microsoft.Extensions.Caching.Distributed; namespace GDBS.Shared.ToolKits { public static class RedisDistributeExtension { /// <summary> /// 自定义IDistribute 分布式扩展方法 jason 同步方法 /// </summary> /// <typeparam name="TModel"></typeparam> /// <param name="cache"></param> /// <param name="key"></param> /// <param name="handler"></param> /// <returns></returns> public static TModel RedisGetOrCreate<TModel>(this IDistributedCache cache, string key, Func<DistributedCacheEntryOptions, TModel> handler) { TModel t; string vs = cache.GetString(key); if (string.IsNullOrEmpty(vs)) { var options = new DistributedCacheEntryOptions(); t = handler.Invoke(options); cache.SetString(key, JsonConvert.SerializeObject(t), options); } else { t = JsonConvert.DeserializeObject<TModel>(vs); } return t; } /// <summary> /// 自定义IDistribute 分布式扩展方法 jason 异步方法 /// </summary> /// <typeparam name="TModel"></typeparam> /// <param name="cache"></param> /// <param name="key"></param> /// <param name="handler"></param> /// <returns></returns> public static async Task<TModel> RedisGetOrCreateAsync<TModel>(this IDistributedCache cache, string key, Func<DistributedCacheEntryOptions, Task<TModel>> handler) { TModel t; var vs = await cache.GetStringAsync(key); if (string.IsNullOrEmpty(vs)) { var options = new DistributedCacheEntryOptions(); t = await handler.Invoke(options); await cache.SetStringAsync(key, JsonConvert.SerializeObject(t), options); } else { t = JsonConvert.DeserializeObject<TModel>(vs); } return t; } } }
9:测试自定义扩展方法,Controller中的主要code。
/// <summary> /// 自定义分布式缓存的扩展方法,没有缓存就设置缓存,有就直接获取 /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <param name="ab_hd"></param> /// <returns></returns> [HttpGet("TestRedisAddString3")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString3(string key, string redisvalue, bool ab_hd = true) { try { await _cacheServer.RedisGetOrCreateAsync<string>(key, (options) => { options.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30); return Task.Factory.StartNew(() => { return $"_cacheServer.RedisGetOrCreateAsync获取或者设置缓存的方法:{redisvalue},时间:{DateTime.Now}"; }); }); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } }
10:调用自定义分布式扩展方法
11:测试结果部分主要截图:
12:公司一微服务系统中有多个服务,我们将不同的服务缓存数据将来存储在不同的Redis数据库中
好了今天就先到这里,下次有时间再更新,自学AbpVnext过程中难免会有一些bug或者不合理的地方,欢迎大家多多指教留言!!!