上一篇《系统操作日志设计》,已基本介绍了为什么要系统操作日志和设计系统操作日志部分内容,如不清楚系统操作日志的请点这里。 :)

通了解《系统操作日志设计》,已基本明确我们不能通过clone的方式来做日志的设计,因为这样不仅会造成的你数据库表爆炸的情况,还大大的增加了工作量,减少了系统的可维护性。

通过思考大概清楚系统操作日志的设计,以下是其UML图:

通过上图,我们可以了解知道该UML主要由三个表组成,其中一个主表LogSetting和两个从表分别是LogOperation和LogSettingDetail。

那么怎么样才能通过这样的设计来现实我们的日志功能呢?

其实一开始我就觉得通过.net的反射功能可以很简单、很方便的实现这个功能,所以我就顺着一个思路来实现她;通过反射动态的获取Model实体的属性,然后再根据LogSettingDetail配置来匹配所要记录的字段信息。

先来主要的代码吧,发现将思想用文字表达出来还是较困难的,代码比较直接:

代码的实现

usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingBLL.Sys;usingSystem.Collections.Generic;usingSystem.Collections.Specialized;usingSystem.Text;usingSystem.Reflection;/// <summary>
///LogManager 的摘要说明/// </summary>public classLogManager<T>whereT :new()
{#regionConstructor/// <summary>///日志管理构造函数/// </summary>publicLogManager(){tableName =typeof(T).Name;Model.Sys.LogSettingmodel = GetLogSetting(tableName);if(model !=null){businessName = model.BusinessName;logID = model.LogID;primaryKey = model.PrimaryKey;urlTemplate = model.UrlTemplate;deleteScriptTemplate = model.DeleteScriptTemplate;updateScriptTemplate = model.UpdateScriptTemplate;}else{throw newArgumentNullException("日志设置为空!");}}/// <summary>//////日志管理构造函数/// </summary>/// </summary>/// <param name="tableName">表名</param>/// <param name="businessName">业务名称</param>publicLogManager(stringtableName,stringbusinessName){this.tableName = tableName;this.businessName = businessName;Model.Sys.LogSettingmodel = GetLogSetting(tableName, businessName);if(model !=null){logID = model.LogID;primaryKey = model.PrimaryKey;urlTemplate = model.UrlTemplate;deleteScriptTemplate = model.DeleteScriptTemplate;updateScriptTemplate = model.UpdateScriptTemplate;}else{throw newArgumentNullException("日志设置为空!");}}#endregion#regionPropertiesprivate intlogID;private stringtableName;private stringbusinessName;private stringprimaryKey;private stringurlTemplate;private stringdeleteScriptTemplate;private stringupdateScriptTemplate;/// <summary>///日志设置实体列表/// </summary>publicList<Model.Sys.LogSetting> LogSettingList{get{System.Web.Caching.Cachecache =HttpRuntime.Cache;List<Model.Sys.LogSetting> list = cache["LogSettingList"]asList<Model.Sys.LogSetting>;if(list !=null&& list.Count > 0){returnlist;}else{LogSettingbll =newLogSetting();list = bll.GetModelList(string.Empty);cache["LogSettingList"] = list;returnlist;}}set{System.Web.Caching.Cachecache =HttpRuntime.Cache;cache["LogSettingList"] =null;}}/// <summary>///日志设置明细/// </summary>publicList<Model.Sys.LogSettingDetail> LogSettingDetail{get{System.Web.Caching.Cachecache =HttpRuntime.Cache;List<Model.Sys.LogSettingDetail> list = cache["LogSettingDetail"]asList<Model.Sys.LogSettingDetail>;if(list !=null&& list.Count > 0){returnlist;}else{LogSettingDetailbll =newLogSettingDetail();list = bll.GetModelList(string.Empty);cache["LogSettingDetail"] = list;returnlist;}}set{System.Web.Caching.Cachecache =HttpRuntime.Cache;cache["LogSettingDetail"] =null;}}#endregion#regionMethod/// <summary>///通过logId获取日志设置明细/// </summary>/// <param name="logId">日志设置编号</param>/// <returns></returns>privateList<Model.Sys.LogSettingDetail> GetLogSettingDetails(intlogId){if(logId == 0)throw newArgumentNullException("LogID为空");List<Model.Sys.LogSettingDetail> list =newList<Model.Sys.LogSettingDetail>();foreach(Model.Sys.LogSettingDetailvarinLogSettingDetail){if(var.LogID == logId)list.Add(var);}returnlist;}/// <summary>///通过tableName和businessName来获取日志设置对象/// </summary>/// <param name="tableName"></param>/// <param name="businessName"></param>/// <returns></returns>privateModel.Sys.LogSettingGetLogSetting(stringtableName,stringbusinessName){foreach(Model.Sys.LogSettingvarinLogSettingList){if(var.TableName.Equals(tableName,StringComparison.InvariantCultureIgnoreCase) && var.BusinessName.Equals(businessName,StringComparison.InvariantCultureIgnoreCase))returnvar;}return null;}privateModel.Sys.LogSettingGetLogSetting(stringtableName){foreach(Model.Sys.LogSettingvarinLogSettingList){if(var.TableName.Equals(tableName,StringComparison.InvariantCultureIgnoreCase))returnvar;}return null;}/// <summary>///比较两个实体,然后返回实体中每个属性值不同的内容/// </summary>/// <param name="oldObj"></param>/// <param name="newObj"></param>/// <returns></returns>public stringCompare(T oldObj, T newObj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<table class=/"GridView/" cellspacing=/"0/" rules=/"all/" border=/"1/" id=/"gv/" style=/"border-collapse:collapse;/">";tableHeader +="<tr><th scope=/"col/">序号</th><th scope=/"col/">字段</th><th scope=/"col/">名称</th><th scope=/"col/">旧值</th><th scope=/"col/">新值</th></tr>";stringtableRow ="<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td></tr>";List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(oldObj,null);objectn = property.GetValue(newObj,null);if(!IsEqual(property.PropertyType, o, n)){sbResult.AppendFormat(tableRow, i % 2 == 0 ?"odd":"even", i, var.ColumnName, var.ColumnText, o, n);i++;}}}sbResult.Append("</table>");#regionAdd Log Recordif(i > 1){Model.Sys.LogOperationoperModel =newModel.Sys.LogOperation();operModel.LogID = logID;operModel.OperationType = (int)OperationType.Update;operModel.Content = tableHeader + sbResult.ToString();operModel.CreateTime =DateTime.Now;if(HttpContext.Current !=null)operModel.CreateUser =HttpContext.Current.User.Identity.Name;if(!string.IsNullOrEmpty(primaryKey)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = p.GetValue(newObj,null);if(o !=null){operModel.PrimaryKeyValue = o.ToString();if(urlTemplate.Contains("{0}"))operModel.Url =string.Format(urlTemplate, o.ToString());}}LogOperationoperBll =newLogOperation();operBll.Add(operModel);}#endregionreturntableHeader + sbResult.ToString();}/// <summary>///删除实体操作,这里并不是真的删除该实体,而是将删除的操作记录在日志中/// </summary>/// <param name="obj"></param>/// <returns></returns>public stringDelete(T obj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<table class=/"GridView/" cellspacing=/"0/" rules=/"all/" border=/"1/" id=/"gv/" style=/"border-collapse:collapse;/">";tableHeader +="<tr><th scope=/"col/">序号</th><th scope=/"col/">字段</th><th scope=/"col/">名称</th><th scope=/"col/">值</th></tr>";stringtableRow ="<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(obj,null);sbResult.AppendFormat(tableRow, i % 2 == 0 ?"odd":"even", i, var.ColumnName, var.ColumnText, o);i++;}}sbResult.Append("</table>");#regionAdd Log Record       Model.Sys.LogOperationoperModel =newModel.Sys.LogOperation();operModel.LogID = logID;operModel.OperationType = (int)OperationType.Delete;operModel.Content = tableHeader + sbResult.ToString();operModel.CreateTime =DateTime.Now;if(!string.IsNullOrEmpty(primaryKey)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = p.GetValue(obj,null);if(o !=null){operModel.PrimaryKeyValue = o.ToString();if(urlTemplate.Contains("{0}"))operModel.Url =string.Format(urlTemplate, o.ToString());}}if(HttpContext.Current !=null)operModel.CreateUser =HttpContext.Current.User.Identity.Name;LogOperationoperBll =newLogOperation();operBll.Add(operModel);#endregionreturn string.Empty;}/// <summary>///添加实体,将添加的操作记录在日志中/// </summary>/// <param name="obj"></param>/// <returns></returns>public stringAdd(T obj){TypeobjTye =typeof(T);StringBuildersbResult =newStringBuilder();stringtableHeader ="<table class=/"GridView/" cellspacing=/"0/" rules=/"all/" border=/"1/" id=/"gv/" style=/"border-collapse:collapse;/">";tableHeader +="<tr><th scope=/"col/">序号</th><th scope=/"col/">字段</th><th scope=/"col/">名称</th><th scope=/"col/">值</th></tr>";stringtableRow ="<tr class='{0}'><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>";List<Model.Sys.LogSettingDetail> list = GetLogSettingDetails(logID);inti = 1;foreach(Model.Sys.LogSettingDetailvarinlist){PropertyInfoproperty = objTye.GetProperty(var.ColumnName);if(property !=null&& !property.IsSpecialName){objecto = property.GetValue(obj,null);sbResult.AppendFormat(tableRow, i % 2 == 0 ?"odd":"even", i, var.ColumnName, var.ColumnText, o);i++;}}sbResult.Append("</table>");#regionAdd Log Record      Model.Sys.LogOperationoperModel =newModel.Sys.LogOperation();operModel.LogID = logID;operModel.OperationType = (int)OperationType.Add;operModel.Content = tableHeader + sbResult.ToString();operModel.CreateTime =DateTime.Now;if(!string.IsNullOrEmpty(primaryKey)){PropertyInfop = objTye.GetProperty(primaryKey);objecto = p.GetValue(obj,null);if(o !=null){operModel.PrimaryKeyValue = o.ToString();if(urlTemplate.Contains("{0}"))operModel.Url =string.Format(urlTemplate, o.ToString());}}if(HttpContext.Current !=null)operModel.CreateUser =HttpContext.Current.User.Identity.Name;LogOperationoperBll =newLogOperation();operBll.Add(operModel);#endregionreturn string.Empty;}/// <summary>///复制一个对象/// </summary>/// <param name="obj"></param>/// <returns></returns>publicT Clone(T obj){TypeobjTye =typeof(T);T model =newT();PropertyInfo[] properties = objTye.GetProperties();foreach(PropertyInfopropertyinproperties){if(!property.IsSpecialName){objecto = property.GetValue(obj,null);property.SetValue(model, o,null);}}returnmodel;}private boolIsEqual(TypedataType,objectoldObj,objectnewObj){if(oldObj ==null&& newObj ==null)return true;if(dataType ==typeof(int)){return(int)oldObj == (int)newObj;}else if(dataType ==typeof(decimal)){return(decimal)oldObj == (decimal)newObj;}else if(dataType ==typeof(double)){return(double)oldObj == (double)newObj;}else if(dataType ==typeof(Guid)){return(Guid)oldObj == (Guid)newObj;}else if(dataType ==typeof(DateTime)){return(DateTime)oldObj == (DateTime)newObj;}elsereturnoldObj.Equals(newObj);}#regionScript. Excute//public int DeleteBusRecode(string primaryKeyValue)//{//    if (string.IsNullOrEmpty(tableName))//        throw new ArgumentException("tableName为空");//    if(string.IsNullOrEmpty(primaryKey))//        throw new ArgumentException("primaryKey为空");//    if (string.IsNullOrEmpty(deleteScriptTemplate))//        throw new ArgumentException("deleteScriptTemplate为空");//    string strSql = string.Format(deleteScriptTemplate, primaryKeyValue);//    Database db = DatabaseFactory.CreateDatabase();//    return 0;//}#endregion#endregion}public enumOperationType{Select = 0,Add = 1,Update = 2,Delete = 3
}

