从零开始,搭建博客系统MVC5+EF6搭建框架(3),添加Nlog日志、缓存机制(MemoryCache、RedisCache)、创建控制器父类BaseController

一、回顾系统进度以及本章概要

目前博客系统已经数据库创建、以及依赖注入Autofac集成,接下来就是日志和缓存集成,这里日志用的是Nlog,其实还有其他的日志框架如log4,这些博客园都有很多介绍,这里就不说了,缓存机制用的是微软自带的MemoryCache和比较流行Redis,这里我也只是了解使用,没有做更升入的研究,以后好好学一下Redis,然后就是实现一个BaseController父类用来重写JsonResult方法为的是返回时间格式问题,默认json返回的时间格式是Date(84923838332223)转为常见的yyyy-MM-dd HH:mm:ss格式。

二、缓存机制实现

1、在公共程序集中创建连个文件加一个Cache用来存放缓存类,一个是Log是用来创建Nlog类,这里都使用接口来实现,以便可以以后可以多个实现。

2、首先创建一个ICacheManager接口类。

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3     public interface ICacheManager
  4     {
  5        /// <summary>
  6        /// 获取
  7        /// </summary>
  8        /// <typeparam name="TEntity"></typeparam>
  9        /// <param name="key"></param>
 10        /// <returns></returns>
 11         TEntity Get<TEntity>(string key);
 12         //设置
 13         void Set(string key, object value, TimeSpan cacheTime);
 14         //判断是否存在
 15         bool Contains(string key);
 16         //移除
 17         void Remove(string key);
 18         //清除
 19         void Clear();
 20
 21     }
 22 }

3、在实现微软缓存机制的时候需要引用System.Runtime.Caching.dll,创建一个MemoryCacheManager 类

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3      public  class MemoryCacheManager : ICacheManager
  4     {
  5         public void Clear()
  6         {
  7
  8             foreach (var item in MemoryCache.Default)
  9             {
 10                 this.Remove(item.Key);
 11             }
 12         }
 13
 14         public bool Contains(string key)
 15         {
 16             return MemoryCache.Default.Contains(key);
 17         }
 18
 19         public TEntity Get<TEntity>(string key)
 20         {
 21             return (TEntity)MemoryCache.Default.Get(key);
 22         }
 23
 24         public void Remove(string key)
 25         {
 26             MemoryCache.Default.Remove(key);
 27         }
 28
 29         public void Set(string key, object value, TimeSpan cacheTime)
 30         {
 31             MemoryCache.Default.Add(key, value, new CacheItemPolicy { SlidingExpiration = cacheTime });
 32         }
 33     }
 34 }

4、实现RedisCacheManager类,这里我们使用的免费的Redis客服端是StackExchange.Redis.可以在nuget中下载到。

RedisCacheManager类

  1 namespace Wchl.WMBlog.Common.Cache
  2 {
  3     public class RedisCacheManager : ICacheManager
  4     {
  5         private readonly string redisConnenctionString;
  6
  7         public volatile ConnectionMultiplexer redisConnection;
  8
  9         private readonly object redisConnectionLock = new object();
 10
 11         public RedisCacheManager()
 12         {
 13             //链接redis服务语句
 14             string redisConfiguration = ConfigurationManager.ConnectionStrings["redisCache"].ToString();
 15
 16             if (string.IsNullOrWhiteSpace(redisConfiguration))
 17             {
 18                 throw new ArgumentException("redis config is empty", nameof(redisConfiguration));
 19             }
 20             this.redisConnenctionString = redisConfiguration;
 21             this.redisConnection = GetRedisConnection();
 22         }
 23
 24         private ConnectionMultiplexer GetRedisConnection()
 25         {
 26             if (this.redisConnection != null && this.redisConnection.IsConnected)
 27             {
 28                 return this.redisConnection;
 29             }
 30             lock (redisConnectionLock)
 31             {
 32                 if (this.redisConnection != null)
 33                 {
 34                     //释放redis连接
 35                     this.redisConnection.Dispose();
 36                 }
 37                 this.redisConnection = ConnectionMultiplexer.Connect(redisConnenctionString);
 38             }
 39             return this.redisConnection;
 40         }
 41
 42         public void Clear()
 43         {
 44             foreach (var endPoint in this.GetRedisConnection().GetEndPoints())
 45             {
 46                 var server = this.GetRedisConnection().GetServer(endPoint);
 47                 foreach (var key in server.Keys())
 48                 {
 49                     redisConnection.GetDatabase().KeyDelete(key);
 50                 }
 51             }
 52         }
 53
 54         public bool Contains(string key)
 55         {
 56             return redisConnection.GetDatabase().KeyExists(key);
 57         }
 58
 59         public TEntity Get<TEntity>(string key)
 60         {
 61             var value = redisConnection.GetDatabase().StringGet(key);
 62             if (value.HasValue)
 63             {
 64                 return SerializeHelper.Deserialize<TEntity>(value);
 65             } else
 66             {
 67                 return default(TEntity);
 68             }
 69         }
 70
 71         public void Remove(string key)
 72         {
 73             redisConnection.GetDatabase().KeyDelete(key);
 74         }
 75
 76         public void Set(string key, object value, TimeSpan cacheTime)
 77         {
 78             if (value != null)
 79             {
 80                 redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime);
 81             }
 82         }
 83     }
 84 }

