(二)Apache log4net™ 手册 - 配置

0、引言

在上一篇文章中我们简单介绍了 Log4Net 及其核心的三大组件。本文将在上一篇文章的基础上继续探讨与 Log4Net 配置相关的内容。

1、配置

将日志请求插入到应用程序代码中需要进行大量的计划和工作。观察表明,大约4%的代码专门用于日志记录。因此,即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。考虑到它们的数量,必须管理这些日志语句,而不需要手动修改它们。

log4net 环境是完全可编程配置的。但是,使用配置文件配置 log4net 要灵活得多。目前,配置文件是用 XML 编写的。

让我们在使用 log4net 的虚拟应用程序 MyApp 的帮助下,体验一下如何实现这一点。

using Com.Foo;// 导入 log4net 类。
using log4net;
using log4net.Config;public class MyApp 
{// 定义一个静态 logger 变量,其引用名为 "MyApp" 的 Logger 实例private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));static void Main(string[] args) {// 设置一个简单的配置,在控制台进行日志记录。BasicConfigurator.Configure();log.Info("Entering application.");Bar bar = new Bar();bar.DoIt();log.Info("Exiting application.");}
}

MyApp 首先导入 log4net 相关的类。然后,它定义了一个名为 MyApp 的静态 logger 变量,该变量恰好是类的完全限定名。

MyApp 使用了下面的 Bar 类:

// 导入 log4net 类。
using log4net;namespace Com.Foo
{public class Bar {private static readonly ILog log = LogManager.GetLogger(typeof(Bar));public void DoIt(){log.Debug("Did it again!");}}
}

调用 BasicConfigurator.Configure() 方法创建一个相当简单的 log4net 设置。这个方法被硬编码为向 root logger 中添加一个 ConsoleAppender。输出将使用设置为模式 “%-4timestamp [%thread] %-5level %logger %ndc - %message%newline” 的 PatternLayout 来格式化。

注意,默认情况下,root logger 被分配给 Level.DEBUG

MyApp 的输出为:

0    [main] INFO  MyApp  - Entering application.
36   [main] DEBUG Com.Foo.Bar  - Did it again!
51   [main] INFO  MyApp  - Exiting application.

顺便提一下,在 log4net 中,子 loggers 只链接到它们现有的祖先。特别的,名为 Com.foo.bar 的 logger 直接链接到 root logger,从而绕过了未使用的 Com 或 Com.Foo loggers。这将显著提高性能并减少 log4net 的内存占用。

MyApp 类通过调用 BasicConfigurator.Configure() 方法配置 log4net。其他类只需要导入 log4net 命名空间,检索它们希望使用的 loggers,然后记录日志即可。

前面的示例始终输出相同的日志信息。幸运的是,我们可以很容易地修改 MyApp,以便在运行时控制日志输出。下面一个稍微修改过的版本。

using Com.Foo;// 导入 log4net 类。
using log4net;
using log4net.Config;public class MyApp 
{private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));static void Main(string[] args) {// BasicConfigurator 被 XmlConfigurator 取代。XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));log.Info("Entering application.");Bar bar = new Bar();bar.DoIt();log.Info("Exiting application.");}
}

这个版本的 MyApp 指示 XmlConfigurator 解析配置文件并相应地设置日志记录。配置文件的路径在命令行中指定。

下面是一个示例配置文件,其输出与前面基于 BasicConfigurator 的示例完全相同。

<log4net><!-- A1 被设置为 ConsoleAppender --><appender name="A1" type="log4net.Appender.ConsoleAppender"><!-- A1 使用 PatternLayout --><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" /></layout></appender><!-- 将 root logger 级别设置为 DEBUG,并将其唯一的 appender 设置为 A1 --><root><level value="DEBUG" /><appender-ref ref="A1" /></root>
</log4net>

假设我们不再对查看属于 Com.Foo 包的任何组件的输出感兴趣。下面的配置文件展示了实现这一目标的一种可能方法。

<log4net><!-- A1 被设置为 ConsoleAppender --><appender name="A1" type="log4net.Appender.ConsoleAppender"><!-- A1 使用 PatternLayout --><layout type="log4net.Layout.PatternLayout"><!-- 以 ISO 8601 格式打印日期 --><conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" /></layout></appender><!-- 将 root logger 级别设置为 DEBUG,并将其唯一的 appender 设置为 A1 --><root><level value="DEBUG" /><appender-ref ref="A1" /></root><!-- 只打印 Com.Foo 包中 WARN 或更高级别的消息 --><logger name="Com.Foo"><level value="WARN" /></logger>
</log4net>

