错误日志之观察者模式
星期一
情景
早晨,项目组长来到小明身边,“有人反映咱们的项目有Bug” “什么Bug?” “不知道,你添加一个日志模块自己看记录去。” ”...“
分析
在MVC全局过滤器中自己添加有异常过滤器。
Global.asax
View Code
FilterConfig.cs
View Code
开工
整理思路:发生错误时要执行自己需要的代码,只需要继承IExceptionFilter,重写OnException方法,然后把自己的过滤器注册到全局即可。
创建过滤器,MyExceptionFilter类
复制代码
1 //因为微软已经提供了一个HandleErrorAttribute类(它其实也是继承了IExceptionFilter),所以我们只需继承它即可
2 public class MyExceptionFilter: HandleErrorAttribute
3 {
4 //重写OnException方法
5 public override void OnException(ExceptionContext filterContext)
6 {
7 base.OnException(filterContext);
8
9 //把错误写到日志文件里面去
10 //思考:如果同时来了多个错误,一起向文件中写内容,就会发生同时访问同一个文件问题。你会怎么解决?
11 //提示:锁、队列
12
13 //LogHelper类用来把错误写到日志里面去
14 LogHelper.Write(filterContext.Exception.ToString());
15
16 }
17 }
复制代码
LogHelper类,用来把错误写到日志里面去
View Code
把自己的过滤器注册到全局
View Code
自定义错误测试
View Code
OK,大功告成,以后就可以根据日志来找错误了。
星期二
情景
早晨,项目组长又来到小明身边,”昨天我用了你的错误日志功能,还不错,但是你将日志写在文件中整理不是太方便,还存在共享冲突问题,你改下写到数据库中“ ”...“
分析
查看昨天写的代码
发现此处是一个变化点,有可能写到文件中,有可能写到数据库中,有可能......
不就是写到不同的地方么,简单,多态就能搞定了。
开工
依赖于抽象,而不依赖于具体
创建IWriteLog接口
View Code
创建WriteLogToText类实现接口,用来写入文本
View Code
创建WriteLogToSqlServer类实现接口,用来写入数据库
View Code
对变化点进行修改
复制代码
1 string exceptionString = ExceptionStringQueue.Dequeue();
2 //依赖接口
3 IWriteLog writeLog = new WriteLogToSqlServer();
4 //IWriteLog writeLog = new WriteLogToText();
5 //把错误信息写到相应的地方
6 writeLog.WriteLog(exceptionString);
复制代码
OK,大功告成,又可以去美滋滋了...
星期三
情景
早晨,项目组长再一次来到小明身边,”经过我的思考,我觉得把错误信息同时写到文本和数据库中比较好“ ”为什么?“ “需求” “...”
分析
错误信息有可能要写到不同的地方,而且不知道有多少地方,说不定明天又加了一个Redis、后天再加一个....
这时候我们可以考虑创建一个集合来保存都需要写到那些地方去。(这里插一句:设计模式只是一种思想,实现方式肯定是不唯一的,但是思想是精髓,不能说这个代码是这个模式,换一种方式实现就不是这个模式了。)
然后依次写入即可。
开工
对LogHelper进行修改
复制代码
1 public class LogHelper
2 {
3 //添加一个静态的异常信息队列,只要出现异常就写到队列中。
4 public static Queue ExceptionStringQueue = new Queue();
5
6 //定义一个集合来存放所有的 观察者,
7 public static IList writeLogList = new List();
8
9 //第一次用到该类型时会执行静态构造函数,只被执行一次
10 static LogHelper() {
11
12 //观察(订阅)
13 writeLogList.Add(new WriteLogToSqlServer());
14 writeLogList.Add(new WriteLogToText());
15
16 //创建一个线程池,将方法排入队列以便执行
17 ThreadPool.QueueUserWorkItem(o=> {
18 while (true)
19 {
20 lock (ExceptionStringQueue)
21 {
22 //如果有错误信息写入日志
23 if (ExceptionStringQueue.Count > 0)
24 {
25 string exceptionString = ExceptionStringQueue.Dequeue();
26 //发布
27 foreach (var writeLog in writeLogList)
28 {
29 writeLog.WriteLog(exceptionString);
30 }
31 }
32 else
33 {
34 Thread.Sleep(1000);
35 }
36 }
37 }
38
39 });
40 }
41
42
43 //给外部提供方法,将错误信息写入队列
44 public static void Write(string exceptionString) {
45 lock (ExceptionStringQueue)
46 {
47 //将错误信息添加到队列
48 ExceptionStringQueue.Enqueue(exceptionString);
49 }
50 }
51 }
复制代码
后期如果还需要写入其它地方或者去掉一个的话,只需要Add一个或者删除一行即可。当然,现在的代码还有很多可优化的地方,比如把通知者(LogHelper)进行抽象,还可以通过配置文件加反射再次解耦。这里就不做过多介绍了。因为已经星期四了...
星期四
采用Log4Net
总结
观察者模式又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者同时监听同一个对象。当对象状态发生改变时,通知所订阅的观察者。
什么时候使用?
当一个对象改变同时需要改变其他对象,并且还不知道要改变多少对象。这时应该考虑观察者模式。星期一
情景
早晨,项目组长来到小明身边,“有人反映咱们的项目有Bug” “什么Bug?” “不知道,你添加一个日志模块自己看记录去。” ”...“
分析
在MVC全局过滤器中自己添加有异常过滤器。
Global.asax
View Code
FilterConfig.cs
View Code
开工
整理思路:发生错误时要执行自己需要的代码,只需要继承IExceptionFilter,重写OnException方法,然后把自己的过滤器注册到全局即可。
创建过滤器,MyExceptionFilter类
复制代码
1 //因为微软已经提供了一个HandleErrorAttribute类(它其实也是继承了IExceptionFilter),所以我们只需继承它即可
2 public class MyExceptionFilter: HandleErrorAttribute
3 {
4 //重写OnException方法
5 public override void OnException(ExceptionContext filterContext)
6 {
7 base.OnException(filterContext);
8
9 //把错误写到日志文件里面去
10 //思考:如果同时来了多个错误,一起向文件中写内容,就会发生同时访问同一个文件问题。你会怎么解决?
11 //提示:锁、队列
12
13 //LogHelper类用来把错误写到日志里面去
14 LogHelper.Write(filterContext.Exception.ToString());
15
16 }
17 }
复制代码
LogHelper类,用来把错误写到日志里面去
View Code
把自己的过滤器注册到全局
View Code
自定义错误测试
View Code
OK,大功告成,以后就可以根据日志来找错误了。
星期二
情景
早晨,项目组长又来到小明身边,”昨天我用了你的错误日志功能,还不错,但是你将日志写在文件中整理不是太方便,还存在共享冲突问题,你改下写到数据库中“ ”...“
分析
查看昨天写的代码
发现此处是一个变化点,有可能写到文件中,有可能写到数据库中,有可能......
不就是写到不同的地方么,简单,多态就能搞定了。
开工
依赖于抽象,而不依赖于具体
创建IWriteLog接口
View Code
创建WriteLogToText类实现接口,用来写入文本
View Code
创建WriteLogToSqlServer类实现接口,用来写入数据库
View Code
对变化点进行修改
复制代码
1 string exceptionString = ExceptionStringQueue.Dequeue();
2 //依赖接口
3 IWriteLog writeLog = new WriteLogToSqlServer();
4 //IWriteLog writeLog = new WriteLogToText();
5 //把错误信息写到相应的地方
6 writeLog.WriteLog(exceptionString);
复制代码
OK,大功告成,又可以去美滋滋了...
星期三
情景
早晨,项目组长再一次来到小明身边,”经过我的思考,我觉得把错误信息同时写到文本和数据库中比较好“ ”为什么?“ “需求” “...”
分析
错误信息有可能要写到不同的地方,而且不知道有多少地方,说不定明天又加了一个Redis、后天再加一个....
这时候我们可以考虑创建一个集合来保存都需要写到那些地方去。(这里插一句:设计模式只是一种思想,实现方式肯定是不唯一的,但是思想是精髓,不能说这个代码是这个模式,换一种方式实现就不是这个模式了。)
然后依次写入即可。
开工
对LogHelper进行修改
复制代码
1 public class LogHelper
2 {
3 //添加一个静态的异常信息队列,只要出现异常就写到队列中。
4 public static Queue ExceptionStringQueue = new Queue();
5
6 //定义一个集合来存放所有的 观察者,
7 public static IList writeLogList = new List();
8
9 //第一次用到该类型时会执行静态构造函数,只被执行一次
10 static LogHelper() {
11
12 //观察(订阅)
13 writeLogList.Add(new WriteLogToSqlServer());
14 writeLogList.Add(new WriteLogToText());
15
16 //创建一个线程池,将方法排入队列以便执行
17 ThreadPool.QueueUserWorkItem(o=> {
18 while (true)
19 {
20 lock (ExceptionStringQueue)
21 {
22 //如果有错误信息写入日志
23 if (ExceptionStringQueue.Count > 0)
24 {
25 string exceptionString = ExceptionStringQueue.Dequeue();
26 //发布
27 foreach (var writeLog in writeLogList)
28 {
29 writeLog.WriteLog(exceptionString);
30 }
31 }
32 else
33 {
34 Thread.Sleep(1000);
35 }
36 }
37 }
38
39 });
40 }
41
42
43 //给外部提供方法,将错误信息写入队列
44 public static void Write(string exceptionString) {
45 lock (ExceptionStringQueue)
46 {
47 //将错误信息添加到队列
48 ExceptionStringQueue.Enqueue(exceptionString);
49 }
50 }
51 }
复制代码
后期如果还需要写入其它地方或者去掉一个的话,只需要Add一个或者删除一行即可。当然,现在的代码还有很多可优化的地方,比如把通知者(LogHelper)进行抽象,还可以通过配置文件加反射再次解耦。这里就不做过多介绍了。因为已经星期四了...
星期四
采用Log4Net
总结
观察者模式又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者同时监听同一个对象。当对象状态发生改变时,通知所订阅的观察者。
什么时候使用?
当一个对象改变同时需要改变其他对象,并且还不知道要改变多少对象。这时应该考虑观察者模式。星期一
情景
早晨,项目组长来到小明身边,“有人反映咱们的项目有Bug” “什么Bug?” “不知道,你添加一个日志模块自己看记录去。” ”...“
分析
在MVC全局过滤器中自己添加有异常过滤器。
Global.asax
View Code
FilterConfig.cs
View Code
开工
整理思路:发生错误时要执行自己需要的代码,只需要继承IExceptionFilter,重写OnException方法,然后把自己的过滤器注册到全局即可。
创建过滤器,MyExceptionFilter类
复制代码
1 //因为微软已经提供了一个HandleErrorAttribute类(它其实也是继承了IExceptionFilter),所以我们只需继承它即可
2 public class MyExceptionFilter: HandleErrorAttribute
3 {
4 //重写OnException方法
5 public override void OnException(ExceptionContext filterContext)
6 {
7 base.OnException(filterContext);
8
9 //把错误写到日志文件里面去
10 //思考:如果同时来了多个错误,一起向文件中写内容,就会发生同时访问同一个文件问题。你会怎么解决?
11 //提示:锁、队列
12
13 //LogHelper类用来把错误写到日志里面去
14 LogHelper.Write(filterContext.Exception.ToString());
15
16 }
17 }
复制代码
LogHelper类,用来把错误写到日志里面去
View Code
把自己的过滤器注册到全局
View Code
自定义错误测试
View Code
OK,大功告成,以后就可以根据日志来找错误了。
星期二
情景
早晨,项目组长又来到小明身边,”昨天我用了你的错误日志功能,还不错,但是你将日志写在文件中整理不是太方便,还存在共享冲突问题,你改下写到数据库中“ ”...“
分析
查看昨天写的代码
发现此处是一个变化点,有可能写到文件中,有可能写到数据库中,有可能......
不就是写到不同的地方么,简单,多态就能搞定了。
开工
依赖于抽象,而不依赖于具体
创建IWriteLog接口
View Code
创建WriteLogToText类实现接口,用来写入文本
View Code
创建WriteLogToSqlServer类实现接口,用来写入数据库
View Code
对变化点进行修改
复制代码
1 string exceptionString = ExceptionStringQueue.Dequeue();
2 //依赖接口
3 IWriteLog writeLog = new WriteLogToSqlServer();
4 //IWriteLog writeLog = new WriteLogToText();
5 //把错误信息写到相应的地方
6 writeLog.WriteLog(exceptionString);
复制代码
OK,大功告成,又可以去美滋滋了...
星期三
情景
早晨,项目组长再一次来到小明身边,”经过我的思考,我觉得把错误信息同时写到文本和数据库中比较好“ ”为什么?“ “需求” “...”
分析
错误信息有可能要写到不同的地方,而且不知道有多少地方,说不定明天又加了一个Redis、后天再加一个....
这时候我们可以考虑创建一个集合来保存都需要写到那些地方去。(这里插一句:设计模式只是一种思想,实现方式肯定是不唯一的,但是思想是精髓,不能说这个代码是这个模式,换一种方式实现就不是这个模式了。)
然后依次写入即可。
开工
对LogHelper进行修改
复制代码
1 public class LogHelper
2 {
3 //添加一个静态的异常信息队列,只要出现异常就写到队列中。
4 public static Queue ExceptionStringQueue = new Queue();
5
6 //定义一个集合来存放所有的 观察者,
7 public static IList writeLogList = new List();
8
9 //第一次用到该类型时会执行静态构造函数,只被执行一次
10 static LogHelper() {
11
12 //观察(订阅)
13 writeLogList.Add(new WriteLogToSqlServer());
14 writeLogList.Add(new WriteLogToText());
15
16 //创建一个线程池,将方法排入队列以便执行
17 ThreadPool.QueueUserWorkItem(o=> {
18 while (true)
19 {
20 lock (ExceptionStringQueue)
21 {
22 //如果有错误信息写入日志
23 if (ExceptionStringQueue.Count > 0)
24 {
25 string exceptionString = ExceptionStringQueue.Dequeue();
26 //发布
27 foreach (var writeLog in writeLogList)
28 {
29 writeLog.WriteLog(exceptionString);
30 }
31 }
32 else
33 {
34 Thread.Sleep(1000);
35 }
36 }
37 }
38
39 });
40 }
41
42
43 //给外部提供方法,将错误信息写入队列
44 public static void Write(string exceptionString) {
45 lock (ExceptionStringQueue)
46 {
47 //将错误信息添加到队列
48 ExceptionStringQueue.Enqueue(exceptionString);
49 }
50 }
51 }
复制代码
后期如果还需要写入其它地方或者去掉一个的话,只需要Add一个或者删除一行即可。当然,现在的代码还有很多可优化的地方,比如把通知者(LogHelper)进行抽象,还可以通过配置文件加反射再次解耦。这里就不做过多介绍了。因为已经星期四了...
星期四
采用Log4Net
总结
观察者模式又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者同时监听同一个对象。当对象状态发生改变时,通知所订阅的观察者。
什么时候使用?
当一个对象改变同时需要改变其他对象,并且还不知道要改变多少对象。这时应该考虑观察者模式。星期一
情景
早晨,项目组长来到小明身边,“有人反映咱们的项目有Bug” “什么Bug?” “不知道,你添加一个日志模块自己看记录去。” ”...“
分析
在MVC全局过滤器中自己添加有异常过滤器。
Global.asax
View Code
FilterConfig.cs
View Code
开工
整理思路:发生错误时要执行自己需要的代码,只需要继承IExceptionFilter,重写OnException方法,然后把自己的过滤器注册到全局即可。
创建过滤器,MyExceptionFilter类
复制代码
1 //因为微软已经提供了一个HandleErrorAttribute类(它其实也是继承了IExceptionFilter),所以我们只需继承它即可
2 public class MyExceptionFilter: HandleErrorAttribute
3 {
4 //重写OnException方法
5 public override void OnException(ExceptionContext filterContext)
6 {
7 base.OnException(filterContext);
8
9 //把错误写到日志文件里面去
10 //思考:如果同时来了多个错误,一起向文件中写内容,就会发生同时访问同一个文件问题。你会怎么解决?
11 //提示:锁、队列
12
13 //LogHelper类用来把错误写到日志里面去
14 LogHelper.Write(filterContext.Exception.ToString());
15
16 }
17 }
复制代码
LogHelper类,用来把错误写到日志里面去
View Code
把自己的过滤器注册到全局
View Code
自定义错误测试
View Code
OK,大功告成,以后就可以根据日志来找错误了。
星期二
情景
早晨,项目组长又来到小明身边,”昨天我用了你的错误日志功能,还不错,但是你将日志写在文件中整理不是太方便,还存在共享冲突问题,你改下写到数据库中“ ”...“
分析
查看昨天写的代码
发现此处是一个变化点,有可能写到文件中,有可能写到数据库中,有可能......
不就是写到不同的地方么,简单,多态就能搞定了。
开工
依赖于抽象,而不依赖于具体
创建IWriteLog接口
View Code
创建WriteLogToText类实现接口,用来写入文本
View Code
创建WriteLogToSqlServer类实现接口,用来写入数据库
View Code
对变化点进行修改
复制代码
1 string exceptionString = ExceptionStringQueue.Dequeue();
2 //依赖接口
3 IWriteLog writeLog = new WriteLogToSqlServer();
4 //IWriteLog writeLog = new WriteLogToText();
5 //把错误信息写到相应的地方
6 writeLog.WriteLog(exceptionString);
复制代码
OK,大功告成,又可以去美滋滋了...
星期三
情景
早晨,项目组长再一次来到小明身边,”经过我的思考,我觉得把错误信息同时写到文本和数据库中比较好“ ”为什么?“ “需求” “...”
分析
错误信息有可能要写到不同的地方,而且不知道有多少地方,说不定明天又加了一个Redis、后天再加一个....
这时候我们可以考虑创建一个集合来保存都需要写到那些地方去。(这