这里在存储数据的时候使用到了序列化和反序列化,用的序列化工具是Newtonsoft.Json,同样也可以在nuget中找到。

SerializeHelper序列化帮助类

  1 namespace Wchl.WMBlog.Common
  2 {
  3     public class SerializeHelper
  4     {
  5         /// <summary>
  6         /// 序列化
  7         /// </summary>
  8         /// <param name="item"></param>
  9         /// <returns></returns>
 10         public static byte[] Serialize(object item)
 11         {
 12             var jsonString = JsonConvert.SerializeObject(item);
 13
 14             return Encoding.UTF8.GetBytes(jsonString);
 15         }
 16         /// <summary>
 17         /// 反序列化
 18         /// </summary>
 19         /// <typeparam name="TEntity"></typeparam>
 20         /// <param name="value"></param>
 21         /// <returns></returns>
 22         public static TEntity Deserialize<TEntity>(byte[] value)
 23         {
 24             if (value == null)
 25             {
 26                 return default(TEntity);
 27             }
 28             var jsonString = Encoding.UTF8.GetString(value);
 29             return JsonConvert.DeserializeObject<TEntity>(jsonString);
 30         }
 31     }
 32 }

三、日志处理:Nlog日志框架

1、首先实现一个日子接口ILogger

  1 namespace Wchl.WMBlog.Common.Log
  2 {
  3     public interface ILogger
  4     {
  5         void Debug(string message);
  6         void Debug(string message, Exception exception);
  7         void Error(string message);
  8         void Error(string message, Exception exception);
  9         void Fatal(string message);
 10         void Fatal(string message, Exception exception);
 11         void Info(string message);
 12         void Info(string message, Exception exception);
 13         void Warn(string message);
 14         void Warn(string message, Exception exception);
 15     }
 16 }

2.在nuget中添加Nlog框架

nlog.config是日志框架的配置文件。

Nloglogger类

  1 namespace Wchl.WMBlog.Common.Log
  2 {
  3     public class NLogLogger : ILogger
  4     {
  5         private readonly Logger logger = LogManager.GetCurrentClassLogger();
  6         public void Debug(string message)
  7         {
  8             logger.Debug(message);
  9         }
 10
 11         public void Debug(string message, Exception exception)
 12         {
 13             logger.Debug(exception, message);
 14         }
 15
 16         public void Error(string message)
 17         {
 18             logger.Error(message);
 19         }
 20
 21         public void Error(string message, Exception exception)
 22         {
 23             logger.Error(exception, message);
 24         }
 25
 26         public void Fatal(string message)
 27         {
 28             logger.Fatal(message);
 29         }
 30
 31         public void Fatal(string message, Exception exception)
 32         {
 33             logger.Fatal(exception, message);
 34         }
 35
 36         public void Info(string message)
 37         {
 38             logger.Info(message);
 39         }
 40
 41         public void Info(string message, Exception exception)
 42         {
 43             logger.Info(exception, message);
 44         }
 45
 46         public void Warn(string message)
 47         {
 48             logger.Warn(message);
 49         }
 50
 51         public void Warn(string message, Exception exception)
 52         {
 53             logger.Warn(exception, message);
 54         }
 55     }
 56 }

3、配置日志文件NLog.config,这里是在webUI层应用这个文件,因为最终日志是在web下运行。