使用的场景

Model文件:

publicclassEmployeeModel{publicintID{get;set;}publicstringName{get;set;}…}
下面介绍如何将系统操作日志集成到你的业务系统中
添加操作:
EmployeeBll bll = new EmployeeBll();
EmployeeModel model = new EmployeeModel();
/* model 实体经过漫长的 赋值 后… */
bll.Add(model);    //添加实体
//添加系统操作记录
//日志LogManager<EmployeeModel> log =newLogManager<EmployeeModel>();
log.Add(model);
 
更新操作:
EmployeeBll bll = new EmployeeBll();
EmployeeModel model = bll.GetModel(employeeID);
LogManager<EmployeeModel> log =newLogManager<EmployeeModel>();
EmployeeModel modelOld = log.Clone(model);   //克隆EmployeeModel实体对象,这个主要是在系统操作日志记录时使用的
 
/* model 实体又经过漫长的 赋值 后… */
bll.Update(model);     //更新实体
//将更新的内容写入系统操作日志中
log.Compare(modelOld, model);    //原来的实体和赋值后的实体对比,并将更新的内容写入系统操作日志中
 
删除操作:
在GridView的RowDeleting事件中获取要删除的实体
EmployeeBll bll = new EmployeeBll();
EmployeeModel model = bll.GetModel(employeeID);
bll.Delete(employeeID);
LogManager<EmployeeModel> log =newLogManager<EmployeeModel>();
log.Delete(model);       //实体的内容记录到日志中
 

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

