搭建一套自己实用的.net架构(2)【日志模块-log4net】
先谈谈简单的模块,日志。在系统中日志模块是必须的,什么系统日志,操作日志,调试日志。这里用的是log4net。
对log4net还不熟悉的小伙伴们赶快去搜索基础教程哦, 我这里就不温故了。
那么有人要问了,log4net确实很强大,而且我们也会用。还要单独写一篇文章来介绍,有必要吗?
我简单的举两个场景:
1:log4net写入DB 还需要在 log4net中配置数据库连接字符串, 我想log4net 和 我的 connectionStrings 用1个配置不行吗?
2:log4net写入参数扩展问题,我配置文件想写入ip地址,那我代码还要定义一个ip的参数。 那我再扩展,还需要再定义,这改动量太大了,能不能只传一个实体类,让log4net自己去映射那?这样我就可以写一些通用的方法,好多项目都可以直接拿过来用,代码修改量也少了点。
有人觉得这都不是问题,高手请跳过。
我这里将日志模块单独封装了一个HY.Log,截图如下:
aaarticlea/png;base64,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" alt="" />
看图有点乱,下面我给大家捋一捋(念lv 念成lu的去面壁思过 ):
第一步:实现自定义参数
我们要在PatternConverter文件夹中定义一些可扩展参数,这样就可以在log4net配置文件中随心使用了,哪截图中我实现了获取客户端ip、获取服务器端ip
或许服务器mac地址。
就拿ClientIpPatternConverter.cs来说需要继承log4net下 log4net.Layout.Pattern.PatternLayoutConverter类,来实现扩展。
- using System.IO;
- using log4net.Core;
- using log4net.Layout.Pattern;
- namespace HY.Log.PatternConverter
- {
- /// <summary>
- /// B/S 客户端地址扩展
- /// </summary>
- internal class ClientIpPatternConverter : PatternLayoutConverter
- {
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
- {
- writer.Write(HY.Utilities.IPHelper.GetRemoteIPAddress());
- }
- }
- }
接着在分别实现 MAC、服务端IP、 以及其它你任何想扩展的参数。
ObjectPatternConverter.cs 这个类就比较特殊了。这个自定义参数其实是让你传入一个实体类,然后通过反射技术,让log4net通过配置文件的 配置自动映射要传入的值。
上面的类 是针对特定的通用功能扩展,这个类只需要定义一个即可。
- using System.IO;
- using System.Reflection;
- using log4net.Core;
- using log4net.Layout.Pattern;
- namespace HY.Log.PatternConverter
- {
- internal class ObjectPatternConverter : PatternLayoutConverter
- {
- protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
- {
- if (Option != null)
- {
- // Write the value for the specified key
- WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
- }
- else
- {
- // Write all the key value pairs
- WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
- }
- }
- /// <summary>
- /// 通过反射获取传入的日志对象的某个属性的值
- /// </summary>
- /// <param name="property"></param>
- /// <param name="loggingEvent"></param>
- /// <returns></returns>
- private object LookupProperty(string property, LoggingEvent loggingEvent)
- {
- object propertyValue = string.Empty;
- PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
- if (propertyInfo != null)
- propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
- return propertyValue;
- }
- }
- }
第二步:实现log4net自定义布局,将自定义参数进行注册
CustomLayout.cs
- using HY.Log.PatternConverter;
- using log4net.Layout;
- namespace HY.Log
- {
- /// <summary>
- /// 定义log日志布局的参数信息
- /// </summary>
- public class CustomLayout : PatternLayout
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- public CustomLayout()
- {
- #region 内部自定义
- AddConverter("ServerIP", typeof(ServerIpPatternConverter));
- AddConverter("ClientIP", typeof(ClientIpPatternConverter));
- AddConverter("MAC", typeof(MacPatternConverter));
- #endregion
- #region 支持开发人员自定义
- AddConverter("Object", typeof(ObjectPatternConverter));
- #endregion
- }
- }
- }
代码将自定义的参数以 key value 的形式进行注册, 以后我们再log4net进行配置的时候 就要记住这些关键字了, 这都是你自己定义的。
你敢在代码中实现 AddConverter("XXOO", typeof(XXOOPatternConverter)); 吗?
第三步:定义自己框架的Log接口并实现它
没啥可说的,看代码吧。
LogMessage.cs 这个类其实就是写了一个传入的的自定义参数的实体类,你可以自己写。不过最好是继承这个类进行扩展。
- using System;
- namespace HY.Log
- {
- /// <summary>
- /// 用于记录日志信息
- /// </summary>
- [Serializable]
- public class LogMessage
- {
- /// <summary>
- /// 日志信息
- /// </summary>
- public string Message { get; set; }
- }
- }
ILog.cs
- using System;
- namespace HY.Log
- {
- public interface ILog
- {
- /// <summary>
- /// 写入Debug日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- void Debug(string message, Exception exception = null);
- /// <summary>
- /// 写入Debug日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- void Debug(object messageEntity, Exception exception = null);
- /// <summary>
- /// 写入Info日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- void Info(string message, Exception exception = null);
- /// <summary>
- /// 写入Info日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- void Info(object messageEntity, Exception exception = null);
- /// <summary>
- /// 写入Warn日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- void Warn(string message, Exception exception = null);
- /// <summary>
- /// 写入Warn日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- void Warn(object messageEntity, Exception exception = null);
- /// <summary>
- /// 写入Error日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- void Error(string message, Exception exception = null);
- /// <summary>
- /// 写入Error日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- void Error(object messageEntity, Exception exception = null);
- /// <summary>
- /// 写入Fatal日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- void Fatal(string message, Exception exception = null);
- /// <summary>
- /// 写入Fatal日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- void Fatal(object messageEntity, Exception exception = null);
- }
- }
NormalLog.cs
- using System;
- using System.Collections.Generic;
- namespace HY.Log
- {
- public class NormalLog : ILog
- {
- #region private
- private static Dictionary<string, log4net.ILog> listILog = new Dictionary<string, log4net.ILog>(); //Log对象集合
- private log4net.ILog iLog; //当前日志对象的实例
- #endregion
- #region 构造函数
- /// <summary>
- /// 构造函数,传入Log4NET 的ILog对象
- /// </summary>
- /// <param name="logger"></param>
- public NormalLog(log4net.ILog logger)
- {
- string LoggerName = logger.Logger.Name; //logger 配置节名称
- if (!listILog.ContainsKey(LoggerName))
- {
- lock (listILog)
- {
- if (!listILog.ContainsKey(LoggerName))
- {
- listILog.Add(LoggerName, logger);
- }
- else
- {
- listILog[LoggerName] = logger;
- }
- }
- }
- else if (listILog[LoggerName] == null)
- {
- listILog[LoggerName] = logger;
- }
- iLog = listILog[LoggerName];
- }
- public NormalLog(string loggerName)
- {
- log4net.ILog logger = log4net.LogManager.GetLogger(loggerName);
- string LoggerName = logger.Logger.Name; //logger 配置节名称
- if (!listILog.ContainsKey(LoggerName))
- {
- listILog.Add(LoggerName, logger);
- }
- else if (listILog[LoggerName] == null)
- {
- listILog[LoggerName] = logger;
- }
- iLog = listILog[LoggerName];
- }
- #endregion
- #region 写入日志
- /// <summary>
- /// 写入Debug日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- public void Debug(string message, Exception exception = null)
- {
- LogMessage messageEntity = new LogMessage
- {
- Message = message
- };
- Debug(messageEntity, exception);
- }
- /// <summary>
- /// 写入Debug日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- public void Debug(object messageEntity, Exception exception = null)
- {
- if (iLog.IsDebugEnabled)
- {
- if (exception != null)
- {
- iLog.Debug(messageEntity, exception);
- }
- else
- {
- iLog.Debug(messageEntity);
- }
- }
- }
- /// <summary>
- /// 写入Info日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- public void Info(string message, Exception exception = null)
- {
- LogMessage messageEntity = new LogMessage
- {
- Message = message
- };
- Info(messageEntity, exception);
- }
- /// <summary>
- /// 写入Info日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- public void Info(object messageEntity, Exception exception = null)
- {
- if (iLog.IsInfoEnabled)
- {
- if (exception != null)
- {
- iLog.Info(messageEntity, exception);
- }
- else
- {
- iLog.Info(messageEntity);
- }
- }
- }
- /// <summary>
- /// 写入Warn日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- public void Warn(string message, Exception exception = null)
- {
- LogMessage messageEntity = new LogMessage
- {
- Message = message
- };
- Warn(messageEntity, exception);
- }
- /// <summary>
- /// 写入Warn日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- public void Warn(object messageEntity, Exception exception = null)
- {
- if (iLog.IsWarnEnabled)
- {
- if (exception != null)
- {
- iLog.Warn(messageEntity, exception);
- }
- else
- {
- iLog.Warn(messageEntity);
- }
- }
- }
- /// <summary>
- /// 写入Error日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- public void Error(string message, Exception exception = null)
- {
- LogMessage messageEntity = new LogMessage
- {
- Message = message
- };
- Error(messageEntity, exception);
- }
- /// <summary>
- /// 写入Error日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- public void Error(object messageEntity, Exception exception = null)
- {
- if (iLog.IsErrorEnabled)
- {
- if (exception != null)
- {
- iLog.Error(messageEntity, exception);
- }
- else
- {
- iLog.Error(messageEntity);
- }
- }
- }
- /// <summary>
- /// 写入Fatal日志,
- /// </summary>
- /// <param name="message">日志信息,占位符为 %Object{Message}</param>
- public void Fatal(string message, Exception exception = null)
- {
- LogMessage messageEntity = new LogMessage
- {
- Message = message
- };
- Fatal(messageEntity, exception);
- }
- /// <summary>
- /// 写入Fatal日志
- /// </summary>
- /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>
- public void Fatal(object messageEntity, Exception exception = null)
- {
- if (iLog.IsFatalEnabled)
- {
- if (exception != null)
- {
- iLog.Fatal(messageEntity, exception);
- }
- else
- {
- iLog.Fatal(messageEntity);
- }
- }
- }
- #endregion
- }
- }
第四步:写一下log模块的支持方法(这里有实现log4net配置和连接字符串共用一个配置的方法)
LogManager.cs
这个类定义的了log4net模块的初始化,数据库连接设置……
- using System;
- using System.IO;
- using log4net.Appender;
- using log4net.Config;
- using log4net.Repository.Hierarchy;
- namespace HY.Log
- {
- public class LogManager
- {
- /// <summary>
- /// 设置DB连接字符串
- /// </summary>
- /// <param name="conString">连接字符串</param>
- /// <param name="loggerName">loggerName</param>
- /// <param name="appenderName">appenderName</param>
- public static void ConfigConnection(string conString, string loggerName, string appenderName = "ADONetAppender")
- {
- try
- {
- Hierarchy h = log4net.LogManager.GetRepository() as Hierarchy;
- if (h != null)
- {
- AdoNetAppender adoAppender = (AdoNetAppender)h.GetLogger(loggerName,
- h.LoggerFactory).GetAppender(appenderName);
- if (adoAppender != null)
- {
- adoAppender.ConnectionString = conString;
- adoAppender.ActivateOptions();
- }
- }
- }
- catch (NullReferenceException) { }
- }
- /// <summary>
- /// 初始化HY.Log, Log配置文件需要写到 Web.config OR App.config
- /// </summary>
- public static void Init()
- {
- XmlConfigurator.Configure();
- }
- /// <summary>
- /// 初始化HY.Log,
- /// </summary>
- /// <param name="configFileName">制定Log配置文件的文件绝对路径</param>
- public static void Init(string configFileName)
- {
- XmlConfigurator.Configure(new FileInfo(configFileName));
- }
- /// <summary>
- /// 检索Logger名称返回日志处理接口
- /// </summary>
- /// <param name="name">Logger名称</param>
- /// <returns>日志接口</returns>
- public static ILog GetLogger(string name)
- {
- var log4Logger = log4net.LogManager.GetLogger(name);
- return new NormalLog(log4Logger);
- }
- }
- }
第五步:如何使用HY.Log.DLL
上面的代码大家看到了,已经可以成功编译一个dll 文件了。
先来编辑一个log4net配置文件
- <?xml version="1.0"?>
- <configuration>
- <!--Log4net Begin-->
- <configSections>
- <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
- </configSections>
- <log4net>
- <!--Log4net Begin,程序运行异常记录-->
- <logger name="LogInfoDB">
- <level value="ALL" />
- <appender-ref ref="ADONetAppender" />
- </logger>
- <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
- <bufferSize value="" />
- <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
- <!--<connectionString value="Data Source=127.0.0.1;Database=test;uid=sa;pwd=test;Max Pool Size=300;Connect Timeout=15;" />-->
- <commandText value="INSERT INTO HY_Log ([LogType],[ModelName],[Message],[Exception],[IP],[Log_Date],[UserID]) VALUES (@LogType,@ModelName, @Message, @Exception, @IP,@Log_Date,@UserID)" />
- <parameter>
- <parameterName value="@LogType" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%Object{LogType}" />
- </layout>
- </parameter>
- <parameter>
- <parameterName value="@ModelName" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%Object{ModelName}" />
- </layout>
- </parameter>
- <parameter>
- <parameterName value="@Message" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%Object{Message}" />
- </layout>
- </parameter>
- <parameter>
- <parameterName value="@Exception" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%Object{Exception}" />
- </layout>
- </parameter>
- <parameter>
- <parameterName value="@IP" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%ClientIP" />
- </layout>
- </parameter>
- <parameter>
- <parameterName value="@Log_Date" />
- <dbType value="DateTime" />
- <layout type="log4net.Layout.RawTimeStampLayout" />
- </parameter>
- <parameter>
- <parameterName value="@UserID" />
- <dbType value="String" />
- <size value="" />
- <layout type="HY.Log.CustomLayout">
- <conversionPattern value="%Object{UserID}" />
- </layout>
- </parameter>
- </appender>
- </log4net>
- <!--Log4net End-->
- </configuration>
- <!--%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
- %n(new line):换行
- %d(datetime):输出当前语句运行的时刻
- %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
- %t(thread id):当前语句所在的线程ID
- %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等
- %c(class):当前日志对象的名称,例如:
- %f(file):输出语句所在的文件名。
- %l(line):输出语句所在的行号。-->
上面的配置文件是一个写入DB的配置
请注意如下配置节:
- <layout type="HY.Log.CustomLayout">
<conversionPattern value="%Object{Exception}" />
<conversionPattern value="%Object{LogType}" />
<conversionPattern value="%ClientIP" />
这便是采用了自定义配置。- 创建HY.ILog对象
public static ILog ilog = null;- HY.Log.LogManager.Init(HttpContext.Current.Server.MapPath(@"~/Config/log4net.config"));//加载配置文件
HY.Log.LogManager.ConfigConnection(ConfigurationManager.ConnectionStrings["Connection"].ToString(), "LogInfoDB");//修改连接字符串
ilog = LogManager.GetLogger("LogInfoText"); //获取Ilog对象 这里可以采用单例模式。代码就不贴了,- 自定义实体类:
- [Serializable]
- public class LogEntity
- {
- /// <summary>
- /// 日志类型
- /// </summary>
- public LogType LogType { get; set; }
- /// <summary>
- /// 模块名称
- /// </summary>
- public string ModelName { get; set; }
- /// <summary>
- /// 信息
- /// </summary>
- public new string Message { get; set; }
- /// <summary>
- /// 异常信息
- /// </summary>
- public string Exception { get; set; }
- public string UserID { get; set; }
- LogEntity loginfo = new LogEntity();
loginfo.ModelName = "ModelName";
loginfo.Message = "Message";
loginfo.Exception = "Exception";
loginfo.UserID = "UserID";
loginfo.LogType = "LogType.Business";
ilog.Error(loginfo,ex);
- 到这里就已经完了。 关于使用的代码比较粗糙,这块就需要根据你程序的具体需求来实现了。这里点到为止。 因为后续我们将会采用AutoFac来注入。 将在后续的文章介绍。
- 各位如果有更好的建立请给我留言, 请各位不吝赐教。
相关文章:
搭建一套自己实用的.net架构(2)【日志模块-log4net】
搭建一套自己实用的.net架构(3)【ORM-Dapper+DapperExtensions】
搭建一套自己实用的.net架构(4)【CodeBuilder-RazorEngine】
原文链接:http://www.cnblogs.com/hy59005271/p/4736885.html
搭建一套自己实用的.net架构(2)【日志模块-log4net】的更多相关文章
- 搭建一套自己实用的.net架构(3)续 【ORM Dapper+DapperExtensions+Lambda】
前言 继之前发的帖子[ORM-Dapper+DapperExtensions],对Dapper的扩展代码也进行了改进,同时加入Dapper 对Lambda表达式的支持. 由于之前缺乏对Lambda的知 ...
- 搭建一套自己实用的.net架构(3)【ORM-Dapper+DapperExtensions】
现在成熟的ORM比比皆是,这里只介绍Dapper的使用(最起码我在使用它,已经运用到项目中,小伙伴们反馈还可以). 优点: 1.开源.轻量.小巧.上手容易. 2.支持的数据库还蛮多的, Mysql,S ...
- 搭建一套自己实用的.net架构(4)【CodeBuilder-RazorEngine】
工欲善其事必先利其器, 下面来说说代码生成器. 现在代码生成器品种繁多各式各样, 什么codesmith.T4. 动软也算.那么每款代码生成器都有自己模板解析引擎. 现在比较流行的 NVelocit ...
- 搭建一套自己实用的.net架构(1)【概述】
入园很久,一直默默的潜水,近来得空想写点什么. 思前想后,那就把自己平时没事干自己摘抄.引用.瞎写的一些东西写出来.帮助自己巩固一下,顺便请高手们指点一二. 我本人很懒 ,一些代码就是直接复制别人的劳 ...
- 基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【六】【引入bootstrap前端框架】
https://blog.csdn.net/linzhefeng89/article/details/78752658 基于springboot+bootstrap+mysql+redis搭建一套完整 ...
- 手把手0基础项目实战(一)——教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)...
原文:手把手0基础项目实战(一)--教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)... 本文你将学到什么? 本文将以原理+实战的方式,首先对& ...
- 搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目
前言 伴随着随着微服务概念的不断盛行,与之对应的各种解决方案也层出不穷.这毕竟是一个信息大爆发的时代,各种编程语言大行其道,各有各的优势.但是有一点未曾改变,那就是他们服务的方式,工作的时候各 ...
- Spring MVC+ Spring + Mybatis从零开始搭建一个精美且实用的管理后台
点击进入<SSM搭建精美实用的管理系统>达人课页面 SSM 框架即 SpringMVC+Spring+Mybatis,相信各位朋友在投递简历时已直观感受到它的重要性,JavaWeb 相关工 ...
- 从原理到代码:大牛教你如何用 TensorFlow 亲手搭建一套图像识别模块 | AI 研习社
从原理到代码:大牛教你如何用 TensorFlow 亲手搭建一套图像识别模块 | AI 研习社 PPT链接: https://pan.baidu.com/s/1i5Jrr1N 视频链接: https: ...
随机推荐
- SpringMVC基本使用
springMVC是一个MVC框架,他控制着请求相应的整个流程,从请求一进入到应用服务器到相应离开,都离不开mvc框架 请求在应用服务器中 先说说请求相应在应用服务器的整个过程 DisptacherS ...
- 常用C#关键字详解教程
很多在学习网站后台的同学都对C#的关键字有些摸不到头脑,现在就和大家一起学习一下这些关键字的含义 类型 Void 用作方法的返回类型时,void 关键字指定方法不返回值. 在方法的参数列表中不允许使用 ...
- Raneto Docs(开源的知识库建站程序)
1.Raneto Docs简单说明 a Raneto是一个基于Markdown的开源的node.js知识库平台,它使用Markdown文件来存储知识库,Raneto我们也可以将其称之为"静态 ...
- OData V4 系列 Action 与 Function
OData 学习目录 了解过WebApi的都知道,WebApi默认方法 Get.Post.Put,如果增加其它过多Post方法即不能识别,还需增加其它配制,请求的Url还需加上Controller及A ...
- 游标的使用——mysql
CREATE DEFINER=`root`@`%` PROCEDURE `split_category_all`()BEGIN declare categ varchar(10); ##套餐列 dec ...
- 原生JS:严格模式详解
严格模式 本文参考MDN做的详细整理,方便大家参考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript) 设计目的 设立”严格模式 ...
- 前端HTML规范
HTML规范 - 整体结构 文件应以“<!DOCTYPE ......>”首行顶格开始,推荐使用“<!DOCTYPE html>”. 必须申明文档的编码charset,且与文件 ...
- 基本排序算法——shell排序java实现
shell排序是对插入排序的一种改进. package basic.sort; import java.util.Arrays; import java.util.Random; public cla ...
- tomcat accesslog日志扩展
由于工作需要,最近对tomcat的日志进行了一些研究,发现其日志大致可以分为两类,一类是运行日志,即平常我们所说的catalina.out日志,由tomcat内部代码调用logger打印出来的:另一类 ...
- C++序列化、反序列化
几个常见的库 http://stackoverflow.com/questions/3637581/fastest-c-serialization Boost: Fast, assorted C++ ...