使用该文件配置的 MyApp 的输出如下所示。

2000-09-07 14:07:41,508 [main] INFO  MyApp - Entering application.
2000-09-07 14:07:41,529 [main] INFO  MyApp - Exiting application.

由于 logger Com.Foo.Bar 没有指定的级别,因此它从 Com.Foo 处继承其级别,Com.Foo 的级别在配置文件中被设置为 WARN。来自 Bar.DoIt 方法的日志语句的级别是 DEBUG,低于 logger 的级别 WARN。因此,DoIt() 方法的日志请求被抑制。

下面是另一个使用多个 appenders 的配置文件。

<log4net><appender name="Console" type="log4net.Appender.ConsoleAppender"><layout type="log4net.Layout.PatternLayout"><!-- 输出调用者的文件名和行号的模式 --><conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" /></layout></appender><appender name="RollingFile" type="log4net.Appender.RollingFileAppender"><file value="example.log" /><appendToFile value="true" /><maximumFileSize value="100KB" /><maxSizeRollBackups value="2" /><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%level %thread %logger - %message%newline" /></layout></appender><root><level value="DEBUG" /><appender-ref ref="Console" /><appender-ref ref="RollingFile" /></root>
</log4net>

使用此配置文件调用增强的 MyApp 将在控制台上输出以下内容。

 INFO [main] (MyApp.cs:16) - Entering application.
DEBUG [main] (Bar.cs:12) - Doing it again!INFO [main] (MyApp.cs:19) - Exiting application.

此外,由于 root logger 已经分配了第二个 appender,因此输出也将定向到 example.log 文件。该文件将在达到 100KB 时进行滚动覆盖。当滚动覆盖发生时,旧版本的 example.log 会自动移动到 example.log.1。

注意,要获得这些不同的日志记录行为,我们不需要重新编译代码。我们同样可以轻松地将日志记录到电子邮件地址,将所有 Com.Foo 的输出重定向到 NT 事件记录器,或者将日志事件转发到远程 log4net 服务器,该服务器会根据本地服务器策略进行日志记录。

有关使用 XmlConfigurator 配置 Appender 的更多示例,请参阅示例 Appender 配置文档。

2、配置属性