总结:

大家可以看到代码还是比较粗糙的,有不少的重复的代码,下一节将会讨论如何进行系统操作日志管理

另外如何大家有什么意见或想法请分享提出。

本节用到的知识点

1、泛型

2、反射

3、缓存

优点:

1、使用和集成方便,代码量小;

2、大大提高工作效率,避免表爆炸;

缺点:

1、代码有待优化;

2、可扩展性较差

转载[http://samlin.cnblogs.com/]

转载于:https://www.cnblogs.com/jackljf/archive/2010/07/20/3589396.html

系统操作日志设计(二)相关推荐

  1. 浅谈管理系统操作日志设计(附操作日志类)

    原文地址:http://www.cnblogs.com/hooray/archive/2012/09/05/2672133.html 相关文章链接:<系统操作日志设计> 在开始做之前,必须 ...

  2. 系统操作日志实现_JAVA

    最近需求需要记录系统日志,在网上查询发现目前有两种主流方式.一种是利用AOP注解实现,一种是利用拦截器实现. AOP实现的方式更为灵活,但需要为每一个需要记录的方法上加上注解(类似于白名单). 我这个 ...

  3. 如何在springboot项目中使用自定义注解实现系统操作日志的功能

    通常我们的项目中都需要记录操作日志,方便回溯问题,找到根源. 因为给项目添加日志记录功能是属于系统级别的功能,所以这个问题我们马上会想到spring的AOP,可以通过切面的形式.那么怎么来实现呢? 先 ...

  4. 华为服务器怎么查看系统日志,查询系统操作日志(operationlog)

    # 查询操作日志. iMana:/->ipmcget -d operationlog -v list 0 Aug 13 23:07:24 iMana bmcipmi.out[354]: Oper ...

  5. 服务器系统操作日志,查询系统操作日志(operationlog)

    # 查询操作日志. iMana:/->ipmcget -d operationlog -v list 0 Aug 13 23:07:24 iMana bmcipmi.out[354]: Oper ...

  6. java 操作日志设计_日志系统新贵 Loki,确实比笨重的ELK轻

    本文同步Java知音社区,专注于Java 作者:linkt1234http://blog.csdn.net/Linkthaha/article/details/100575278 最近,在对公司容器云 ...

  7. 业务应用系统的业务操作日志设计

    目的:记录业务的访问活动 操作时间:精确到秒 服务器IP:可能部署多台服务器,记录当前线程服务器IP地址 访问者IP:访问者ip地址 访问者账号:系统通过手机号登录,记录手机号 业务名称:读取菜单名 ...

  8. java 可视化系统操作日志_技术文 | 日志框架使用技巧分享

    原标题:技术文 | 日志框架使用技巧分享 日志的意义 对于一个应用程序来说日志记录是具有重要意义的. 日志通常用于线上问题追踪,协助定位业务问题或程序问题,以及基于日志的业务逻辑统计分析等. java ...

  9. spring aop 实现系统操作日志记录存储到数据库

    1.引入依赖 <!--spring切面aop依赖--> <dependency><groupId>org.springframework.boot</grou ...

最新文章

  1. Turtle-可视化界面画圣诞树
  2. Java获得泛型类中T的实例
  3. CentOS 7 安装MySQL 5.6遇到问题及解决方案
  4. Excel中这四个常出错的地方,你一定中过!
  5. sql基础教程亚马逊_针对Amazon,Apple,Google的常见SQL面试问题
  6. 解决VS命令提示符 “Setting environment for using Microsoft Visual Studio. 此时不应有“系列错误
  7. python 图像走势预测_在keras中对单一输入图像进行预测并返回预测结果操作
  8. bzoj 2844 子集异或和名次
  9. 浅析C++开发语言的特点
  10. 设计模式之职责链模式(责任链模式)
  11. 字节架构师:来说说 Kafka 的消费者客户端详解,你都搞懂了吗,Javaweb面试总结
  12. python常用的几个库_盘点Python常用的20个库
  13. 网络流量分析与Android逆向小结
  14. git 使用总结(三)repo sync -m
  15. 华为架构师谈如何理解运用模块与微服务,系统学Java从零开始
  16. Python基于OpenCV的图像去雾算法[完整源码&部署教程]
  17. 109、IG-541混合气体灭火系统的设计灭火浓度
  18. Python的生成器和迭代器
  19. 计算机图形学常见算法原理,计算机图形学常用算法及代码大全
  20. mysql基础地总结一下

热门文章

  1. jquery-confirm
  2. excel公式:定位单元格
  3. kafaka生产者消费者demo(简易上手demo)
  4. c语言大作业菜单,C语言大作业:编写菜单控制猜商品价格程序
  5. cpp判断输入为数字_猜数字小程序带你C语言入门
  6. 怎么看python程序卡在哪里_Python程序卡住了
  7. xml文件转换成图片_如何把pdf文件转换成图片?
  8. discuz mysql_搭建Discuz! (mysql+apache+Discuz! )
  9. Hadoop报错AccessControlException: Permission denied: user=vincent, access=WRITE, inode=/:iie4bu:supe
  10. win10 笔记本猎豹WiFi无法打开