Redis是項目中普遍使用到的緩存組件,在Abp中如何使用呢!
首先先大概的看下abp源碼結構:
從結構就能看出abp使用了StackExchange.Redis,展開包可看出其實它是引用的Microsoft.Extensions.Caching.StackExchangeRedis
還發現這里面還有UnitOfWork,還有待研究~~
系統中如何使用呢?
1、添加abp的包引用
可以通過cli命令添加:abp add-package Volo.Abp.Caching.StackExchangeRedis(注意要在使用緩存的項目中執行命令,在此為Application層,可自動向Module類添加DependsOn引用),
也可手動通過nuget包添加引用(添加引用后要在對應的Module類中手動添加DependsOn引用),效果如下:
1 namespace abcFlow.WorkFlowEngine 2 { 3 [DependsOn( 4 typeof(WorkFlowEngineDomainModule), 5 typeof(WorkFlowEngineApplicationContractsModule), 6 typeof(AbpDddApplicationModule), 7 typeof(AbpAutoMapperModule) 8 )] 9 [DependsOn(typeof(AbpCachingStackExchangeRedisModule))] 10 public class WorkFlowEngineApplicationModule : AbpModule 11 { 12 public override void ConfigureServices(ServiceConfigurationContext context) 13 { 14 context.Services.AddAutoMapperObjectMapper<WorkFlowEngineApplicationModule>(); 15 Configure<AbpAutoMapperOptions>(options => 16 { 17 options.AddMaps<WorkFlowEngineApplicationModule>(validate: true); 18 }); 19 20 21 Configure<AbpDistributedCacheOptions>(options => 22 { 23 options.KeyPrefix = "demo"; 24 options.HideErrors = false; 25 }); 26 } 27 } 28 }
代碼中也添加了對AbpDistributedCacheOptions的配置,分別對應緩存前綴以及是否要隱藏錯誤(默認為true,在此為實驗目的設為false);
2、設置redis連接屬性
abp同樣提供了appsettings.json文件配置以及在Module中通過ConfigureServices方法中配置,在此以appsettings.json為例:
1 "Redis": { 2 "IsEnabled": "true", 3 "Configuration": "127.0.0.1" 4 }
配置顯示聲明啟用Redis並設置IP地址,本機端口號默認、無密碼,該配置與StackExchangeRedis是一致的,可以進行驗證下,包含集群模式也可以進行驗證,問題不大。
以上就將Redis的配置設置好了,下面看下如何進行數據的讀寫:
3、Redis的數據讀寫
數據的讀寫放在Application層,調用方式如下:
1 using JetBrains.Annotations; 2 using System; 3 using System.Threading.Tasks; 4 using Volo.Abp; 5 using Volo.Abp.Caching; 6 7 namespace abcFlow.WorkFlowEngine.FlowDesign 8 { 9 public class WfSchemeAppService : WorkFlowEngineAppService, IWfSchemeAppService 10 { 11 private readonly IWfSchemeRepository _wfSchemeRepository; 12 private readonly IDistributedCache<WfSchemeDto> _distributedCache; 13 14 public WfSchemeAppService( 15 IWfSchemeRepository wfSchemeRepository, 16 IDistributedCache<WfSchemeDto> distributedCache) 17 { 18 this._wfSchemeRepository = wfSchemeRepository; 19 this._distributedCache = distributedCache; 20 } 21 22 public async Task<WfSchemeDto> FindAsync([NotNull] Guid id) 23 { 24 Check.NotNull(id, nameof(id)); 25 return await _distributedCache.GetOrAddAsync( 26 id.ToString(), 27 async () => await GetWfSchemeById(id), 28 () => new Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions 29 { 30 AbsoluteExpiration = DateTimeOffset.Now.AddHours(2) 31 }); 32 } 33 34 private async Task<WfSchemeDto> GetWfSchemeById(Guid id) 35 { 36 var obj = await _wfSchemeRepository.FindAsync(id); 37 return ObjectMapper.Map<WfScheme, WfSchemeDto>(obj); 38 } 39 } 40 }
- 首先進行注入IDistributedCache,在此指定了緩存的數據類型
- 通過方法_distributedCache.GetOrAddAsync來實現緩存數據的讀寫(無數據時先加載數據再插入緩存),還可進行過期時間設置(在此可將時間提出出來作為常量)
看下Redis中存儲的對象:
最后看下GetOrAddAsync的代碼:
1 /// <summary> 2 /// Gets or Adds a cache item with the given key. If no cache item is found for the given key then adds a cache item 3 /// provided by <paramref name="factory" /> delegate and returns the provided cache item. 4 /// </summary> 5 /// <param name="key">The key of cached item to be retrieved from the cache.</param> 6 /// <param name="factory">The factory delegate is used to provide the cache item when no cache item is found for the given <paramref name="key" />.</param> 7 /// <param name="optionsFactory">The cache options for the factory delegate.</param> 8 /// <param name="hideErrors">Indicates to throw or hide the exceptions for the distributed cache.</param> 9 /// <param name="considerUow">This will store the cache in the current unit of work until the end of the current unit of work does not really affect the cache.</param> 10 /// <param name="token">The <see cref="T:System.Threading.CancellationToken" /> for the task.</param> 11 /// <returns>The cache item.</returns> 12 public virtual async Task<TCacheItem> GetOrAddAsync( 13 TCacheKey key, 14 Func<Task<TCacheItem>> factory, 15 Func<DistributedCacheEntryOptions> optionsFactory = null, 16 bool? hideErrors = null, 17 bool considerUow = false, 18 CancellationToken token = default) 19 { 20 token = CancellationTokenProvider.FallbackToProvider(token); 21 var value = await GetAsync(key, hideErrors, considerUow, token); 22 if (value != null) 23 { 24 return value; 25 } 26 27 using (await SyncSemaphore.LockAsync(token)) 28 { 29 value = await GetAsync(key, hideErrors, considerUow, token); 30 if (value != null) 31 { 32 return value; 33 } 34 35 value = await factory(); 36 37 if (ShouldConsiderUow(considerUow)) 38 { 39 var uowCache = GetUnitOfWorkCache(); 40 if (uowCache.TryGetValue(key, out var item)) 41 { 42 item.SetValue(value); 43 } 44 else 45 { 46 uowCache.Add(key, new UnitOfWorkCacheItem<TCacheItem>(value)); 47 } 48 } 49 50 await SetAsync(key, value, optionsFactory?.Invoke(), hideErrors, considerUow, token); 51 } 52 53 return value; 54 }