在targets的节点下面配置,这里是以文件的方式保存日子,你也可以使用这个配置一个直接把日子写到数据库中

  1 <target xsi:type ="File"
  2     name="file"
  3     header="------------------------------Start------------------------------"
  4     footer="------------------------------End------------------------------"
  5     fileName="${basedir}/App_Data/Logs/${shortdate}.log"
  6     layout="${longdate} - ${level:uppercase=true}:${message} ${callsite:fileName=true} ${exception:format=Type,Message,Method,StackTrace:maxInnerExceptionLevel=5:innerFormat=ShortType,Message,Method,StackTrace}"
  7     keepFileOpen="false"
  8     archiveFileName="${basedir}/App_Data/Logs/Backup_${shortdate}.{##}.log"
  9     archiveNumbering="Sequence"
 10     archiveEvery="Day"
 11     maxArchiveFiles="30">
 12
 13     </target>

在rules节点下配置 <logger name="*" minlevel="Error" writeTo="file" />表示什么级别的日志对应放在哪个配置里面。

这里日志保存在发布站点App_Data\Logs下

4、日志测试

4.1在测试之前首先设置一个全局错误机制文件ExpFilter继承HandleErrorAttribute,放在Webcore下面

这里需要添加System.Web.Mvc.dll程序集。

ExpFilter类:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class ExpFilter:HandleErrorAttribute
  4     {
  5         public override void OnException(ExceptionContext filterContext)
  6         {
  7             Exception exp = filterContext.Exception;
  8
  9             //获取ex的第一级内部异常
 10             Exception innerEx = exp.InnerException == null ? exp : exp.InnerException;
 11             //循环获取内部异常直到获取详细异常信息为止
 12             while (innerEx.InnerException!=null)
 13             {
 14                 innerEx = innerEx.InnerException;
 15             }
 16             NLogLogger nlog = new NLogLogger();
 17             if (filterContext.HttpContext.Request.IsAjaxRequest())
 18             {
 19
 20                 nlog.Error(innerEx.Message);
 21                 JsonConvert.SerializeObject(new { status = 1, msg ="请求发生错误,请联系管理员"});
 22             }
 23             else
 24             {
 25                 nlog.Error("Error",exp);
 26                 ViewResult vireResult = new ViewResult();
 27                 vireResult.ViewName = "/Views/Shared/Error.cshtml";
 28                 filterContext.Result = vireResult;
 29             }
 30
 31             //告诉MVC框架异常被处理
 32             filterContext.ExceptionHandled = true;
 33             base.OnException(filterContext);
 34         }
 35     }
 36 }
 37 

4.2这里对两种请求方式做处理一种是Ajax请求,一种是对链接地址做处理,另外还需要在webui下创建一个错误提醒页面。(/Views/Shared/Error.cshtml)

4.3在homecontroller控制器下写错误代码

4.4日志测试结果:这里直接开始执行(不调试)

然后在项目文件下查看web站点下的\App_Data\Logs查看日子文件

日志信息:错误信息,以及错误是那个文件多少行都有显示。

四、创建BaseController类

这里使用反序列化工具都是Newtonsoft.Json

BaseController类:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class BaseController: Controller
  4     {
  5         protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
  6         {
  7             return new JsonNetResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior };
  8         }
  9     }
 10 }

JsonNetResult类:

  1 namespace Wchl.WMBlog.WebCore
  2 {
  3     public class JsonNetResult:JsonResult
  4     {
  5         public override void ExecuteResult(ControllerContext context)
  6         {
  7             if (context==null)
  8             {
  9                 throw new ArgumentException(nameof(context));
 10             }
 11
 12             var response = context.HttpContext.Response;
 13
 14             response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
 15
 16             if (ContentEncoding != null)
 17             {
 18                 response.ContentEncoding = ContentEncoding;
 19             }
 20
 21             var jsonSerializerSetting = new JsonSerializerSettings();
 22             //首字母小写
 23             jsonSerializerSetting.ContractResolver = new CamelCasePropertyNamesContractResolver();
 24             //日期格式化
 25             jsonSerializerSetting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
 26             var json = JsonConvert.SerializeObject(Data, Formatting.None, jsonSerializerSetting);
 27
 28             response.Write(json);
 29
 30         }
 31     }
 32 }

直接在创建的控制器下集成:

时间: 2024-09-30 09:08:42

从零开始,搭建博客系统MVC5+EF6搭建框架(3),添加Nlog日志、缓存机制(MemoryCache、RedisCache)、创建控制器父类BaseController的相关文章

从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效果 2.2实现控制器在前台控制器中创建一个Blog的控制器,主要是展示博客分类以及详情页 Action详情页实现: 1 /// <summary> 2 /// 详情页 3 /// </summary> 4 /// <param name="id"><

从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑

