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

目前博客系统已经数据库创建、以及依赖注入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 }

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

接下来就是准备实现页面布局,先做个简单的前台查看,后台分布的功能,然后在一步一步的完善,希望大家多多指点,多多支持,谢谢了。

10月10日补充说明:

全局错误处理机制需要在FilterConfig中配置,才能起作用。感谢园友1非烟的指正

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

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

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

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

    前言      从上篇30岁找份程序员的工作(伪程序员的独白),文章开始,我说过我要用我自学的技术,来搭建一个博客系统,也希望大家给点意见,另外我很感谢博客园的各位朋友们,对我那篇算是自我阶段总结文章 ...

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

    一.博客系统进度回顾以及页面设计 1.1页面设计说明 紧接前面基础基本完成了框架搭建,现在开始设计页面,前台页面设计我是模仿我博客园的风格来设计的,后台是常规的左右布局风格. 1.2前台页面风格 主页 ...

  4. 从零开始,搭建博客系统MVC5+EF6搭建框架(4)下,前后台布局实现、发布博客以及展示。

    一.博客系统进度回顾 目前已经完成了,前台展示,以及后台发布的功能,最近都在做这个,其实我在国庆的时候就可以弄完的,但是每天自己弄,突然最后国庆2天,连电脑都不想碰,所以就一直拖着,上一篇写了前端实现 ...

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

    一.测试仓储层.业务层是否能实现对数据库表的操作 1.创建IsysUserInfoRepository接口来继承IBaseRepository父接口 namespace Wchl.WMBlog.IRe ...

  6. Django快速搭建博客系统

    Django快速搭建博客系统 一.开发环境 Windows 7(64bit) python 3.6   https://www.python.org/ Django 2.0  https://www. ...

  7. day14搭建博客系统项目

    day14搭建博客系统项目 1.下载代码包 [root@web02 opt]# git clone https://gitee.com/lylinux/DjangoBlog.git 2.使用pid安装 ...

  8. 【干货】利用MVC5+EF6搭建博客系统(四)(上)前后台页面布局页面实现,介绍使用的UI框架以及JS组件

    一.博客系统进度回顾以及页面设计 1.1页面设计说明 紧接前面基础基本完成了框架搭建,现在开始设计页面,前台页面设计我是模仿我博客园的风格来设计的,后台是常规的左右布局风格. 1.2前台页面风格 主页 ...

  9. 【干货】利用MVC5+EF6搭建博客系统(四)(下)前后台布局实现、发布博客以及展示

    二.博客系统后台布局实现 2.1.这里所用的是MVC的布局页来实现的,后台主要分为三部分:导航.菜单.主要内容 代码实现: 这里把后台单独放在一个区域里面,所以我这里建立一个admin的区域 在布局页 ...

随机推荐

  1. C语言中的sizeof()

    sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着"辛苦我一个,幸福千万人"的伟大思想,我决定将其尽可能详细的总结一下. 但当我总结的时候才发现,这个 ...

  2. iOS开发系列--让你的应用“动”起来

    --iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...

  3. 关于Unicode,字符集,字符编码,每个程序员都应该知道的事

    关于Unicode,字符集,字符编码,每个程序员都应该知道的事 作者:Jack47 李笑来的文章如何判断一个人是否聪明?中提到: 必要.清晰.且准确的概念,是一切思考的基石.所谓思考,很大程度上,就是 ...

  4. EF:The provider did not return a ProviderManifest instance

    报告错误1:指定的存储区提供程序在配置中找不到,或者无效. 报告错误2:System.Data.ProviderIncompatibleException: The provider did not ...

  5. 特邀美国EMC实战专家Mark来华授课

    “轻松搞定EMC-PCB和系统设计”课程介绍 本次课程特邀美国EMC领域权威专家Mark Montrose主讲,将涵盖满足产品电磁兼容性和信号完整性的基本原理.课程涉及多个领域,不仅仅针对PCB设计, ...

  6. JavaScript中的百变大咖~this

    原文链接:http://www.jeffjade.com/2015/08/03/2015-08-03-javascript-this/ JavaScript作为一种脚本语言身份的存在,因此被很多人认为 ...

  7. Windows内网渗透提权的几个实用命令

    1.获取操作系统信息 查看所有环境变量:set 识别系统体系结构:echo %PROCESSOR_ARCHITECTURE%  AMD64 识别操作系统名称及版本:systeminfo 查看某特定用户 ...

  8. ExtJs控件属性配置详细

    序言:    1.本文摘自网络,看控件命名像是4.0以前的版本,但控件属性配置仍然可以借鉴(不足之处,以后项目用到时再续完善). Ext.form.TimeField: 配置项:            ...

  9. jQuery 2.0.3 源码分析 样式操作

    根据API分类 CSS addClass() jQuery.cssHooks .hasClass() .removeClass() .toggleClass() .addClass() 对元素的样式操 ...

  10. SQL 里解析 XML 格式 字段 信息

    DECLARE @ItemMessage XML ),zje ),yfje ),bcje ),URL ),Remark )) SET @ItemMessage=N'<List> <i ...