当前位置: 首页 > news >正文

(一)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 2 Logo

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 项目
Logging Services Logo
log4net 是 Apache 软件基金会的 Apache 日志服务项目的一部分。Logging Services 项目旨在为应用程序调试和审计提供跨语言的日志服务。
Why Log 4?

有些同学可能会对名称中出现的数字 “4” 感到疑惑,但如果你尝试使用英文念出 Log4j 或者 Log4Net 的名称后,相信这个问题就会迎刃而解了。

没错,名称中的 “4” 代表英文单词 "for",因为 “4” 的英文单词 "four" 与 "for" 发音类似。所以,"Log4j" 的含义就是 "Log for Java", 意思是这是一个为 Java 提供日志服务的工具。

这是一种常见的命名方式,通过数字 “4” 来代替 "for", 使得名称更加简洁,也增加了一些趣味性。此外,还有其他的类似命名方式,比如使用 “2” 来代替 "to"。它们都在许多场合内大量使用着。

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, appenderslayouts。这三种类型的组件协同工作使得开发者能够根据消息类型和级别记录日志消息,并在运行时控制这些消息的格式和报告位置。这些组件由控制着 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 层次结构的顶层。它主要有三点不同:

  1. 它总是存在的
  2. 它不能按名称检索
  3. 它总是有一个指定的级别

使用 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 开始,在层次结构中向上进行,直至 root logger。

为了确保所有的 logger 最终都可以继承一个级别,root logger 总是有一个分配的级别。其默认值是 DEBUG。

下面是四个表,其中包含各种分配的级别值和根据上述规则继承级别结果。

Logger 名称分配的级别继承的级别
rootProotProot
XnoneProot
X.YnoneProot
X.Y.ZnoneProot

上例一中,只有 root logger 被分配了级别。该级别值,即 Proot,由其他 logger X、X.Y、X.Y.Z 继承。

Logger 名称分配的级别继承的级别
rootProotProot
XPxPx
X.YPxyPxy
X.Y.ZPxyzPxyz

上例二中,所有的 logger 都有分配的级别值。所以不需要级别继承

Logger 名称分配的级别继承的级别
rootProotProot
XPxPx
X.YnonePx
X.Y.ZPxyzPxyz

上例三中,root、X 以及 X.Y.Z logger 分别被分配为级别 Proot、Px 以及 Pxyz。logger X.Y 从其父级 X 处继承其级别值。

Logger 名称分配的级别继承的级别
rootProotProot
XPxPx
X.YnonePx
X.Y.ZnonePx

上例四中,root 以及 X logger 分别被分配为级别 Proot 以及 Px。logger X.Y 以及 X.Y.Z 从最近的具有指定级别的父级 X 处继承其级别值。

日志记录请求是(通过 log4net.ILog)调用 logger 实例的一个打印方法发出的。这些打印方法是 DebugInfoWarnErrorFatal

根据定义,打印方法确定日志记录请求的级别。例如:如果 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");

中,xy 引用完全相同的 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 中,那么对 XX 的子级启用的日志记录请求将在文件和控制台上打印。通过将 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 名称添加的 AppendersAdditivity 标志输出目标说明
rootA1不适用A1没有默认的 appender 附加到 root(即 root 默认是没有附加任何 appender 的,这里我们显示地为其配置了一个 A1 appender)
xA-x1, A-x2trueA1, A-x1, A-x2“x” 和 root 的 appenders
x.ynonetrueA1, A-x1, A-x2“x” 和 root 的 appenders
x.y.zA-xyz1trueA1, A-x1, A-x2, A-xyz1“x.y.z”、“x” 和 root 中的 appenders
securityA-secfalseA-sec因为 additivity 标志设置为 false,因此没有 appender 累积
security.accessnonetrueA-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。根据这一规则&#xff0c;E.U. SEMPER &#x1f339;项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作&#xff0c;API 已经发展成为 log4j —— 一个流行的 Ja…...

基于Java的民宿管理系统设计与实现(源码+lw+部署文档+讲解等)(民宿预约、民宿预订、民宿管理、酒店预约通用)

文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/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 采用方式二&#xff1a;DaemonSetHostNetworknodeSelector 三、采用方式二&#xff1a;DeploymentNo…...

分布式锁如何实现

