(一)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]:所谓“滚动失明”,是指当日志信息过于冗长时,程序员查找日志需要滚动查看大量的日志。而相信大部分小伙伴应该体会过,在大量冗长的信息内快速滚动时,我们很难从中找到有用的信息,就像是“失明”了一样。这是由于人的注意力和视觉搜索能力是有限的,当面对大量快速变化的信息时,可能会错过重要的细节。这就是所谓的"滚动失明”。


下一篇

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

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

相关文章

word重复上次操作的快捷键的F4没效果了

word重复上次操作的快捷键的F4没效果了 word编辑文档的时候&#xff0c;以前都是用F4快捷键解决重复上次操作的&#xff0c;或者ctrly&#xff0c;现在没效果了&#xff0c;在哪里设置回去呢&#xff1f;也没开什么软件不存在快捷键冲突的&#xff0c;F4键也没坏。咋弄哦&…

redis分布式秒杀锁

-- 获取锁标识&#xff0c;是否与当前线程一致&#xff1f; if(redis.call(get, KEYS[1]) ARGV[1]) then-- 一致&#xff0c;删除return redis.call(del, KEYS[1]) end -- 不一致&#xff0c;直接返回 return 0package com.platform.lock;public interface ILock {/*** 获取锁…

Avalonia环境搭建

1.开发文档 开发文档&#xff0c; GitHub项目地址 https://github.com/avaloniaui/avalonia 2.VS2022 及扩展安装 建议使用vs2022最新版本下载并安装扩展Avalonia for Visual Studio 2022 3.安装Avalonia UI模板 dotnet new install Avalonia.Templates 查看安装版本 dot…

【MyBatis】MyBatis 详解

MyBatis 详解 一. MyBatis 是什么二. MyBatis 在整个框架中的定位三. MyBatis 的操作1. 先创建好数据库和表2. 添加MyBatis框架⽀持3. 修改配置文件4. 添加业务代码5. 增、删、改操作① 增加⽤户② 修改用户操作③ 删除操作 6. 查询操作① 单表查询② 多表查询 一. MyBatis 是什…

Mojo 正式发布,Rust 能否与之匹敌?

9 月 7 日&#xff0c;Modular 公司宣布正式发布 Mojo&#xff1a;Mojo 现在已经开放本地下载——初步登陆 Linux 系统&#xff0c;并将很快提供 Mac 与 Windows 版本。据介绍&#xff0c;Mojo 最初的目标是比 Python 快 35000 倍&#xff0c;近日该团队表示&#xff0c;Mojo 将…

设计模式 - 观察者模式

目录 一. 前言 二. 实现 三. 优缺点 一. 前言 观察者模式属于行为型模式。在程序设计中&#xff0c;观察者模式通常由两个对象组成&#xff1a;观察者和被观察者。当被观察者状态发生改变时&#xff0c;它会通知所有的观察者对象&#xff0c;使他们能够及时做出响应&#xf…

基于Dockerfile创建镜像

基于现有镜像创建 1.首先启动一个镜像&#xff0c;在容器里做修改 docker create -it centos:7 /bin/bash #常用选项&#xff1a; -m 说明信息&#xff1b; -a 作者信息&#xff1b; -p 生成过程中停止容器的运行。 2.然后将修改后的容器提交为新的镜像&#xff0c;需要使用…

基于SSM+Vue的学习交流论坛的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

用delphi7将excel导入access并查询及其分析(一)

开发环境&#xff1a;win7 64&#xff08;win10 64&#xff09;两个系统环境&#xff0c;delphi7。 一、安装delphi7&#xff08;已经放在阿里云盘的soft中&#xff09; 解压安装&#xff0c;文件夹里自带SN.txt。直接默认路径安装&#xff08;关系到后续的控件安装时方便&…

Hive窗口函数回顾