前言      从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章的评论,在里面能看出有很多种声音,有支持的我的朋友给我加油打气,有分享自己工作经历的朋友,有提出忠肯意见的朋友,有对记事本写代码吐槽的朋友,也有希望让我换个行业的,觉得我可能不适合这个行业朋友,不管怎样,我都接受,都是大家同行的一些忠告,谢谢大家. 首先我要在这里感谢很多博客园里面的大牛,写了很多系

从零开始,搭建博客系统MVC5+EF6搭建框架(4)上,前后台页面布局页面实现,介绍使用的UI框架以及JS组件

一.博客系统进度回顾以及页面设计 1.1页面设计说明 紧接前面基础基本完成了框架搭建,现在开始设计页面,前台页面设计我是模仿我博客园的风格来设计的,后台是常规的左右布局风格. 1.2前台页面风格 主页面: 技术博客风格: 详情页风格: 详情页留言风格: 1.3后台风格: 表格风格: 博客发布风格: 以上看到的系统页面是目前系统完成的风格,以后页面设计都参考这些页面风格. 二.使用前端web框架以及插件说明 2.1选择前端web框架,我找了很多框架,以前学过自学过bootstrap觉得对于没有前端

从零开始,搭建博客系统MVC5+EF6搭建框架(2),测试添加数据、集成Autofac依赖注入

一.测试仓储层.业务层是否能实现对数据库表的操作 1.创建IsysUserInfoRepository接口来继承IBaseRepository父接口 1 namespace Wchl.WMBlog.IRepository 2 { 3 public partial interface IsysUserInfoRepository : IBaseRepository<sysUserInfo> 4 { 5 6 } 7 } 2.创建sysUserInfoRepository类继承BaseReposit

使用ASP.NET MVC+Entity Framework快速搭建博客系统

学习 ASP.NET MVC 也有一段时间了,打算弄个小程序练练手,做为学习过程中的记录和分享. 首先,得确定需求,木有需求的话,那还搞个毛线呀!嗯--大致思考了一下,终于得出如下需求: 1.能自定义分类 2.能发文章 OK!就这样,先从简单的开始(其实是复杂的不会做),后面有需要再添加(希望水平能达到).功能确定了,那么改确定要做成什么样子的了.先和度娘商量一下先-- 终于在我的淫威之下,度娘交出了一个比较简洁的,源网站在这里(表示感谢),被小弟阉割了之后效果如下图: 接下来就开始编码了么?嗯

使用EC2,VPC搭建博客系统详细步骤-1

1搭建 Amazon Virtual Private Cloud (Amazon VPC) 1.1搭建步骤: 1.1.1创建VPC 1.1.2子网 1.1.3路由表 1.1.4Internet网关 1.1.5DHCP选项集 1.1.6NAT网关 1.1.7ACL和安全组 2启动EC2实例,选择合适的AMI等等. 3在 Amazon Linux 2 上安装 LAMP Web 服务器 3.1安装步骤: 3.1.1远程(CRT使用*.pub) 3.1.2安装 Amazon Linux Extras和P

用php搭建博客系统-待续

PHP(全名:PHP: Hypertext Preprocessor)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域.PHP 独特的语法混合了C.Java.Perl以及PHP自创的语法.它可以比CGI或者Perl更快速地执行动态网页.用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多:PHP还可以执行编译后代码,编译可

django 搭建博客系统之创建博客的数据库模型

在我们之前已经创建好了虚拟环境,以及开始一个项目. 现在我们要添加一些功能性代码,django鼓励我们把自己编写的代码放入app中,每个app实现一个功能. 如今新建一个blog app 1,在虚拟环境下进入根目录,运行 python manage.py startapp blog.就建立了一个名为blog的应用,app. 2,在setting.py 中'告诉'django 存在这样的一个app. 好了 我们已经有了blog这个app,是要实现博客文章,博客的文章应该含有标题.正文.作者.发表时

MVC5+EF6+BootStrap3.3.5 博客系统之项目搭建(一)

环境:vs2013,sql2008R2 引用版本:MVC5,EF6,BootStrap3.3.5 在之前一直都是webfrom开发,虽然开发简单:但是有很多不足的地方.在之前开发都是webfrom+MVC三层架构+数据库等等 我在想将MVC5,EF6,BootStrap3.3.5,结合融于之前的开发模式之中. 1.新建解决方案 2.新建控制台应用程序 Blog.MVC.EF.BootStrap.DAL,主要用于EF数据处理 3.新建3个类库 Blog.MVC.EF.BootStrap.Model