(一)Apache log4net™ 手册 - 介绍
0、相关概念
- Log4j
-
几乎每个大型应用程序都包含自己的日志记录或跟踪 API。根据这一规则,E.U. SEMPER 🌹项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作,API 已经发展成为 log4j —— 一个流行的 Java 日志包。该软件包是在 Apache 软件许可证下发布的,这是一个由开源 🌹倡议组织认证的成熟的开源许可证。最新的 log4j 版本,包括完整的源代码、类文件和文档,可以在 https://logging.apache.org/log4j/2.x/index.html 🌹上找到。
在代码中插入日志语句是一种低技术含量的调试方法。这也可能是唯一的方法,因为调试器并不总是可用或适用的。这通常是多线程应用程序和分布式应用程序所要面临的情况。
经验表明,日志记录是开发周期的一个重要组成部分。它有几个优点。它提供了关于应用程序运行的精确上下文。一旦插入到代码中,日志输出的生成就不需要人工干预。此外,日志输出可以保存在持久介质中,以供以后研究。除了在开发周期中使用之外,一个功能足够丰富的日志包还可以被视为一个审计工具。
正如 Brian W. Kernighan 和 Rob Pike 在他们真正优秀的书《The Practice of Programming》中所说的那样:
作为个人选择,除了获取堆栈跟踪或一两个变量的值之外,我们倾向于不使用调试器。一个原因是它很容易迷失在复杂的数据结构和控制流的细节中;我们发现,与努力思考并在关键位置添加输出语句和自检代码相比,逐步执行程序的效率更低。点击语句比扫描精心放置的显示的输出要花更长的时间。决定在哪里放置
print语句比单步到达代码的关键部分花费更少的时间,即便假设我们知道关键部分在哪里。更重要的是,调试语句留在程序中;调试会话是短暂的。日志记录确实有其缺点。它会降低应用程序的运行速度。如果过于冗长,可能会导致滚动失明[1]。为了减轻这些担忧,log4j 被设计成可靠、快速和可扩展的。由于日志记录很少是应用程序的主要关注点,因此 log4j API 力求易于理解和使用。
Log4j 2 -
Log4j 1.x 已被广泛采用并在许多应用程序中使用。然而,经过多年发展它的速度已经慢下来了。由于需要兼容非常旧的 Java 版本,它变得更加难以维护,并最终在 2015 年 8 月到达了其生命周期尽头 🌹。它的替代方案,SLF4J/Logback 对框架进行了许多必要的改进。
Apache Log4j 2 是 Log4j 的升级版,相对于其前身 Log4j 1.x 提供了重大改进。它提供了 Logback 中可用的许多改进,同时修复了 Logback 架构中的一些固有问题。
Log4Net - Apache log4net 库是一个帮助程序员将日志语句输出到各种输出目标的工具。log4net 是优秀的 Apache log4j™ 框架到 Microsoft® .NET 运行时的一个移植。log4net 保持了框架在精神上与最初的 log4j 相似,同时利用了 .NET 运行时的新特性。有关 log4net 的更多信息,请参阅 特性文档。 Apache log4net 项目
- log4net 是 Apache 软件基金会的 Apache 日志服务项目的一部分。Logging Services 项目旨在为应用程序调试和审计提供跨语言的日志服务。 Why Log
-
有些同学可能会对名称中出现的数字 “
4” 感到疑惑,但如果你尝试使用英文念出 Log4j 或者 Log4Net 的名称后,相信这个问题就会迎刃而解了。没错,名称中的 “
4” 代表英文单词 "for",因为 “4” 的英文单词 "four" 与 "for" 发音类似。所以,"Log4j" 的含义就是 "Log for Java", 意思是这是一个为 Java 提供日志服务的工具。这是一种常见的命名方式,通过数字 “
4” 来代替 "for", 使得名称更加简洁,也增加了一些趣味性。此外,还有其他的类似命名方式,比如使用 “2” 来代替 "to"。它们都在许多场合内大量使用着。
4? 1、框架
Log4Net 可用于多个框架。对于每个支持的框架,都构建了一个针对该框架的程序集:
- .NET Standard 1.3 via .NET Core 1.0
- Microsoft® .NET Framework 1.0
- Microsoft .NET Framework 1.1
- Microsoft .NET Framework 2.0
- Microsoft .NET Framework 3.5
- Microsoft .NET Framework 4.0
- Microsoft .NET Framework 4.5
- Microsoft .NET Framework 3.5 Client Profile
- Microsoft .NET Framework 4.0 Client Profile
- Microsoft .NET Compact Framework 1.0
- Microsoft .NET Compact Framework 2.0
- Mono 1.0
- Mono 2.0
- Mono 3.5
- Mono 4.0
- Microsoft Shared Source CLI 1.0
- CLI 1.0 Compatible
并不是所有的框架都是平等的,一些特性被排除在一些构建(的程序集)之外。有关更多信息,请参阅框架支持文档。
2、Loggers 与 Appenders
Log4Net 有三个主要的组件:loggers, appenders 与 layouts。这三种类型的组件协同工作使得开发者能够根据消息类型和级别记录日志消息,并在运行时控制这些消息的格式和报告位置。这些组件由控制着 appender 和(将对象转换为字符串的)object renderers 的动作的 filters 辅助。
3、Logger 层次结构
与普通的 System.Console.WriteLine 相比,任何日志 API 的首要优势在于它能够禁用某些日志语句,同时允许其他日志语句不受阻碍地打印。此功能假设日志空间,即所有可能的日志语句的空间,是根据开发人员选择的一些标准进行分类的。
Loggers 是命名实体。Loggers 名称区分大小写,并遵循以下分层命名规则:
- 层次结构命名
-
如果一个 logger 名称后跟一个点是后代 logger 名称的前缀,则该 logger 被称为另一个 logger 的祖先。如果在其自身和后代 logger 之间没有祖先,则称其为子 logger 的父 logger。
层次结构的工作方式与 .NET 中的命名空间和类层次结构非常相似。这是非常方便的,我们很快就会看到。
例如:名为 “Foo.Bar” 的 logger 是名为 “Foo.Bar.Baz” 的 logger 的父级。
类似的,“System” 是 “System.Text” 的父级以及 “System.Text.StringBuilder” 的祖先。大多数开发人员应该熟悉这套命名方案。
root logger 位于 logger 层次结构的顶层。它主要有三点不同:
- 它总是存在的
- 它不能按名称检索
- 它总是有一个指定的级别
使用 log4net.LogManager 类的静态方法以检索 loggers。GetLogger 方法将所需 logger 的名称作为参数。如下列所示:
namespace log4net
{public class LogManager{public static ILog GetLogger(string name);public static ILog GetLogger(Type type);}
}
接收 Type 参数的 GetLogger 方法使用完全限定类型名作为要检索的 logger 名称。
这些 GetLogger 方法返回一个 ILog 接口。这是传递给开发人员的 Logger 的表现形式。ILog 接口定义如下:
namespace log4net
{public interface ILog{/* Test if a level is enabled for logging */bool IsDebugEnabled { get; }bool IsInfoEnabled { get; }bool IsWarnEnabled { get; }bool IsErrorEnabled { get; }bool IsFatalEnabled { get; }/* Log a message object */void Debug(object message);void Info(object message);void Warn(object message);void Error(object message);void Fatal(object message);/* Log a message object and exception */void Debug(object message, Exception t);void Info(object message, Exception t);void Warn(object message, Exception t);void Error(object message, Exception t);void Fatal(object message, Exception t);/* Log a message string using the System.String.Format syntax */void DebugFormat(string format, params object[] args);void InfoFormat(string format, params object[] args);void WarnFormat(string format, params object[] args);void ErrorFormat(string format, params object[] args);void FatalFormat(string format, params object[] args);/* Log a message string using the System.String.Format syntax */void DebugFormat(IFormatProvider provider, string format, params object[] args);void InfoFormat(IFormatProvider provider, string format, params object[] args);void WarnFormat(IFormatProvider provider, string format, params object[] args);void ErrorFormat(IFormatProvider provider, string format, params object[] args);void FatalFormat(IFormatProvider provider, string format, params object[] args);}
}
loggers 也许 被分配了级别。级别是 log4net.Core.Level 类的实例。以下级别按优先级的先后顺序定义:
- ALL
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
- OFF
如果给定的 logger 没有被分配级别,那么它将从具有指定级别的最接近的祖先处继承一个级别。更正式地:
- 级别继承
- 给定 logger X 的继承级别等于 logger 层次结构中的第一个非空级别,从 X 开始,在层次结构中向上进行,直至
rootlogger。
为了确保所有的 logger 最终都可以继承一个级别,root logger 总是有一个分配的级别。其默认值是 DEBUG。
下面是四个表,其中包含各种分配的级别值和根据上述规则继承级别结果。
| Logger 名称 | 分配的级别 | 继承的级别 |
|---|---|---|
| root | Proot | Proot |
| X | none | Proot |
| X.Y | none | Proot |
| X.Y.Z | none | Proot |
上例一中,只有 root logger 被分配了级别。该级别值,即 Proot,由其他 logger X、X.Y、X.Y.Z 继承。
| Logger 名称 | 分配的级别 | 继承的级别 |
|---|---|---|
| root | Proot | Proot |
| X | Px | Px |
| X.Y | Pxy | Pxy |
| X.Y.Z | Pxyz | Pxyz |
上例二中,所有的 logger 都有分配的级别值。所以不需要级别继承
| Logger 名称 | 分配的级别 | 继承的级别 |
|---|---|---|
| root | Proot | Proot |
| X | Px | Px |
| X.Y | none | Px |
| X.Y.Z | Pxyz | Pxyz |
上例三中,root、X 以及 X.Y.Z logger 分别被分配为级别 Proot、Px 以及 Pxyz。logger X.Y 从其父级 X 处继承其级别值。
| Logger 名称 | 分配的级别 | 继承的级别 |
|---|---|---|
| root | Proot | Proot |
| X | Px | Px |
| X.Y | none | Px |
| X.Y.Z | none | Px |
上例四中,root 以及 X logger 分别被分配为级别 Proot 以及 Px。logger X.Y 以及 X.Y.Z 从最近的具有指定级别的父级 X 处继承其级别值。
日志记录请求是(通过 log4net.ILog)调用 logger 实例的一个打印方法发出的。这些打印方法是 Debug、Info、Warn、Error 和 Fatal。
根据定义,打印方法确定日志记录请求的级别。例如:如果 log 是一个 logger 实例,则语句 log.Info("..") 是一个级别为 INFO 的日志请求。
如果日志记录请求的级别高于或等于其 logger 的级别,则说该日志记录请求已启用。否则,请求将被禁用。没有指定级别的 logger 将从层次结构中继承一个级别。这条规则总结如下:
- 基本选择规则
- 如果 L ≥ K,则启用级别为 K(指定的或继承的,视情况而定)的 logger 中的级别为 L 的日志请求。
这条规则是 log4net 的核心。它假设级别是有序的。对于标准级别,我们有 DEBUG < INFO < WARN < ERROR < FATAL。
使用相同的名称调用 log4net.LogManager.GetLogger 方法将始终返回对完全相同的 logger 对象的引用。
例如,在
ILog x = LogManager.GetLogger("wombat");
ILog y = LogManager.GetLogger("wombat");
中,x 和 y 引用完全相同的 logger 对象。
因此,这使得配置一个 logger 并随后在不传递引用的前提下在代码中的另外一个地方检索相同的实例成为可能。log4net logger 可以按任何顺序进行创建和配置,这与生物学上的亲子关系(父母总是先于孩子)存在根本矛盾。特别是,“parent” logger 将找到并链接到它的后代,即使它是在它们之后实例化的。
log4net 环境的配置通常在应用程序初始化时完成。首选的方法是读取配置文件。稍后将讨论这种方法。
通过软件组件,log4net 使得 loggers 命名变得非常容易。这可以通过在每个类中静态实例化一个 logger 来实现,logger 的名称等于类的完全限定名称。这是定义 logger 的一种有用且直接的方法。由于日志输出带有生成 logger 的名称,因此这种命名策略可以很容易地识别日志消息的来源。然而,这只是命名 loggers 的一种可能的策略,尽管很常见。log4net 不限制可能的 loggers 集合。开发人员可根据需要自由地命名 loggers。
尽管如此,以 logger 所在的类命名 logger 似乎是迄今为止已知的最佳策略。对于开发人员来说,要明确每个日志消息的来源很简单。最重要的是,它利用应用程序的设计来生成 logger 层次结构的设计。希望应用程序的设计中已经考虑了一些问题。
4、Appenders
基于 logger 选择性地启用或禁用日志记录请求的能力只是其中的一部分。Log4Net 允许日志请求打印到多个目的地。在 Log4Net 中,输出目的地被称为 appender。Appenders 必须实现 log4net.Appenders.IAppender 接口。
在 Log4Net 包中定义了以下 appenders:
| 类型 | 描述 |
|---|---|
log4net.Appender.AdoNetAppender | 使用预处理语句或存储过程将日志事件写入数据库。 |
log4net.Appender.AnsiColorTerminalAppender | 将颜色突出显示的日志事件写入一个 ANSI 终端窗口。 |
log4net.Appender.AspNetTraceAppender | 将日志事件写入 ASP 跟踪上下文。然后可以在 ASP 页面的末尾或 ASP 跟踪页面上呈现这些内容。 |
log4net.Appender.BufferingForwardingAppender | 在将日志事件转发给子 appender 之前缓冲日志事件。 |
log4net.Appender.ColoredConsoleAppender | 将日志事件写入应用程序的控制台。事件可以进入标准输出流,也可以进入标准错误流。事件可以为每个级别定义可配置的文本和背景颜色。 |
log4net.Appender.ConsoleAppender | 将日志事件写入应用程序的控制台。事件可以进入标准输出流,也可以进入标准错误流。 |
log4net.Appender.DebugAppender | 将日志事件写入 .NET 系统。 |
log4net.Appender.EventLogAppender | 将日志事件写入 Windows 事件日志。 |
log4net.Appender.FileAppender | 将日志事件写入文件系统中的文件。 |
log4net.Appender.ForwardingAppender | 将日志事件转发给子 appender。 |
log4net.Appender.LocalSyslogAppender | 将日志事件写入本地 syslog 服务(仅限 UNIX)。 |
log4net.Appender.MemoryAppender | 将日志事件存储在内存缓冲区中。 |
log4net.Appender.NetSendAppender | 将日志事件写入 Windows Messenger 服务。这些消息显示在用户终端的对话框中。 |
log4net.Appender.OutputDebugStringAppender | 将日志事件写入调试器。如果应用程序没有调试器,系统调试器将显示该字符串。如果应用程序没有调试器并且系统调试器未激活,则忽略该消息。 |
log4net.Appender.RemoteSyslogAppender | 使用 UDP 网络将日志事件写入远程 syslog 服务。 |
log4net.Appender.RemotingAppender | 使用 .NET 远程处理将日志事件写入远程处理接收器。 |
log4net.Appender.RollingFileAppender | 将日志事件写入文件系统中的文件。RollingFileAppender 可以配置为根据日期或文件大小限制记录多个文件。 |
log4net.Appender.SmtpAppender | 将日志事件发送到电子邮件地址。 |
log4net.Appender.SmtpPickupDirAppender | 将 SMTP 邮件作为文件写入取件目录。然后,可以通过 SMTP 代理(如 IIS SMTP 代理)读取和发送这些文件。 |
log4net.Appender.TelnetAppender | 客户端通过 Telnet 连接以接收日志事件。 |
log4net.Appender.TraceAppender | 将日志事件写入 .NET 跟踪系统。 |
log4net.Appender.UdpAppender | 使用 UdpClient 将日志事件作为无连接 UDP 数据报发送到远程主机或多播组。 |
一个 logger 可以附加多个 appender。
给定 logger 的每个启用的日志记录请求将被转发到该 logger 中的所有 appender 以及层次结构中更高的 appender。 换句话说,appenders 是从 logger 层次结构中累加继承的。例如,如果将控制台 appender 添加到 root logger,那么所有启用的日志请求将至少在控制台上打印。如果另外一个文件 appender 被添加到 logger X 中,那么对 X 和 X 的子级启用的日志记录请求将在文件和控制台上打印。通过将 logger 上的 additivity 设置为 false,可以覆盖此默认行为,以便不再添加 appender 累积。
支配 appender 累加的规则总结如下:
- appender 可加性
-
logger X 的日志语句的输出将转到 X 及其祖先中的所有 appenders。这就是术语 "appender additivity" 的含义。
但是,如果 logger X 的祖先,比如 Y,将
additivity标志设置为false,则 X 的输出将定向到 X 及其上至 Y(包括 Y)的祖先中的所有 appenders;但不定向到 Y 的任何祖先中的 appenders。默认情况下,loggers 将其
additivity标志设置为true。
下表展示了一个示例:
| Logger 名称 | 添加的 Appenders | Additivity 标志 | 输出目标 | 说明 |
|---|---|---|---|---|
root | A1 | 不适用 | A1 | 没有默认的 appender 附加到 root(即 root 默认是没有附加任何 appender 的,这里我们显示地为其配置了一个 A1 appender) |
| x | A-x1, A-x2 | true | A1, A-x1, A-x2 | “x” 和 root 的 appenders |
| x.y | none | true | A1, A-x1, A-x2 | “x” 和 root 的 appenders |
| x.y.z | A-xyz1 | true | A1, A-x1, A-x2, A-xyz1 | “x.y.z”、“x” 和 root 中的 appenders |
| security | A-sec | false | A-sec | 因为 additivity 标志设置为 false,因此没有 appender 累积 |
| security.access | none | true | A-sec | 只有 “security” 的 appenders,因为 “security” 中的 additivity 标志设置为了 false |
5、Filters
appenders 可以过滤传递给它们的事件。可以在配置中指定 filters,以便对通过不同 appenders 记录的事件进行精细控制。
最简单的控制形式是在 appender 上指定一个 Threshold(阈值)。其工作原理是只记录级别大于或等于阈值的事件。
更复杂和自定义的事件过滤可以使用在每个 appender 上定义的过滤器链来完成。filters 必须实现 log4net.Filter.IFilter 接口。
在 Log4Net 包中定义了以下 filters:
| 类型 | 描述 |
|---|---|
log4net.Filter.DenyAllFilter | 丢弃所有日志事件。 |
log4net.Filter.LevelMatchFilter | 和事件的级别完全匹配。 |
log4net.Filter.LevelRangeFilter | 对一系列级别进行匹配。 |
log4net.Filter.LoggerMatchFilter | 与记录器名称的开头匹配。 |
log4net.Filter.PropertyFilter | 匹配特定属性值的子字符串。 |
log4net.Filter.StringMatchFilter | 匹配事件消息中的子字符串。 |
filters 可以配置为根据匹配接受或拒绝事件。
6、Layouts
通常情况下,用户不仅希望自定义输出目的地,还希望自定义输出格式。这是通过将 layout 与 appender 关联来实现的。layout 负责根据用户的意愿格式化日志记录请求;而 appender 负责将格式化后的输出发送到目的地。PatternLayout 是标准 log4net 分发的一部分,它允许用户根据类似于 C 语言 printf 函数的转换模式指定输出格式。
例如,带有转换模式 “%timestamp [%thread] %-5level %logger - %message%newline” 的 PatternLayout 将输出类似于以下内容:
176 [main] INFO Com.Foo.Bar - Located nearest gas station.
第一个字段是程序开始后经过的毫秒数。第二个字段是发出日志请求的线程。第三个字段是日志语句的级别。第四个字段是与日志请求关联的 logger 的名称。“-”后面的文本是语句的消息。
log4net 包中包含以下 layouts:
| 类型 | 描述 |
|---|---|
log4net.Layout.ExceptionLayout | 呈现来自日志事件的异常文本。 |
log4net.Layout.PatternLayout | 根据一组灵活的格式化标志来格式化日志事件。 |
log4net.Layout.RawTimeStampLayout | 从日志事件中提取时间戳。 |
log4net.Layout.RawUtcTimeStampLayout | 以通用时间(UTC)从日志事件中提取时间戳。 |
log4net.Layout.SimpleLayout | 非常简单地格式化日志事件:[level] - [message] |
log4net.Layout.XmlLayout | 将日志事件格式化为 XML 元素。 |
log4net.Layout.XmlLayoutSchemaLog4j | 将日志事件格式化为符合 log4j 事件文件类型定义的 XML 元素。 |
7、Object Renderers
同样重要的是,log4net 将根据用户指定的标准呈现日志消息的内容。例如,如果您经常需要记录橙子(当前项目中使用的对象类型),那么您可以注册一个 OrangeRenderer,每当需要记录橙子时就会调用它。
对象呈现遵循类层次结构。例如,假设橙子是水果,如果你注册了一个 FruitRenderer,那么包括橙子在内的所有水果都将由 FruitRenderer 渲染,除非你注册了一个特定于橙子的 OrangeRenderer。
object renderers 必须实现 log4net.ObjectRenderer.IObjectRenderer 接口。
请注意,ObjectRenderers 不会被 DebugFormat、InfoFormat、WarnFormat、ErrorFormat 和 FatalFormat 方法使用。
脚注
[1]:所谓“滚动失明”,是指当日志信息过于冗长时,程序员查找日志需要滚动查看大量的日志。而相信大部分小伙伴应该体会过,在大量冗长的信息内快速滚动时,我们很难从中找到有用的信息,就像是“失明”了一样。这是由于人的注意力和视觉搜索能力是有限的,当面对大量快速变化的信息时,可能会错过重要的细节。这就是所谓的"滚动失明”。
下一篇
相关文章:
(一)Apache log4net™ 手册 - 介绍
0、相关概念 Log4j 几乎每个大型应用程序都包含自己的日志记录或跟踪 API。根据这一规则,E.U. SEMPER 🌹项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作,API 已经发展成为 log4j —— 一个流行的 Ja…...
基于Java的民宿管理系统设计与实现(源码+lw+部署文档+讲解等)(民宿预约、民宿预订、民宿管理、酒店预约通用)
文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技…...
039:mapboxGL更换地图上的鼠标样式
第039个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中更换地图上的鼠标的样式。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共74行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:htt…...
【云原生】K8S对外服务之Ingress
目录 一、Ingress 简介1.1Ingress 组成1.3Ingress-Nginx 工作原理 二、部署 nginx-ingress-controller2.1部署ingress-controller Pod及相关资源2.2ingress 暴露服务的方式2.3 采用方式二:DaemonSetHostNetworknodeSelector 三、采用方式二:DeploymentNo…...
分布式锁如何实现
分布式是现在的比较主流的技术,常常和微服务一起出现。那么对于多个实例之间,如何证分布式系统中多个进程或线程同步访问共享资源呢?我们其实一想到的就是锁,我们在java里边有 synchronized, 在python里有lock,但是这个…...
Mysql存储-EAV模式
Mysql存储-EAV模式 最近又又又搞一点新东西,要整合不同业务进行存储和查询,一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键,需要充分考虑你需要使用的字段、使用场景,当数据结构设计完成后便…...
全局变量报错:\Output\STM32.axf: Error: L6218E: Undefined symbol
全局变量报错: .\Output\STM32.axf: Error: L6218E: Undefined symbol key_num (referred from main.o). 这里只说全局变量哦,这是因为你在调用的.c文件里 把定义写在了函数里面,写函数外面就没事了 改为: .h的声明文件根本不用写…...
算法错题簿(持续更新)
自用算法错题簿,按算法与数据结构分类 python1、二维矩阵:记忆化搜索dp2、图论:DFS3、回溯:129612964、二叉树:贪心算法5、字符串:记忆化搜索6、01字符串反转:结论题7、二进制数:逆向…...
基于Springboot实现疫情网课管理系统项目【项目源码+论文说明】
基于Springboot实现疫情网课管理系统演示 摘要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于疫情网课管理系统当然也不能排除在外,随着网络技术的不断成熟,带动了疫情…...
Linux文件与目录的增删改查
一、增 1、mkdir命令 作用: 创建一个新目录。 格式: mkdir [选项] 要创建的目录 常用参数: -p:创建目录结构中指定的每一个目录,如果目录不存在则创建,如果目录已存在也不会被覆盖。 用法示例&a…...
JVM的内存模型
一、JVM的内存模型 1.1、目标 内存模型是用来描述JVM内部的内存结构和内存管理的模型。它定义了JVM在运行Java程序时所需要的各种内存区域,以及每个内存区域的作用和特点。 1.2、结构划分 1.2.1、栈 每个线程在执行Java方法时会创建一个栈帧(Stack …...
数据采集项目之业务数据(三)
1. Maxwell框架 开发公司为Zendesk公司开源,用java编写的MySQL变更数据抓取软件。内部是通过监控MySQL的Binlog日志,并将变更数据以JSON格式发送到Kafka等流处理平台。 1.1 MySQL主从复制 主机每次变更数据都会生成对应的Binlog日志,从机可…...
vuedraggable影响点击事件的解决办法
在工作中有很多场景需要针对广告、商品、信息推广等进行一个排序,或者对展示的顺序做出调整,方便放用户第一眼看到自己感兴趣的信息,因此避免不了需要用到排序的插件,这里以vue为例子,采用的插件是vuedraggable,这个插件针对于排序的功能相对完善,官网地址:vuedraggable官网 但…...
Linux 中的 grep 命令
Linux 中的 grep 命令是一个强大的文本搜索工具,它允许用户在文件中查找指定的文本模式,并将匹配的行打印出来。grep 是“Global Regular Expression Print”的缩写,它使用正则表达式来进行文本搜索,因此具有强大的灵活性和功能。…...
阶段五-Day03-Ajax
一、JavaWeb中路径的说明 1. JavaWeb中的路径 在JavaWeb中, 路径分为相对路劲和绝对路径两种: 相对路径: ./ 表示当前目录 ../ 表示当前文件所在目录的上一级目录 绝对路径: 完整的路径名 2. 在JavaWeb中/的不同意义 /斜杠如果被浏览器解析,得到的是 协议本地ip端口号…...
EPOLL单线程版本 基于reactor 的 httpserver文件下载 支持多个客户端同时处理
之前写了一个httpserver的问价下载服务器 如果有多个客户端请求过来只能串行处理必须得等当前的操作完成之后才会处理 另外还存在 文件大的时候 会出错 处理不了 原因就是 sendfile是在一个while循环中处理的 当调用send失败返回-1之后 就 结束了 而一般来讲 se…...
uniapp实现微信小程序隐私协议组件封装
uniapp实现微信小程序隐私协议组件封装。 <template><view class"diygw-modal basic" v-if"showPrivacy" :class"showPrivacy?show:" style"z-index: 1000000"><view class"diygw-dialog diygw-dialog-modal bas…...
【Node.js】NPM 和 package.json
NPM npm 是 Node.js 的包管理工具,基于命令行,用于安装、升级、移除、管理依赖项。 常用命令: npm init:初始化一个新的 npm 项目,创建 package.json 文件。(括号里为默认值) description&am…...
周总结【java项目】
项目进度: 学习了JavaFX,下载了sceneBuilder辅助工具构建窗口(目前建立了登陆,注册,忘记密码的界面),然后是学习了MySQL的连接,现在的项目是刚连上数据库; 下一步&…...
《深度不确定条件下的决策:从理论到实践》PDF
制定未来计划时需要预测变化,尤其是制定长期计划或针对罕见事件的计划时。当这些变化存在高度不确定性的时候,这种预期就变得越来越困难。 今天给大家介绍的这本《深度不确定条件下的决策:从理论到实践》正是解决以上问题的良方。完整书籍文…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