1.语法 1.1 基于行的窗口函数 Hive的窗口函数分为两种类型&#xff0c;一种是基于行的窗口函数&#xff0c;即将某个字段的多行限定为一个范围&#xff0c;对范围内的字段值进行计算&#xff0c;最后将形成的字段拼接在该表上。 注意&#xff1a;在进行窗口函数计算之前&#…

不用休眠的 Kotlin 并发:深入对比 delay() 和 sleep()

本文翻译自&#xff1a; https://blog.shreyaspatil.dev/sleepless-concurrency-delay-vs-threadsleep 毫无疑问&#xff0c;Kotlin 语言中的协程 Coroutine 极大地帮助了开发者更加容易地处理异步编程。该特性中封装的诸多高效 API&#xff0c;可以确保开发者花费更小的精力去…

Mysql--内置函数

字符串函数 1、拼接字符串 concat(str1,str2...) select concat(12,34,abccc) select CONCAT(name,的家乡是,hometown) from students 2、包含字符个数 length(abc) 注&#xff1a;一个中文占3个字符&#xff0c;一个字母或数字占1个字符 3、截取字符串 left(str,len)返回字…

Elasticsearch:使用 huggingface 模型的 NLP 文本搜索

本博文使用由 Elastic 博客 title 组成的简单数据集在 Elasticsearch 中实现 NLP 文本搜索。你将为博客文档建立索引&#xff0c;并使用摄取管道生成文本嵌入。 通过使用 NLP 模型&#xff0c;你将使用自然语言在博客文档上查询文档。 安装 Elasticsearch 及 Kibana 如果你还没…

计算机竞赛 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

Safran与是德科技合作为蔚来提供电动汽车中的5G和C-V2X连接测试

概述 虹科Safran GNSS模拟器助力是德科技&#xff08;Keysight&#xff09;为中国顶级电动汽车制造商之一——蔚来汽车&#xff08;NIO&#xff09;提供了业界领先的UXM 5G测试解决方案以验证5G和C-V2X的连接性&#xff0c;能够根据3GPP和其他标准组织定义的最新5G新无线电&am…

解决扬声器异常

之前使用的是PulseAudio PulseAudio 是默认的音频服务器和音频框架&#xff0c;因此大多数应用程序通过 PulseAudio 来处理音频 但也有一些应用程序直接使用 ALSA&#xff08;Advanced Linux Sound Architecture&#xff09;来与音频硬件交互。在这些情况下&#xff0c;ALSA …

深入理解计算机系统(1):系统组成

一、系统硬件组成 1、控制器&#xff08;CPU&#xff09;&#xff1a;解释和执行内存中的指令 &#xff08;1&#xff09;、控制器 程序控制器&#xff1a;指令指针&#xff0c;指向主存中的机器语言指令&#xff0c;为一个字大小的存储设备或寄存器。 指令寄存器、指令译码器、…

离线安装mysql客户端

下载路径 oracle网站总是在不断更新&#xff0c;所以下载位置随时可能变动但万变不离其宗&#xff0c;学习也要学会一通百通。 首先直接搜索&#xff0c;就能找找到mysql官网 打开网站&#xff0c;并点击 DOWNLOADS 往下滚动&#xff0c;找到社区版下载按钮。…

高效解决 TypeError : ‘ numpy._DTypeMeta‘ object is not subscriptable 问题

文章目录 问题描述解决问题 问题描述 解决问题 参考博文 打开报错位置 AppData\Roaming\Python\Python39\site-packages\cv2\typing\ 添加single-quotes&#xff0c;即单引号 博主说The trick is to use single-quotes to avoid the infamous TypeError: ‘numpy._DTypeMeta’…

微信小程序发布流程

前言 上周写了如何写一个小程序&#xff0c;然后经过查资料&#xff0c;改bug&#xff0c;找chatgpt美化页面&#xff0c;我写了一个计算代谢率的小工具&#xff0c;写完了之后该怎么办呢&#xff0c;当然是发布上架&#xff0c;然后我就开始了发布的折腾 提交代码 这一步很…