log4net 用户手册


公告:CSDN 博客最新皮肤炫酷黑已经上线! [C#][C#][C#][C#] 我的log4net log4net log4net log4net 使用手册(完善中) 分类: C# 2009-08-11 09:48 5290 人阅读 评论(4) 收藏 举报 1.1.1.1. log4net log4net log4net log4net 简介 log4net 是.Net 下一个非常优秀的开源日志记录组件。log4net 记录日志的功能非常强大。它可以将日志分不同的等级,以不同 的格式,输出到不同的媒介。Java 平台下,它还有一个姐妹组件——log4j。 log4net 的下载地址:http://logging.apache.org/log4net/download.html 2.2.2.2. log4net log4net log4net log4net 的组成 log4net 主要由五部分组成,分别为 Appenders、Filters、Layouts、Loggers 和Object Renders。 2.12.12.12.1 AppendersAppendersAppendersAppenders Appenders 用来定义日志的输出方式。它还可以通过配置 Filters 和Layout 来实现日志的过滤和输出格式。 它的输出方式有: 1.AdoNetAppender 将日志记录到数据库中。可以采用 SQL 和存储过程两种方式。 2.AnsiColorTerminalAppender 将日志高亮输出到 ANSI 终端。 3.AspNetTraceAppender 能用 asp.net 中Trace 的方式查看记录的日志。 4.BufferingForwardingAppender 在输出到子 Appenders 之前先缓存日志事件。 5.ConsoleAppender 将日志输出到应用程序控制台。 6.EventLogAppender 将日志写到 Windows Event Log。 7.FileAppender 将日志输出到文件。 8.ForwardingAppender 发送日志事件到子 Appenders。 9.LocalSyslogAppender 将日志写到 local syslog service (仅用于 UNIX 环境下)。 10. MemoryAppender 将日志存到内存缓冲区。 11. NetSendAppender 将日志输出到 Windows Messenger service.这些日志信息将在用户终端的对话框中显示。 12. OutputDebugStringAppender 将日志输出到 Debuger,如果程序没有 Debuger,就输出到系统 Debuger。如果系 统Debuger 也不可用,将忽略消息。 13. RemoteSyslogAppender 通过 UDP 网络协议将日志写到 Remote syslog service。 14. RemotingAppender 通过.NET Remoting 将日志写到远程接收端。 15. RollingFileAppender 将日志以回滚文件的形式写到文件中。 16. SmtpAppender 将日志写到邮件中。 17. SmtpPickupDirAppender 将消息以文件的方式放入一个目录中,像 IISSMTP agent 这样的 SMTP 代理就可以阅 读或发送它们。 18. TelnetAppender 客户端通过 Telnet 来接受日志事件。 19. TraceAppender 将日志写到.NET trace 系统。 20. UdpAppender 将日志以无连接 UDP 数据报的形式送到远程宿主或用 UdpClient 的形式广播。 2.22.22.22.2 FiltersFiltersFiltersFilters 使用过滤器可以过滤掉 Appender 输出的内容。过滤器有以下几种: 1.DenyAllFilter 阻止所有的日志事件被记录 2.LevelMatchFilter 只有指定等级的日志事件才被记录 3.LevelRangeFilter 日志等级在指定范围内的事件才被记录 4.LoggerMatchFilter Logger 名称匹配,才记录 5.PropertyFilter 消息匹配指定的属性值时才被记录 6.StringMathFilter 消息匹配指定的字符串才被记录 2.32.32.32.3 LayoutsLayoutsLayoutsLayouts Layout 用于控制 Appender 的输出格式,可以使线性的也可以使 XML。一个 Appender 只能有一个 Layout。 最常用的 Layout 应该是用户自定义格式的 PatternLayout,其次是 SimpleLayout 和ExceptionLayout。然后还有 4个Layout, 其中有两个是输出 Xml 的Layout,但是中文会有问题。 ExceptionLayout 需要给 Logger 的方法传入 Exception 对象作为参数才起作用,否则就什么也不输出。输出的时候会包含 Message 和Trace 最后说一下 PatterLayout 的格式化字符串: ConversionConversionConversionConversion PatternPatternPatternPattern NameNameNameName EffectEffectEffectEffect a 等价于 appdomainappdomainappdomainappdomain appdomain 引发日志事件的应用程序域的友好名称。(我在使用中一般是可执行文件的名字。) c 等价于 loggerloggerloggerlogger C 等价于 typetypetypetype class 等价于 typetypetypetype d 等价于 datedatedatedate date 发生日志事件的本地时间。 使用 %utcdate 输出 UTC 时间。date 后面还可 以跟一个日期格式,用大括号括起来。例如:%date{HH:mm:ss,fff}%date{HH:mm:ss,fff}%date{HH:mm:ss,fff}%date{HH:mm:ss,fff}或者 %date{dd%date{dd%date{dd%date{dd MMMMMMMMMMMM yyyyyyyyyyyyyyyy HH:mm:ss,fff}HH:mm:ss,fff}HH:mm:ss,fff}HH:mm:ss,fff}。如果 date 后面什么也不跟,将使用 ISO8601 格式 。 日期格式和.Net 中DateTime 类的 ToString 方法中使用的格式是一样。 另外 log4net 还有 3个自己的格式 Formatter。 它们是 "ABSOLUTE","DATE"和"ISO8601"分别代表 AbsoluteTimeDateFormatterAbsoluteTimeDateFormatterAbsoluteTimeDateFormatterAbsoluteTimeDateFormatter, DateTimeDateFormatter DateTimeDateFormatter DateTimeDateFormatter DateTimeDateFormatter 和Iso8601DateFormatterIso8601DateFormatterIso8601DateFormatterIso8601DateFormatter。例如: %date{ISO8601}%date{ISO8601}%date{ISO8601}%date{ISO8601}或%date{ABSOLUTE}%date{ABSOLUTE}%date{ABSOLUTE}%date{ABSOLUTE}。 它们的性能要好于 ToString。 exception 异常信息 日志事件中必须存了一个异常对象,如果日志事件不包含没有异常对象,将什么也不输出。异常输出完毕后会 跟一个换行。一般会在输出异常前加一个换行,并将异常放在最后。 F 等价于 filefilefilefile file 发生日志请求的源代码文件的名字。 警告:只在调试的时候有效。调用本地信息会影响性能。 identity 当前活动用户的名字(Principal.Identity.Name). 警告:会影响性能。(我测试的时候%identity 返回都是空的。) l 等价于 locationlocationlocationlocation L 等价于 linelinelineline location 引发日志事件的方法(包括命名空间和类名),以及所在的源文件和行号。 警告:会影响性能。没有 pdb 文件的话,只有方法名,没有源文件名和行号。 level 日志事件等级 line 引发日志事件的行号 警告:会影响性能。 logger 记录日志事件的 Logger 对象的名字。 可以使用精度说明符控制 Logger 的名字的输出层级,默认输出全名。 注意,精度符的控制是从右开始的。例如:logger 名为 "a.b.c", 输出模型为 %logger{2}%logger{2}%logger{2}%logger{2} ,将输出"b.c"。 m 等价于 messagemessagemessagemessage M 等价于 methodmethodmethodmethod message 由应用程序提供给日志事件的消息。 mdc MDC(旧为:ThreadContext.Properties) 现在是事件属性的一部分。 保留它是为了兼容性,它等价于 propertypropertypropertyproperty。 method 发生日志请求的方法名(只有方法名而已)。 警告:会影响性能。 n 等价于 newlinenewlinenewlinenewline newline 换行符 ndc NDC(nested diagnostic context) p 等价于 levellevellevellevel P 等价于 propertypropertypropertyproperty properties 等价于 propertypropertypropertyproperty property 输出事件的特殊属性。例如: %property{user}%property{user}%property{user}%property{user} 输出 user 属性。属性是由 loggers 或appenders 添加到时间 中的。 有一个默认的属性"log4net:HostName"总是会有。 %property %property %property %property 将输出所以的属性 。 (我除了知道可以用它获得主机名外,还不知道怎么用。) 关于调用本地信息(caller location information)的说明: %type %file %line %method %location %class %C%F%L%l %M 都会调用本地信息。这样做会影响性能。本地信息使用 System.Diagnostics.StackTrace 得到。.Net 1.0 不支持 System.Diagnostics.StackTrace 类。 本地信息在调试模式下可以正常获取,在非调试模式下可能获取不到,或只能获取一部分。(根据我的测试,其实是需要有一 个程序数据库(.pdb)文件。) %property 这个东西中的属性好像是要用代码来设置(除了默认属性 log4net:HostName)。 转义字符的修饰符: r 等价于 timestamptimestamptimestamptimestamp t 等价于 threadthreadthreadthread timestamp 从程序启动到事件发生所经过的毫秒数。 thread 引发日志事件的线程,如果没有线程名就使用线程号。 type 引发日志请求的类的全名。. 可以使用精度控制符。例如: 类名是 "log4net.Layout.PatternLayout", 格式模型是 %type{1}%type{1}%type{1}%type{1} 将输出 "PatternLayout"。(也是从右开始的。) 警告:会影响性能。 u 等价于 identityidentityidentityidentity username 当前用户的 WindowsIdentity。(类似:HostName/Username) 警告:会影响性能。 utcdate 发生日志事件的 UTC 时间。后面还可以跟一个日期格式,用大括号括起 来。例如:%utcdate{HH:mm:ss,fff}%utcdate{HH:mm:ss,fff}%utcdate{HH:mm:ss,fff}%utcdate{HH:mm:ss,fff}或者%utcdate{dd%utcdate{dd%utcdate{dd%utcdate{dd MMMMMMMMMMMM yyyyyyyyyyyyyyyy HH:mm:ss,fff}HH:mm:ss,fff}HH:mm:ss,fff}HH:mm:ss,fff}。如果 utcdate 后面什 么也不跟,将使用 ISO8601 格式 。 日期格式和.Net 中DateTime 类的 ToString 方法中使用的格式是一样。 另外 log4net 还有 3个自己的格式 Formatter。 它们是 "ABSOLUTE","DATE"和"ISO8601"分别代表 AbsoluteTimeDateFormatterAbsoluteTimeDateFormatterAbsoluteTimeDateFormatterAbsoluteTimeDateFormatter, DateTimeDateFormatter DateTimeDateFormatter DateTimeDateFormatter DateTimeDateFormatter 和Iso8601DateFormatterIso8601DateFormatterIso8601DateFormatterIso8601DateFormatter。例如: %date{ISO8601}%date{ISO8601}%date{ISO8601}%date{ISO8601}或%date{ABSOLUTE}%date{ABSOLUTE}%date{ABSOLUTE}%date{ABSOLUTE}。 它们的性能要好于 ToString。 w 等价于 usernameusernameusernameusername x 等价于 ndcndcndcndc X 等价于 mdcmdcmdcmdc %%%输出一个百分号 FormatFormatFormatFormat modifiermodifiermodifiermodifier leftleftleftleft justifyjustifyjustifyjustify minimumminimumminimumminimum widthwidthwidthwidth maximummaximummaximummaximum widthwidthwidthwidth commentcommentcommentcomment 2.42.42.42.4 LoggersLoggersLoggersLoggers Logger 是直接和应用程序交互的组件。Logger 只是产生日志,然后由它引用的 Appender 记录到指定的媒介,并由 Layout 控 制输出格式。 Logger 提供了多种方式来记录一个日志消息,也可以有多个 Logger 同时存在。每个实例化的 Logger 对象对被 log4net 作为命 名实体(Named Entity)来维护。log4net 使用继承体系,也就是说假如存在两个 Logger,名字分别为 a.b.c 和a.b。那么 a.b 就是 a.b.c 的祖先。每个 Logger 都继承了它祖先的属性。 下面说一下日志的等级,它们由高到底分别为: OFFOFFOFFOFF >>>> FATALFATALFATALFATAL >>>> ERRORERRORERRORERROR >>>> WARNWARNWARNWARN >>>> INFOINFOINFOINFO >>>> DEBUGDEBUGDEBUGDEBUG >>>> ALLALLALLALL 其中 OFF 表示停用所以日志记录,ALL 表示所有日志都可以记录。 Logger 实现的 ILog 接口,ILog 定义了 5个方法(Debug,Inof,Warn,Error,Fatal)分别对不同的日志等级记录日志。这 5个方法 还有 5个重载。我们以 Debug 为例说明一下,其它的和它差不多。 ILog 中对 Debug 方法的定义如下: void Debug(object message); void Debug(object message, Exception ex); 还有一个布尔属性: bool IsDebugEnabled { get; } 如果使用 Debug(object message, Exception ex),则无论 Layout 中是否定义了%exception,默认配置下日志都会输出 Exception。包括 Exception 的Message 和Trace。如果使用 Debug(object message),则无论如何日志是不会输出 Exception 的,因为没有啊。 最后还要说一个 LogManager 类,它用来管理所应得 Logger。它的 GetLogger 静态方法,可以获得配置文件中相应的 Logger: log4net.ILog log = log4net.LogManager.GetLogger("logger-name"); %20logger false 20 none 如果 logger 名不足 20 个字符,就在左边补空格。 %-20logger true 20 none 如果 logger 名不足 20 个字符,就在右边补空格。 %.30logger NA none 30 超过 30 个字符将截断。 %20.30logger false 20 30 logger 名要在 20 到30 之间,少了在左边补空格,多了截断。 %-20.30logger true 20 30 logger 名要在 20 到30 之间,少了在右边补空格,多了截断。 2.52.52.52.5 ObjectObjectObjectObject RendersRendersRendersRenders 我对 Object Renders 的理解是这样的。它将告诉 logger 如何把一个对象转化为一个字符串记录到日志里。(你可能注意到了,ILog 中定义的接口接收的参数是 Object,而不是 String。) 例如你想把 Orange 对象记录到日志中,但此时 logger 只会调用 Orange 默认的 ToString 方法而已。所以要定义一个 OrangeRender 类实现 log4net.ObjectRender.IObjectRender 接口,然后注册它。这时 logger 就会知道如何把 Orange 记录到 日志中了。 不过我没有测试过,具体怎么做还是看文档吧。 2.62.62.62.6 RepositoryRepositoryRepositoryRepository Repository 主要用于日志对象组织结构的维护。如果你不想自己扩展 log4Net 的话,可以用不找它。但我还是觉得应该提一下。 3.3.3.3. 在程序中使用 log4netlog4netlog4netlog4net 在使用 log4net 前要先做一些配置的工作。配置工作可以在配置文件中完成也可以再程序中用代码完成。我们主要讲在配置文件 中如何配置 log4net,因为这样更方便灵活,而且还不用重新编译代码。至于如何使用代码进行配置,请查看文档和后面参考中 的连接。 3.13.13.13.1 定义配置文件 log4net 的配置可以放在应用程序的默认配置文件中(app.config 或web.config),也可以再你自己的配置文件中。 如果用 Visual Studio 来编辑配置文件,它对 log4net 的标签是不会智能提示和自动补全的。当然也不是不可能,看这里: http://www.cnblogs.com/didasoft/archive/2007/07/23/log4net_xsd.html 这里要感谢 Jerry 同学,为我们提供的 xsd schema。 废话少说,先看一个完整的配置文件的例子:
name="testApp.Logging">name="testApp.Logging">name="testApp.Logging"> type="log4net.Layout.PatternLayout">type="log4net.Layout.PatternLayout">type="log4net.Layout.PatternLayout"> type="log4net.Filter.LevelRangeFilter">type="log4net.Filter.LevelRangeFilter">type="log4net.Filter.LevelRangeFilter"> type="log4net.Layout.PatternLayout">type="log4net.Layout.PatternLayout">type="log4net.Layout.PatternLayout"> 如果 log4net 的配置不是放在应用程序的配置文件里,而是在自己定义的文件里,节点里的
节点是不 需要的。 下面对其中的标签元素做一下说明。 3.1.13.1.13.1.13.1.1 所有的配置都要在元素里定义。 支持的属性: 支持的子元素: 3.1.23.1.23.1.23.1.2 实际上就是一个根 logger,所有其它 logger 都默认继承它。root 元素没有属性。 支持的子元素: 3.1.33.1.33.1.33.1.3 支持的属性: 支持的子元素: debug 可选,取值是 true 或false,默认是 false。设置为 true,开启 log4net 的内部调试。 update 可选,取值是 Merge(合并)或Overwrite(覆盖),默认值是 Merge。设置为 Overwrite,在提交配置的时候 会重置已经配置过的库。 threshold 可选,取值是 repository(库)中注册的 level,默认值是 ALL。 appender 0或多个 logger 0或多个 renderer 0或多个 root 最多一个 param 0或多个 appender-ref 0个或多个,要引用的 appender 的名字。 level 最多一个。 只有在这个级别或之上的事件才会被记录。 param 0个或多个, 设置一些参数。 name 必须的,logger 的名称 additivity 可选,取值是 true 或false,默认值是 true。设置为 false 时将阻止父 logger 中的 appender。 appender-ref 0个或多个,要引用的 appender 的名字。 level 最多一个。 只有在这个级别或之上的事件才会被记录。 param 0个或多个, 设置一些参数。 3.1.43.1.43.1.43.1.4 定义日志的输出方式,只能作为 log4net 的子元素。name 属性必须唯一,type 属性必须指定。 支持的属性: 支持的子元素: 实际上所能包含的子元素远不止上面 4个。 3.1.53.1.53.1.53.1.5 布局,只能作为的子元素。 支持的属性: 支持的子元素: 3.1.63.1.63.1.63.1.6 过滤器,只能作为的子元素。 支持的属性: 支持的子元素: 3.1.73.1.73.1.73.1.7 元素可以是如何元素的子元素。 支持的属性: name 必须的,Appender 对象的名称 type 必须的,Appender 对象的输出类型 appender-ref 0个或多个,允许此 appender 引用其他 appender,并不是所以 appender 类型都支持。 filter 0个或多个,定义此 app 使用的过滤器。 layout 最多一个。定义 appender 使用的输出格式。 param 0个或多个, 设置 Appender 类中对应的属性的值。 type 必须的,Layout 的类型 param 0个或多个, 设置一些参数。 type 必须的,Filter 的类型 param 0个或多个, 设置一些参数。 name 必须的,取值是父对象的参数名。 支持的子元素: 3.23.23.23.2 使用配置文件 3.2.13.2.13.2.13.2.1 关联配置文件 log4net 默认关联的是应用程序的配置文件(AppName.exe.config),可以使用程序集自定义属性来进行设置。下面来介绍一下这 个自定义属性:log4net.Config.XmlConifguratorAttribute。 XmlConfiguratorAttribute 有3个属性: • ConfigFileConfigFileConfigFileConfigFile 配置文件的名字,文件路径相对于应用程序目录(AppDomain.CurrentDomain.BaseDirectory)。ConfigFile 属性不能和 ConfigFileExtension 属性一起使用。 • ConfigFileExtensionConfigFileExtensionConfigFileExtensionConfigFileExtension 配置文件的扩展名,文件路径相对于应用程序的目录。ConfigFileExtension 属性不能和 ConfigFile 属性一起使用。 • WatchWatchWatchWatch 如果将 Watch 属性设置为 true,就会监视配置文件。当配置文件发生变化的时候,就会重新加载。 如果 ConfigFile 和ConfigFileExtension 都没有设置,则使用应用程序的配置文件(AppName.exe.config)。 举例: 1.[assembly: log4net.config.XmlConfigurator(Watch=true)] 2.//监视默认的配置文件,AppName.exe.config 3. 4.[assembly: log4net.config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)] 5.//监视配置文件,AppName.exe.log4net 6. 7.[assembly: log4net.config.XmlConfigurator(ConfigFile="log4net.config")] 8.//使用配置文件 log4net.config,不监视改变。 3.2.23.2.23.2.23.2.2 获取日志对象 log4net.ILog logger = log4net.LogManager.GetLogger("LoggerName"); LogManager 还有其他多个方法,比如检查指定日志是否存在,返回所以日志对象等等。 value 可选的,value 和type 中,必须有一个属性被指定。value 是一个能被转化为参数值的字符串。 type 可选的,value 和type 中,必须有一个属性被指定。type 是一个类型名,如果 type 不是在 log4net 程序 集中定义的,就需要使用全名。 param 0个或多个, 设置一些参数。 特别的,如果日志名在配置文件中不存在,GetLogger 方法会创建一个日志对象,它会继承它的父类的属性。例如"x.y.z"会继承 "x.y"的属性,如果没有"x.y"就继承"x"的属性,如果连"x"也没有,会继承 root 的属性。 3.2.33.2.33.2.33.2.3 使用日志对象 获取日志对象后,使用它是很简单的,只要调用对应的 Debug, Info 等方法就可以了。不过有一件事要说一下,我们以 Debug 为例。 if (log.isDebugEnabled) {log.Debug(...)} 文档上是这么说的“如果 Debug 功能不被使用,就不会有参数构造上的开销。但是,另一方面,如果 logger 的Debug 功能被起 用,就会有俩倍的开销用于评估 logger 是否被起用:一次是判断 debugEnabled,一次是判断 debug 是否被启用。但这不是极 重的负担,因为评估 logger 的时间只有整个 log 语句执行时间的 1%。” 也就是说 Debug 方法会先判断 Debug 是否启用,再记录日志。使用 isDebugEnabled,是否会带来性能提升,是要看情况的。 3.33.33.33.3 一些配置的例子 配置文件的结构可以参照 3.1 节,这里只给出部分元素的使用实例。 3.3.13.3.13.3.13.3.1 1) 日志等级过滤器 其中,日志等级 WARN,FATAL 必须大写。 2) 字符串过滤器 上面的例子,只输出日志信息中包含字符串"Warn"或"Error"的才输出。最后的 DenyAllFilter 会阻止所有的日志信息。 过滤器还有一个 AcceptOnMatch 属性,默认为 true,表示匹配的时候提交日志事件。设置成 false 的时候,不同类型的过滤器 是不一样的。StringMatchFilter 会不提交日志事件,造成匹配的日志信息不被输出。 StringMatchFilter 还有一个 RegexToMatch 属性,用来设置正则表达式。 3.3.23.3.23.3.23.3.2 1) AdoNetAppenderAdoNetAppenderAdoNetAppenderAdoNetAppender 将日志写入到 Sql Server 数据库 数据库表的 Create 语句: CREATETABLE[dbo].[Log] ( [Id] [int] IDENTITY(1, 1) NOTNULL, [Date] [datetime] NOTNULL, [Thread] [varchar] (255) NOTNULL, [Level] [varchar] (50) NOTNULL, [Logger] [varchar] (255) NOTNULL, [Message] [varchar] (4000) NOTNULL, [Exception] [varchar] (2000) NULL ) 配置文件: 我经过测试,使用元素,和元素都可以,还可以混合使用。对于等元素,log4net 的文档上 并没有说,但文档的例子中却在用。我个人感觉很多类属性都可以做标签用,并不限于文档中说的那几个。 上面只是 Sql Server 的配置,其他数据库见文档:http://logging.apache.org/log4net/release/config-examples.html 2) ConsoleConsoleConsoleConsole 输出到控制台 target 默认是输出到标准输出流的(Console.out),这里输出到标准错误输出流(Console.Error)。 3) ColoredConsoleAppenderColoredConsoleAppenderColoredConsoleAppenderColoredConsoleAppender 高亮输出到控制台 上例中,高于等于 ERROR 的日志都会用指定的前景色和背景色显示。也可以有多个 4) FileAppenderFileAppenderFileAppenderFileAppender 输出到文件 上面是一个复杂的 FileAppender,其实除了 File 属性,其他的属性都是可选的。这个属性值可以使用系统的环境变量,上面就 用到了系统的临时文件夹${Tmp}。也可以像 layout 的Header 属性那样使用转义字符串,像这样: 注意文件名要符合操作系统的命名规范。 layout 的Footer 属性,因为没有将 type 设置为 PatternString,所以不能使用转义字符串。所以要想换行就只有用 xml 实 体了 , 表示换行回车/n/r。layout 的Header 和Footer 在很多 Appender 中是没有用的,比如 ConsoleAppender 和 AdoAppender。 FileAppender 的AppendToFile 表示日志写入文件的方式是追加还是覆盖,默认是 true,追加。Encoding 用来设置文件编码, 不知道问什么我测试的时候,好像不起作用。lockingModel 没搞懂,大概是多进程操做同一个日志文件的时候用的吧。 5) RollingFileAppenderRollingFileAppenderRollingFileAppenderRollingFileAppender 输出到可滚动的文件 RollingFileAppender 继承自 FileAppender,FileAppender 的属性,它都可以用。一个简单的例子: 上例中,如果 log.txt 的文件大小超过 100KB,就会把 log.txt 做备份,备份文件名为 log.txt.1,log.txt.2……。但是备份文件的最 大数是 10 个。 说明: a. 本文中使用的 log4net 版本是 1.2.10。
还剩14页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

cm74

贡献于2016-01-25

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf