在.ToolKits层中新建扩展方法Log4NetExtensions.cs。
//Log4NetExtensions.cs using log4net; using log4net.Config; using Microsoft.Extensions.Hosting; using System.IO; using System.Reflection; namespace Meowv.Blog.ToolKits.Extensions { public static class Log4NetExtensions { public static IHostBuilder UseLog4Net(this IHostBuilder hostBuilder) { var log4netRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); XmlConfigurator.Configure(log4netRepository, new FileInfo("log4net.config")); return hostBuilder; } } }配置log4net,然后我们直接返回IHostBuilder对象,便于在Main方法中链式调用。
//Program.cs using Meowv.Blog.ToolKits.Extensions; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using System.Threading.Tasks; namespace Meowv.Blog.HttpApi.Hosting { public class Program { public static async Task Main(string[] args) { await Host.CreateDefaultBuilder(args) .UseLog4Net() .ConfigureWebHostDefaults(builder => { builder.UseIISIntegration() .UseStartup<Startup>(); }).UseAutofac().Build().RunAsync(); } } }然后修改MeowvBlogExceptionFilter过滤器,代码如下:
//MeowvBlogExceptionFilter.cs using log4net; using Microsoft.AspNetCore.Mvc.Filters; namespace Meowv.Blog.HttpApi.Hosting.Filters { public class MeowvBlogExceptionFilter : IExceptionFilter { private readonly ILog _log; public MeowvBlogExceptionFilter() { _log = LogManager.GetLogger(typeof(MeowvBlogExceptionFilter)); } /// <summary> /// 异常处理 /// </summary> /// <param></param> /// <returns></returns> public void OnException(ExceptionContext context) { // 错误日志记录 _log.Error($"{context.HttpContext.Request.Path}|{context.Exception.Message}", context.Exception); } } }可以删掉之前添加的LoggerHelper.cs类,运行一下,同样可以达到预期效果。
本篇将集成Redis,使用Redis来缓存数据,使用方法参考的微软官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/distributed
关于Redis的介绍这里就不多说了,这里有一篇快速入门的文章:Redis快速入门及使用,对于不了解的同学可以看看。
直入主题,先在appsettings.json配置Redis的连接字符串。
//appsettings.json ... "Caching": { "RedisConnectionString": "127.0.0.1:6379,password=123456,ConnectTimeout=15000,SyncTimeout=5000" } ...对应的,在AppSettings.cs中读取。
//AppSettings.cs ... /// <summary> /// Caching /// </summary> public static class Caching { /// <summary> /// RedisConnectionString /// </summary> public static string RedisConnectionString => _config["Caching:RedisConnectionString"]; } ...在.Application.Caching层添加包Microsoft.Extensions.Caching.StackExchangeRedis,然后在模块类MeowvBlogApplicationCachingModule中添加配置缓存实现。
//MeowvBlogApplicationCachingModule.cs using Meowv.Blog.Domain; using Meowv.Blog.Domain.Configurations; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Caching; using Volo.Abp.Modularity; namespace Meowv.Blog.Application.Caching { [DependsOn( typeof(AbpCachingModule), typeof(MeowvBlogDomainModule) )] public class MeowvBlogApplicationCachingModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddStackExchangeRedisCache(options => { options.Configuration = AppSettings.Caching.RedisConnectionString; //options.InstanceName //options.ConfigurationOptions }); } } }options.Configuration是 Redis 的连接字符串。
options.InstanceNam是 Redis 实例名称,这里没填。
options.ConfigurationOptions是 Redis 的配置属性,如果配置了这个字,将优先于 Configuration 中的配置,同时它支持更多的选项。我这里也没填。
紧接着我们就可以直接使用了,直接将IDistributedCache接口依赖关系注入即可。
可以看到默认已经实现了这么多常用的接口,已经够我这个小项目用的了,同时在Microsoft.Extensions.Caching.Distributed.DistributedCacheExtensions中微软还给我们提供了很多扩展方法。
于是,我们我就想到写一个新的扩展方法,可以同时处理获取和添加缓存的操作,当缓存存在时,直接返回,不存在时,添加缓存。
新建MeowvBlogApplicationCachingExtensions.cs扩展方法,如下:
//MeowvBlogApplicationCachingExtensions.cs using Meowv.Blog.ToolKits.Extensions; using Microsoft.Extensions.Caching.Distributed; using System; using System.Threading.Tasks; namespace Meowv.Blog.Application.Caching { public static class MeowvBlogApplicationCachingExtensions { /// <summary> /// 获取或添加缓存 /// </summary> /// <typeparam></typeparam> /// <param></param> /// <param></param> /// <param></param> /// <param></param> /// <returns></returns> public static async Task<TCacheItem> GetOrAddAsync<TCacheItem>(this IDistributedCache cache, string key, Func<Task<TCacheItem>> factory, int minutes) { TCacheItem cacheItem; var result = await cache.GetStringAsync(key); if (string.IsNullOrEmpty(result)) { cacheItem = await factory.Invoke(); var options = new DistributedCacheEntryOptions(); if (minutes != CacheStrategy.NEVER) { options.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(minutes); } await cache.SetStringAsync(key, cacheItem.ToJson(), options); } else { cacheItem = result.FromJson<TCacheItem>(); } return cacheItem; } } }