可以使用程序集级别(assembly-level)的属性来配置 log4net,而不是以编程方式指定。

  • XmlConfiguratorAttribute

    log4net.Config.XmlConfiguratorAttribute 允许使用以下的属性配置 XmlConfigurator:

    • ConfigFile

      如果指定了该属性,这是要与 XmlConfigurator 一起使用的配置文件的文件名。该文件路径相对于应用程序基目录(AppDomain.CurrentDomain.BaseDirectory)。

      此属性不能与 ConfigFileExtension 属性一起使用。

    • ConfigFileExtension

      如果指定了该属性,这是配置文件的扩展名。使用程序集文件名作为基本名,然后附加这个扩展名。例如,如果程序集是从 TestApp.exe 文件加载的,并且 ConfigFileExtension 属性设置为 log4net,那么配置文件名就是 TestApp.exe.log4net。这等同于将 ConfigFile 属性设置为 TestApp.exe.log4net。

      配置文件的路径是通过使用应用程序基目录(AppDomain.CurrentDomain.BaseDirectory)、程序集文件名和配置文件扩展名来构建的。

      此属性不能与 ConfigFile 属性一起使用。

    • Watch

      如果指定了该标志并将其设置为 true,则框架将监视配置文件,并在每次修改配置文件时重新加载配置。

    如果没有指定 ConfigFile 或 ConfigFileExtension 属性,则应用程序配置文件(例如 TestApp.exe.config)将被用作 log4net 配置文件。

    使用示例:

    // 使用 .config 文件配置 log4net
    [assembly: log4net.Config.XmlConfigurator(Watch=true)]
    // 这将导致 log4net 在应用程序基目录
    //(即包含 TestApp.exe 的目录)中查找一个
    // 名为 TestApp.exe.config 的配置文件。
    // 该配置文件将被监视以查看更改。
    
    // 使用 .log4net 文件配置 log4net
    [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
    // 这将导致 log4net 在应用程序基目录
    //(即包含 TestApp.exe 的目录)中查找一个
    // 名为 TestApp.exe.log4net 的配置文件。
    // 该配置文件将被监视以查看更改。
    

    每个程序集只能使用此属性一次。

使用属性可以更清晰地定义应用程序的配置将从何处加载。然而,值得注意的是,属性是纯粹被动的。它们只是信息。因此,如果你使用配置属性,你必须调用 log4net 以便它读取属性。一个简单的对 LogManager.GetLogger 的调用将导致读取和处理调用程序集上的属性。因此,在应用程序启动的尽可能早的阶段进行日志记录调用是至关重要的,当然在加载和调用任何外部程序集之前就更是如此。

3、appSettings

如果你使用属性来配置 log4net,则可以使用应用程序配置文件的 appSettings 节的两个设置来覆盖程序集属性中给定的值。

带有 “log4net.Config” 键的设置会覆盖配置文件名(并被认为是相对于您的应用程序的基目录),带有 “log4net.Config.Watch” 键的设置决定是否应监视文件的更改。

即便程序集属性

[assembly: log4net.Config.XmlConfigurator(Watch=false)]

将应用程序配置为使用配置文件 “TestApp.exe.config” 并且不监视它的更改。但您可以通过在应用程序的配置文件中添加

<appSettings><add key="log4net.Config" value="log4net.config"/><add key="log4net.Config.Watch" value="True"/>
</appSettings>

来覆盖此设置,以使用文件 “log4net.config” 并监视它。

4、配置文件

通常使用文件指定 log4net 配置。该文件可以通过以下两种方式读取:

  • 使用 .NET System.Configuration API
  • 直接读取文件内容

4.1、.config 文件

System.Configuration API 只有当配置数据在应用程序的配置文件中才可用;也就是名为 MyApp.exe.configWeb.config 的文件。由于 System.Configuration API 不支持重新加载配置文件,因此无法使用 log4net.Config.XmlConfigurator.ConfigureAndWatch 方法来监视配置设置。使用 System.Configuration API 读取配置数据的主要优点是,它比直接访问配置文件需要的权限更少。

使用 System.Configuration API 配置应用程序的唯一方法是调用 log4net.Config.XmlConfigurator.Configure() 方法或 log4net.Config.XmlConfigurator.Configure(ILoggerRepository) 方法。

为了在 .config 文件中嵌入配置数据,必须使用 configSections 元素将节名称标识给 .NET 配置文件解析器。该节必须指定将用于解析配置节的 log4net.Config.Log4NetConfigurationSectionHandler。这种类型必须完全由程序集限定,因为它是由 .NET 配置文件解析器加载的,而不是由 log4net 加载的。必须指定 log4net 程序集的正确程序集名称。以下是一个简单的配置文件示例,它指定了用于 log4net 节的正确节处理程序。

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /></configSections><log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root></log4net>
</configuration>

在上述示例中,指定了 log4net 程序集。该程序集必须位于 .NET 运行时可以找到的位置。例如,它可以位于与应用程序相同的目录中。如果 log4net 程序集存储在 GAC 中,则必须指定完全限定的程序集名称,包括文化、版本和公钥。

当使用 .config 文件指定配置时,节名和 XML 元素名必须是 log4net。

4.2、直接读取文件

XmlConfigurator 可以直接读取任何 XML 文件并使用它来配置 log4net。这包括应用程序的 .config 文件;也就是名为 MyApp.exe.configWeb.config 的文件。不直接读取配置文件的唯一原因是,如果应用程序没有足够的权限来读取该文件,那么必须使用 .NET 配置 APIs(见上文)来加载配置。

可以使用接受 System.IO.FileInfo 对象的任何 log4net.Config.XmlConfigurator 方法来指定读取配置的文件。因为可以监视文件系统以获取文件更改通知,所以可以使用 ConfigureAndWatch 方法来监视配置文件的修改,并自动重新配置 log4net。

此外,还可以使用 log4net.Config.XmlConfiguratorAttribute 来指定读取配置的文件。

配置是从文件中的 log4net 元素中读取的。文件中只能指定一个 log4net 元素,但它可以位于 XML 层次结构的任何位置。例如,它可以是根元素:

<?xml version="1.0" encoding="utf-8" ?>
<log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root>
</log4net>

或者它可以嵌套在其他元素中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="log4net" type="System.Configuration.IgnoreSectionHandler" /></configSections><log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root></log4net>
</configuration>

上述示例展示了如何将配置数据嵌入到 .config 文件中,即使该文件是由 log4net 直接读取的。一个重要的注意事项是,如果 .NET 配置文件解析器找到了一个没有使用 configSections 元素注册的元素,它将抛出一个异常。因此,在上述示例中,注册了 log4net 节的名称,但指定来处理该节的类型是 System.Configuration.IgnoreSectionHandler。这是一个内置类,表示将采用另一种方法来读取配置节。

5、配置语法

log4net 包含一个解析 XML DOM 的配置读取器,即 log4net.Config.XmlConfigurator。本节定义了配置器接受的语法。

下面是一个有效的 XML 配置示例。根元素必须是 <log4net>。注意,这并不意味着这个元素不能嵌入到另一个 XML 文档中。有关如何在配置文件中嵌入 XmlConfigurator XML 的更多信息,请参见上面的配置文件部分。

<log4net><appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout></appender><root><level value="INFO" /><appender-ref ref="ConsoleAppender" /></root>
</log4net>

<log4net> 元素支持以下属性:

属性描述
debug可选属性。值必须为 true 或者 false。默认值为 false。将此属性设置为 true 以启用此配置的内部 log4net 调试。
update可选属性。值必须为 “Merge”(合并) 或者 “Overwrite”(覆盖)。默认值为 “Merge”。将此属性设置为 “Overwrite”,以便在应用此配置之前重置正在配置的存储库的配置。
threshold可选属性。值必须是在存储库上注册的级别的名称。默认值为 ALL。设置此属性以限制在整个存储库中记录的消息,而不管消息被记录到哪个 logger。

<log4net> 元素支持以下子元素:

元素描述
appender允许 0 个或多个元素。定义一个 appender。
logger允许 0 个或多个元素。定义一个 logger 的配置。
renderer允许 0 个或多个元素。定义一个 object renderer。
root可选元素,最多允许一个。定义 root logger 的配置。
param允许 0 个或多个元素。存储库特定参数。

6、Appenders

Appender 只能被定义为 <log4net> 元素的子元素。每个 Appender 必须具有唯一的名称。必须指定 Appender 的实现类型。

下面这个例子展示了一个类型为 log4net.Appender.ConsoleAppender 的 Appender 被定义。这个 Appender 将被称为 ConsoleAppender。

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" ><layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" /></layout>
</appender>

<appender> 元素支持以下属性:

属性描述
name必要属性。值必须是此 appender 的字符串名称。在此配置文件中定义的所有 appender 中,名称必须是唯一的。logger 的 <appender-ref> 元素使用此名称来引用 appender。
type必要属性。值必须是此 appender 的类型名称。如果 appender 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。

<appender> 元素支持以下子元素:

元素描述
appender-ref允许 0 个或多个元素。允许 appender 引用另外的 appenders。并非所有的 appenders 都支持。
filter允许 0 个或多个元素。定义此 appender 使用的 filters。
layout可选元素,最多允许一个。定义此 appender 使用的 layout。
param允许 0 个或多个元素。appender 特定参数。

有关配置 appender 的示例,请参见示例 Appender 配置文档。

7、Filters

Filters 元素只能定义为 <appender> 元素的子元素

<filter> 元素支持以下属性:

属性描述
type必要属性。值必须是此 filter 的类型名称。如果 filter 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。

<filter> 元素支持以下子元素:

元素描述
param允许 0 个或多个元素。filter 特定参数。

filters 形成了一个事件必须通过的链条。沿途的任何 filter 都可以接受事件并停止(过滤)处理,拒绝事件并停止(过滤)处理,或者允许事件传递到下一个过滤器。如果事件在没有被拒绝的情况下到达过滤器链的末端,那么它将被隐式接受并将被记录。

<filter type="log4net.Filter.LevelRangeFilter"><levelMin value="INFO" /><levelMax value="FATAL" />
</filter>

上面这个过滤器将拒绝那些级别低于 INFO 或高于 FATAL 的事件。所有在 INFO 和 FATAL 之间的事件都将被记录。

如果我们只想让包含特定子字符串(例如 ‘database’)的消息通过,那么我们需要指定以下 filters:

<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="database" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />

第一个过滤器将在事件的消息文本中查找子字符串 ‘database’。如果找到了文本,过滤器将接受消息并停止过滤处理,消息将被记录。如果没有找到子字符串,事件将被传递给下一个过滤器进行处理。如果没有下一个过滤器,事件将被隐式接受并将被记录。但是因为我们不希望记录不匹配的事件,我们需要使用 log4net.Filter.DenyAllFilter,它将拒绝所有到达它的事件。这个过滤器只在过滤器链的末尾有用。

如果我们想允许消息文本中包含 ‘database’ 或 ‘ldap’ 的事件通过,我们可以使用以下 filters:

<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="database"/>
</filter>
<filter type="log4net.Filter.StringMatchFilter"><stringToMatch value="ldap"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />

8、Layouts

Layout 元素只能定义为 <appender> 元素的子元素。

<layout> 元素支持以下属性:

属性描述
type必要属性。值必须是此 layout 的类型名称。如果 layout 没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。

<layout> 元素支持以下子元素:

元素描述
param允许 0 个或多个元素。layout 特定参数。

下例展示了如何配置一个使用 log4net.Layout.PatternLayout 的 layout。

<layout type="log4net.Layout.PatternLayout"><conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>

9、Root Logger

只能定义一个 root logger 元素,它必须是 <log4net> 元素的子元素。root logger 是 logger 层次结构的根。所有的 logger 最终都从这个 logger 继承。

一个 root logger 示例:

<root><level value="INFO" /><appender-ref ref="ConsoleAppender" />
</root>

<root> 元素不支持任何属性。

<root> 元素支持以下子元素:

元素描述
appender-ref允许 0 个或多个元素。允许 logger 通过名称引用 appenders。
level可选元素,最多允许一个。定义此 logger 的日志级别。此 logger 只会接受此级别或以上的事件。
param允许 0 个或多个元素。logger 特定参数。

10、Loggers

Logger 元素只能定义为 <log4net> 元素的子元素。

一个 logger 示例:

<logger name="LoggerName"><level value="DEBUG" /><appender-ref ref="ConsoleAppender" />
</logger>

<logger> 元素支持以下属性:

属性描述
name必要属性。值必须是 logger 的名称。
additivity可选属性。值可以为 true 或者 false。默认值为 true。将此属性设置为 false 以防止此 logger 继承父 loggers 上定义的 appenders。

<logger> 元素支持以下子元素:

元素描述
appender-ref允许 0 个或多个元素。允许 logger 通过名称引用 appenders。
level可选元素,最多允许一个。定义此 logger 的日志级别。此 logger 只会接受此级别或以上的事件。
param允许 0 个或多个元素。logger 特定参数。

11、Renderers

Renderer 元素只能定义为 <log4net> 元素的子元素。

一个 renderer 示例:

<renderer renderingClass="MyClass.MyRenderer" renderedClass="MyClass.MyFunkyObject" />

<renderer> 元素支持以下属性:

属性描述
renderingClass必要属性。值必须是此 renderer 的类型名称。如果该类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。这是将负责渲染 renderedClass 的对象的类型。
renderedClass必要属性。值必须是此 renderer 的目标类型的类型名称。如果该类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。这是此 renderer 将渲染的类型的名称。

<renderer> 元素不支持任何子元素。

12、Parameters

Parameter 元素可以是许多元素的子元素。有关详细信息,请参阅上面的特定元素。

一个 param 示例:

<param name="ConversionPattern" value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />

<param> 元素支持以下属性:

属性描述
name必要属性。值必须是要在父对象上设置的参数的名称。
value可选属性。必须指定 valuetype 属性之一。该属性的值是一个字符串,可以转换为参数的值。
type可选属性。必须指定 valuetype 属性之一。此属性的值是要创建并设置为参数值的类型名称。如果类型没有在 log4net 程序集中定义,那么此类型名称必须是完全程序集限定的。

<param> 元素支持以下子元素:

元素描述
param允许 0 个或多个元素。Parameter 特定参数。

一个使用嵌套 param 元素的 param 示例:

<param name="evaluator" type="log4net.spi.LevelEvaluator"><param name="Threshold" value="WARN"/>
<param>

13、扩展参数

配置参数直接映射到对象上的可写属性。可用的属性取决于正在配置的对象的实际类型。log4net SDK 文档包含了 log4net 程序集中所有组件的 API 参考。

对于第三方组件,请参阅其相关 API 参考以获取可用属性的详细信息。

14、紧凑参数语法

所有参数也可以通过使用参数名称作为元素名称来指定,而不是使用 param 元素和 name 属性。

例如一个 param:

<param name="evaluator" type="log4net.spi.LevelEvaluator"><param name="Threshold" value="WARN"/>
<param>

也可以写成:

<evaluator type="log4net.spi.LevelEvaluator"><threshold value="WARN"/>
<evaluator>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/97580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】信号屏蔽与信号捕捉的原理与实现(附图解与代码)

这一篇的篇幅可能有点长&#xff0c;如果已经了解了以下两个知识点的同学可以自行跳到第三部分——信号屏蔽的实现。 不太了解的同学希望你们能够静下心来看完&#xff0c;相信一定会有不小的收获。那么话不多说&#xff0c;我们这就开始啦&#xff01;&#xff01;&#xff0…

Linux网络存储:NFS

NSF 笔记&#xff1a; NFS是通过网络来进行服务器和客户端之间的数据传输的&#xff0c;我们大家都知道&#xff0c;要想通过网络进行传输&#xff0c;必须得知道是通过哪一个端口进行传输的&#xff01; NFS服务器对于端口的选择是随机的&#xff0c;那么问题在于&#xff0…

代码随想录算法训练营第四十六天 | 518. 零钱兑换 II、377. 组合总和 Ⅳ

518. 零钱兑换 II 视频讲解&#xff1a;动态规划之完全背包&#xff0c;装满背包有多少种方法&#xff1f;组合与排列有讲究&#xff01;| LeetCode&#xff1a;518.零钱兑换II_哔哩哔哩_bilibili 代码随想录 &#xff08;1&#xff09;代码 377. 组合总和 Ⅳ 视频讲解&…

JOSEF约瑟 闭锁继电器 LB-7 YDB-100 100V 50HZ 控制断路器的合闸或跳闸

闭锁继电器LB-7导轨安装名称:闭锁继电器型号:LB-7闭锁继电器额定电压100V功率消耗≤10VA触点容量220V1.5A40W返回系数≥0.8 LB-1A、LB-1D、DB-1、HBYB-102/D YDB-100、HLO、DB-100、LB-7型闭锁继电器 一、用途 LB-7型闭锁继电器(以下简称继电器)用于发电厂及变电所内高压母线…

MySQL报错:Row size too large (> 8126)

问题描述 1118 - Row size too large ( 8126). Changing some columns to TEXT or BLOB or using ROW_FORMATDYNAMIC or ROW_FORMATCOMPRESSED may help. ln current row format, BLOB prefix of 768 bytes is stored inline. 问题分析 InnoDB引擎建表时&#xff0c;如果最大行…

git stash

git stash 是 Git 中一个非常有用的命令&#xff0c;用于临时保存当前工作目录中的修改&#xff0c;以便你可以切换到其他分支或处理其他任务而不丢失你的修改。它的主要用途是&#xff1a; 保存未提交的修改&#xff1a;你可以使用 git stash 命令将未提交的修改&#xff08;包…

【计算机网络】网络编程接口 Socket API 解读(9)

Socket 是网络协议栈暴露给编程人员的 API&#xff0c;相比复杂的计算机网络协议&#xff0c;API 对关键操作和配置数据进行了抽象&#xff0c;简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍&#xff0c;从而更好的理解 socket 编程。…

Electron笔记

基础环境搭建 官网:https://www.electronjs.org/zh/ 这一套笔记根据这套视频而写的 创建项目 方式一: 官网点击GitHub往下拉找到快速入门就能看到下面这几个命令了 git clone https://github.com/electron/electron-quick-start //克隆项目 cd electron-quick-start //…

提取歌曲伴奏?用对软件一键帮你搞定~

相信大家经常想获取某首歌曲的伴奏&#xff0c;但是不知从何下手&#xff0c;今天这篇教程给大家分享一个超神奇软件&#xff0c;一键提取歌曲伴奏&#xff01; 第一步&#xff1a;打开【音分轨】APP&#xff0c;进入首页点击【人声分离】 第二步&#xff1a;选择导入方式&…

Java小技能:利用反射获取整个项目的枚举字典

文章目录 前言I JAVA反射获取所有枚举类1.1 遍历特定目录1.2 todosee also流水线docker 部署前言 需求:提供一个接口返回项目的所有枚举,提供给前端使用。 I JAVA反射获取所有枚举类 1.1 遍历特定目录 遍历特定目录的枚举,返回给前端使用 @GetMapping("findAnyEnum…

SpringBoot 中使用JPA

最近忙里偷闲&#xff0c;想写一点关于JPA的东西&#xff0c;另外也加深下对JPA的理解&#xff0c;才有了此篇博文。 一、JPA JPA &#xff08;Java Persistence API&#xff09;Java持久化API&#xff0c;是一套Sun公司Java官方制定的ORM 规范&#xff08;sun公司并没有实现…

建议收藏!混迹职场多年总结出的8大技巧!

1. 不要吃“哑巴”亏&#xff1a;不管在什么企业&#xff0c;一定要“会说话”&#xff0c;敢于表达自己&#xff0c;但是又兼顾身边人的感受&#xff0c;考虑好自己的言行将会带来的后果。良好的沟通技巧对于在职场中建立良好的人际关系和解决问题至关重要。学会倾听、表达和理…

C/C++ 排序算法总结

1.冒泡排序 https://blog.csdn.net/weixin_49303682/article/details/119365319 1 #include <stdio.h>2 3 #define N 94 5 void print(int a[])6 {7 for(int i 0; i < N; i)8 {9 printf("%d ", a[i]); 10 } 11 printf("…

为什么mac上有的软件删除不掉?

对于Mac用户来说&#xff0c;软件卸载通常是一个相对简单的过程。然而&#xff0c;有时你可能会发现某些软件似乎“顽固不化”&#xff0c;即使按照常规方式尝试卸载&#xff0c;也依然存在于你的电脑上。这到底是为什么呢&#xff1f;本文将探讨这一问题的可能原因。 1.卸载失…

C#制做一个 winform下的表情选择窗口

能力有限&#xff0c;别人可能都是通过其他方式实现的&#xff0c;我这里简单粗暴一些&#xff0c;直接通过点击按钮后弹出个新窗体来实现。 1、先在form1上增加一个toolstrip控件&#xff0c;再增加个toolstripbutton按钮&#xff0c;用来点击后弹出新窗体&#xff0c;如图&a…

【uniapp】小程序开发5:获取openid、获取手机号

一、获取小程序openid 需要配合后端接口获取授权码&#xff08;code&#xff09; 1&#xff09;调用uni.login()方法获取授权code&#xff0c;并把code传给getOpenid //使用uni.login的时候可以在任何接口下使用即可&#xff0c;主要看打印出来的code值和openid let that t…

智能井盖传感器:城市安全卫士

随着城市人口的不断增加和城市基础设施的不断发展&#xff0c;井盖作为城市道路和排水系统的重要组成部分&#xff0c;承担着确保城市安全和便利性的关键角色。然而&#xff0c;井盖在日常使用中常常面临倾斜、水浸和翻转等问题&#xff0c;这些问题可能导致交通阻塞、行人坠井…

小谈设计模式(20)—组合模式

小谈设计模式&#xff08;20&#xff09;—组合模式 专栏介绍专栏地址专栏介绍 组合模式对象类型叶节点组合节点 核心思想应用场景123 结构图结构图分析 Java语言实现首先&#xff0c;我们需要定义一个抽象的组件类 Component&#xff0c;它包含了组合节点和叶节点的公共操作&a…

Windows配置ADB工具

一、目的 在进行嵌入式开发时&#xff0c;我们经常使用ADB工具登录到开发板上进行命令操作&#xff0c;本篇我们介绍如何在windows平台配置ADB环境。 二、实战 1.下载adb工具包​​​​​​​https://developer.android.com/studio/releases/platform-tools?hlzh-cnhttps://d…

任务工单发送失败重试方案设计

需求背景&#xff1a; 该系统为一个工单系统&#xff0c;其中任务工单为该系统中的一个模块&#xff1b;任务工单它是需要周期性调度的一种任务类型&#xff1b;可以按照用户配置的时间周期定时性触发的。由于任务需要发送到对应的工作人员上&#xff0c;所以这里需要先对员工进…