分布式是现在的比较主流的技术&#xff0c;常常和微服务一起出现。那么对于多个实例之间&#xff0c;如何证分布式系统中多个进程或线程同步访问共享资源呢&#xff1f;我们其实一想到的就是锁&#xff0c;我们在java里边有 synchronized, 在python里有lock&#xff0c;但是这个…...

Mysql存储-EAV模式

Mysql存储-EAV模式 最近又又又搞一点新东西&#xff0c;要整合不同业务进行存储和查询&#xff0c;一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键&#xff0c;需要充分考虑你需要使用的字段、使用场景&#xff0c;当数据结构设计完成后便…...

全局变量报错:\Output\STM32.axf: Error: L6218E: Undefined symbol

全局变量报错&#xff1a; .\Output\STM32.axf: Error: L6218E: Undefined symbol key_num (referred from main.o). 这里只说全局变量哦&#xff0c;这是因为你在调用的.c文件里 把定义写在了函数里面&#xff0c;写函数外面就没事了 改为&#xff1a; .h的声明文件根本不用写…...

算法错题簿(持续更新)

自用算法错题簿&#xff0c;按算法与数据结构分类 python1、二维矩阵&#xff1a;记忆化搜索dp2、图论&#xff1a;DFS3、回溯&#xff1a;129612964、二叉树&#xff1a;贪心算法5、字符串&#xff1a;记忆化搜索6、01字符串反转&#xff1a;结论题7、二进制数&#xff1a;逆向…...

基于Springboot实现疫情网课管理系统项目【项目源码+论文说明】

基于Springboot实现疫情网课管理系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于疫情网课管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了疫情…...

Linux文件与目录的增删改查

一、增 1、mkdir命令 作用&#xff1a; 创建一个新目录。 格式&#xff1a; mkdir [选项] 要创建的目录 常用参数&#xff1a; -p&#xff1a;创建目录结构中指定的每一个目录&#xff0c;如果目录不存在则创建&#xff0c;如果目录已存在也不会被覆盖。 用法示例&a…...

JVM的内存模型

一、JVM的内存模型 1.1、目标 内存模型是用来描述JVM内部的内存结构和内存管理的模型。它定义了JVM在运行Java程序时所需要的各种内存区域&#xff0c;以及每个内存区域的作用和特点。 1.2、结构划分 1.2.1、栈 每个线程在执行Java方法时会创建一个栈帧&#xff08;Stack …...

数据采集项目之业务数据(三)

1. Maxwell框架 开发公司为Zendesk公司开源&#xff0c;用java编写的MySQL变更数据抓取软件。内部是通过监控MySQL的Binlog日志&#xff0c;并将变更数据以JSON格式发送到Kafka等流处理平台。 1.1 MySQL主从复制 主机每次变更数据都会生成对应的Binlog日志&#xff0c;从机可…...

vuedraggable影响点击事件的解决办法

在工作中有很多场景需要针对广告、商品、信息推广等进行一个排序,或者对展示的顺序做出调整,方便放用户第一眼看到自己感兴趣的信息,因此避免不了需要用到排序的插件,这里以vue为例子,采用的插件是vuedraggable,这个插件针对于排序的功能相对完善,官网地址:vuedraggable官网 但…...

Linux 中的 grep 命令

Linux 中的 grep 命令是一个强大的文本搜索工具&#xff0c;它允许用户在文件中查找指定的文本模式&#xff0c;并将匹配的行打印出来。grep 是“Global Regular Expression Print”的缩写&#xff0c;它使用正则表达式来进行文本搜索&#xff0c;因此具有强大的灵活性和功能。…...

阶段五-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 的包管理工具&#xff0c;基于命令行&#xff0c;用于安装、升级、移除、管理依赖项。 常用命令&#xff1a; npm init&#xff1a;初始化一个新的 npm 项目&#xff0c;创建 package.json 文件。&#xff08;括号里为默认值&#xff09; description&am…...

周总结【java项目】

项目进度&#xff1a; 学习了JavaFX&#xff0c;下载了sceneBuilder辅助工具构建窗口&#xff08;目前建立了登陆&#xff0c;注册&#xff0c;忘记密码的界面&#xff09;&#xff0c;然后是学习了MySQL的连接&#xff0c;现在的项目是刚连上数据库&#xff1b; 下一步&…...

《深度不确定条件下的决策:从理论到实践》PDF

制定未来计划时需要预测变化&#xff0c;尤其是制定长期计划或针对罕见事件的计划时。当这些变化存在高度不确定性的时候&#xff0c;这种预期就变得越来越困难。 今天给大家介绍的这本《深度不确定条件下的决策&#xff1a;从理论到实践》正是解决以上问题的良方。完整书籍文…...

【MySQL】表的基础增删改查

前面我们已经知道怎么来创建表了&#xff0c;接下来就来对创建的表进行一些基本操作。 这里先将上次创建的表删除掉&#xff1a; mysql> use test; Database changedmysql> show tables; ---------------- | Tables_in_test | ---------------- | student | -----…...

第11章 Redis(二)

11.11 Redis 哨兵机制和集群有什么区别 难度:★★★ 重点:★★ 白话解析 前面的题目都是Redis的原理,接下来就是实际使用的问题了,首先Redis为了保证高可用,在微服务场景下必须是部署集群的,而Redis的集群部署通常就两种方式:主从和Redis Cluster。 参考答案 1、主从…...

mybatis配置entity下不同文件夹同类型名称的多个类型时启动springboot项目出现TypeException源码分析

记录问题&#xff1a;当配置了 mybatis.type-aliases-packagecom.runjing.erp.entity 配置项时&#xff0c;如果entity文件夹下存在不同子文件夹下的同名类型时&#xff0c;mybatis初始化加载映射时会爆出org.apache.ibatis.type.TypeException&#xff1a; The alias TestDemo…...

淘宝商品评论数据分析接口,淘宝商品评论接口

淘宝商品评论数据分析接口可以通过淘宝开放平台API获取。 通过构建合理的请求URL&#xff0c;可以向淘宝服务器发起HTTP请求&#xff0c;获取商品评论数据。接口返回的数据一般为JSON格式&#xff0c;包含了商品的各种评价信息。 获取到商品评论数据后&#xff0c;可以对其进…...

RK3288 android7.1 修改双屏异触usb tp触摸方向

一&#xff0c;问题描述&#xff1a; android机器要求接两个屏&#xff08;lvdsmipi&#xff09;两个usb tp要实现双屏异触。由于mipi的方向和lvds方向转成一样的了。两个usb tp的方向在异显示的时候也要作用一样。这个时候要根据pid和vid修改触摸上报的数据。usb tp有通用的触…...

软考 系统架构设计师系列知识点之软件架构风格(8)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件架构风格&#xff08;7&#xff09; 这个十一注定是一个不能放松、保持“紧”的十一。由于报名了全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;11月4号就要考试&#xff0c;因此…...

ubuntu安装ssh

安装 OpenSSH 服务器&#xff08;如果尚未安装&#xff09;&#xff1a; apt-get update && apt-get upgrade -y sudo apt-get install -y openssh-server 检查 SSH 服务是否正在运行&#xff1a; sudo service ssh status 如果 SSH 服务未运行&#xff0c;请通过以…...

webpack不同环境下使用CSS分离插件mini-css-extract-plugin

1.背景描述 使用mini-css-extract-plugin插件来打包css文件&#xff08;从css文件中提取css代码到单独的文件中&#xff0c;对css代码进行代码压缩等&#xff09;。 本次采用三个配置文件&#xff1a; 公共配置文件&#xff1a;webpack.common.jsdev开发环境配置文件&#x…...

[MongoDB]-权限验证管理

[MongoDB]-权限验证管理 senge | 2023年9月 背景说明&#xff1a;现有两套MongoDB副本集群给开发人员使用时未开启认证。 产生影响&#xff1a;用户若输入账号以及密码则会进行校验&#xff0c;但用户可以在不输入用户名和密码的情况下也可直接登录。 倘若黑客借此进行攻击勒索…...

bootstrapjs开发环境搭建

Bootstrapjs是一个web前端页面应用开发框架&#xff0c;其提供功能丰富的JavaScript工具集以及用户界面元素或组件的样式集&#xff0c;本文主要描述bootstrapjs的开发环境搭建。 如上所示&#xff0c;使用nodejs运行时环境、使用npm包管理工具、使用npm初始化一个项目工程test…...