【C++】POCO学习总结(十七):日志系统(级别、通道、格式化、记录流)

【C++】郭老二博文之:C++目录

1、Poco::Message 日志消息

1.1 说明

所有日志消息都在Poco::Message对象中存储和传输。
头文件:#include “Poco/Message.h”
一条消息包含如下内容:优先级、来源、一个文本、一个时间戳、进程和线程标识符、可选参数(名称-值对)

1.2 消息优先级

POCO定义了8个消息优先级:

  • PRIO_FATAL(最高优先级)
  • PRIO_CRITICAL
  • PRIO_ERROR
  • PRIO_WARNING
  • PRIO_NOTICE
  • PRIO_INFORMATION
  • PRIO_DEBUG
  • PRIO_TRACE(最低优先级)

设置、获取优先级

  • void setPriority(Priority prio)
  • Priority getPriority() const

1.3 消息来源

消息来源:一般用生成消息的类的名称,或者产生消息的子系统的名称

  • void setSource(const std::string& source)
  • const std::string& getSource() const

1.4 消息内容

要记录的实际消息。对格式、长度等没有要求。可以在出现在日志目的地之前由格式化程序修改

  • void setText(const std::string& text)
  • const std::string& getText() const

1.5 时间戳

创建消息的日期和时间,精度可达微秒级。
由Poco::Message的构造函数自动初始化为当前日期和时间。

  • void setTime(const Timestamp& time)
  • const Timestamp& getTime() const

1.6 进程和线程标识符

进程标识符(PID)是一个长整型值,用于存储系统的进程ID。
线程标识符(TID)也是一个长整型值,存储当前线程的序列号。
进程标识符、线程标识符和线程名称在Poco::Message的构造函数中初始化。

  • void setThread(const std::string& threadName)
  • const std::string& getThread() const
  • void setTid(long tid)
  • long getTid() const
  • void setPid(long pid)
  • long getPid() const

1.7 消息参数

消息可以存储任意数量的键值对。键和值可以是任意字符串。消息参数可以在格式化程序中引用。使用索引操作符访问消息参数。

2、Poco::Logger 日志记录

2.1 创建

Poco::Logger是日志框架的主要入口点。
头文件 #include “Poco/Logger.h”
应用程序使用Poco::Logger类的实例来生成日志消息。
每个记录器都有一个附加的通道,该通道将消息传递到它们的目的地(可能通过其他通道)。
每个记录器都有一个名称,它成为该记录器生成的所有消息的源。该名称是在创建时设置的,以后不可更改

2.2 优先级

日志记录器根据消息的优先级过滤消息。
只有优先级等于或高于日志记录器日志级别的消息才会被传播。
例如:
日志级别设置为PRIO_ERROR的日志记录器将只传播优先级为PRIO_ERROR、PRIO_CRITICAL或PRIO_FATAL的消息。
PRIO_WARNING或更低的值将被丢弃。

2.3 记录器的层次结构

根据它们的名字,记录器形成了一个树状的层次结构。
日志记录器的名称由一个或多个组件组成,以句点分隔。每个组件对应于前一个组件的名称空间中的一个名称。
一个特殊的记录器,根记录器,是一个以空字符串作为其名称的记录器。它构成了日志记录器层次结构的根。
日志记录器层次结构的最大深度没有限制。

在这里插入图片描述

2.4 继承层次结构

新创建的日志记录器从日志记录器层次结构中的祖先继承其日志级别和附加通道。
例如:在创建时,记录器“HTTPServer.RequestHandler.cgi”将从名为“HTTPServer.RequestHandler”的记录器继承其日志级别和附加通道。
一旦日志程序被完全创建,它就不再与它的祖先相关。换句话说,对日志记录器的日志级别或通道的更改对其已经存在的后代没有影响。

2.5 记录日志

  • void log(const Message& msg):如果消息的优先级大于或等于记录器的日志级别,则将消息传播到附加的通道。信息保持不变。

  • void log(const Exception& exc):创建并记录一条优先级为PRIO_ERROR的消息和异常的显示文本

创建并记录具有各自优先级和给定文本的消息:

  • void fatal(const std::string& text)
  • void critical(const std::string& text)
  • void error(const std::string& text)
  • void warning(const std::string& text)
  • void notice(const std::string& text)
  • void information(const std::string& text)
  • void debug(const std::string& text)
  • void trace(const std::string& text)

void dump(const std::string& text,const void* buffer, int length,Message::Priority prio = Message::PRIO_DEBUG)
用给定的优先级记录给定的消息。文本之后是给定缓冲区的十六进制转储。

2.6 日志级别

  • bool is(int level) const:如果日志记录器的日志级别至少为level,则返回true。- bool fatal() const

如果日志记录器的日志级别至少是相应的级别,则返回true:

  • bool critical() const
  • bool error() const
  • bool warning() const
  • bool notice() const
  • bool information() const
  • bool debug() const
  • bool trace() const

2.7 记录器

POCO管理一个全局的记录器映射。
不要自己创建记录器。要使用POCO提供记录器的引用。POCO会根据需要动态创建新的记录器。

static Logger& get(const std::string& name)

返回对具有给定名称的记录器的引用。如果没有会自动创建日志记录器。这是线程安全的。

2.8 示例

#include "Poco/Logger.h"
using Poco::Logger;
int main(int argc, char** argv)
{Logger& logger = Logger::get("TestLogger");logger.information("This is an informational message");logger.warning("This is a warning message");return 0;
}

3、Poco::Channel 通道

3.1 说明

Poco::Channel的子类负责将消息(Poco::Message)传递到它们的目的地(例如,控制台或日志文件)。
每个Poco::Logger(它本身是Poco::Channel的子类)都连接到Poco::Channel。POCO提供了POCO::Channel的各种子类,这些子类将消息传递到控制台、日志文件或系统的日志记录设施。
可以定义你自己的通道类。
通道使用引用计数进行内存管理。

3.2 信道特性

通道可以支持任意数量的属性(键值对),这些属性用于配置通道。
属性是通过setProperty()成员函数设置的:
属性的值可以通过getProperty()获得:
这两个函数是在Poco::Configurable类中定义的,它是Poco::Channel的超类。

  • void setProperty(const std::string& name, const std::string& value)
  • std::string getProperty(const sdt::string& name)

3.3 Poco::ConsoleChannel 控制台通道

Poco::ConsoleChannel 是最基本的通道实现。
头文件:#include “Poco/ConsoleChannel.h”
Poco::ConsoleChannel 只是将接收到的任何消息的文本写入标准输出(std::clog)。
Poco::ConsoleChannel 没有可配置的属性。
Poco::ConsoleChannel 是根记录器的默认通道。

3.4 Poco::WindowsConsoleChannel Windows控制台

Poco::WindowsConsoleChannel类似于ConsoleChannel,但直接写入Windows控制台,而不是std::clog。
头文件:#include “Poco/WindowsConsoleChannel.h”
Poco::WindowsConsoleChannel 只是将接收到的任何消息的文本写入Windows控制台。
Poco::WindowsConsoleChannel 没有可配置的属性。
Poco::WindowsConsoleChannel 支持> UTF-8编码的文本。

3.5 Poco::NullChannel 空通道

Poco::NullChannel丢弃发送给它的所有消息。
头文件:#include “Poco/NullChannel.h”

3.6 Poco::SimpleFileChannel 最简日志文件

3.6.1 说明

Poco::SimpleFileChannel是编写日志文件最简单的方法。
消息的文本被附加到一个文件中,后跟一个换行符。
支持可选的简单日志文件轮换:在主日志文件和备日志文件之间轮流写,当一旦主日志文件超过一定大小,将创建一个备日志文件(如果已经存在,则将其清空)。如果备日志文件超过最大大小,则清空主日志文件,并继续记录主日志文件,依此类推。

3.6.2 属性

1)path:主日志文件路径。
2)secondaryPath:备日志文件路径。默认为path.1
3) rotation:日志文件大小

  • never:默认的,一直记录在主日志文件
  • n:当文件大小超过n字节时轮换
  • n K:当文件大小超过n Kb时轮换
  • n M:当文件大小超过n Mb时轮换

3.6.3 示例

#include "Poco/Logger.h"
#include "Poco/SimpleFileChannel.h"
#include "Poco/AutoPtr.h"
using Poco::Logger;
using Poco::SimpleFileChannel;
using Poco::AutoPtr;
int main(int argc, char** argv)
{AutoPtr<SimpleFileChannel> pChannel(new SimpleFileChannel);pChannel->setProperty("path", "sample.log");pChannel->setProperty("rotation", "2 K");Logger::root().setChannel(pChannel);Logger& logger = Logger::get("TestLogger"); // 继承根通道for (int i = 0; i < 100; ++i)logger.information("Testing SimpleFileChannel");return 0;
}

3.7 Poco::FileChannel 文件通道

3.7.1 说明

Poco::FileChannel提供了全面的日志文件支持。
头文件:#include “Poco/FileChannel.h”
消息的文本被附加到一个文件中,后跟一个换行符。
Poco::FileChannel 支持根据文件大小或时间间隔轮换日志文件。
Poco::FileChannel 支持归档日志文件的自动归档(不同的文件命名策略)、压缩(gzip)和清除(根据归档文件的时间或归档文件的数量)。

3.7.2 属性

1)path:日志文件路径
2)rotation:日志文件的轮换方式

  • never 不轮换
    • n:当文件大小超过n字节时轮换
  • n K:当文件大小超过n Kb时轮换
  • n M:当文件大小超过n Mb时轮换
  • [day,][hh:][mm]:在指定的星期/时间轮换
  • daily/weekly/monthly:每天/每周/每月
  • n hours/weeks/months:每n个小时/周/月

3)archive:归档日志文件的命名

  • number:一个自动递增的数字,从0开始,附加到日志文件名后。最新存档的文件总是0。
  • timestamp: 以 YYYYMMDDHHMMSS 格式的时间戳附加到日志文件中。

4)times:指定轮换时间是作为本地时间还是UTC时间处理。有效值为local和utc。
5)compress:自动压缩归档文件。指定true或false。
6)purgeAge:指定归档日志文件的最大保存时间。超过这个时间的文件将被清除。
7)purgeCount:指定归档日志文件的最大数目。如果达到这个数字,那么最旧的归档日志文件将被清除。

3.7.3 示例

#include "Poco/Logger.h"
#include "Poco/FileChannel.h"
#include "Poco/AutoPtr.h"
using Poco::Logger;
using Poco::FileChannel;
using Poco::AutoPtr;
int main(int argc, char** argv)
{AutoPtr<FileChannel> pChannel(new FileChannel);pChannel->setProperty("path", "sample.log");pChannel->setProperty("rotation", "2 K");pChannel->setProperty("archive", "timestamp");Logger::root().setChannel(pChannel);Logger& logger = Logger::get("TestLogger"); // 继承根通道for (int i = 0; i < 100; ++i)logger.information("Testing FileChannel");return 0;
}

3.8 Poco::EventLogChannel Windows专用

Poco::EventLogChannel:仅在Windows NT平台上使用,记录Windows事件日志。
Poco::EventLogChannel将PocoFoundation.dll注册为Windows事件日志中的消息定义资源DLL。
当查看Windows事件日志时,事件查看器应用程序必须能够找到PocoFoundation.dll,否则日志消息将不会按预期显示。

3.9 Poco::SyslogChannel Linux专用

仅在Unix平台上可用的Poco::SyslogChannel将日志记录到本地Syslog守护进程。
Net库包含一个RemoteSyslogChannel类,它使用基于udp的Syslog协议与远程Syslog守护进程一起工作。

3.10 Poco::AsyncChannel 异步通道

Poco::AsyncChannel允许在单独的线程中运行通道。
将产生日志消息的线程与传递日志消息的线程解耦。
所有日志消息都存储在FIFO队列中。
一个单独的线程从队列中提取消息并将它们发送到另一个通道。

#include "Poco/Logger.h"
#include "Poco/AsyncChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/AutoPtr.h"
using Poco::Logger;
using Poco::AsyncChannel;
using Poco::ConsoleChannel;
using Poco::AutoPtr;
int main(int argc, char** argv)
{AutoPtr<ConsoleChannel> pCons(new ConsoleChannel);AutoPtr<AsyncChannel> pAsync(new AsyncChannel(pCons));Logger::root().setChannel(pAsync);Logger& logger = Logger::get("TestLogger");for (int i = 0; i < 10; ++i)logger.information("This is a test");return 0;
}

3.11 Poco::SplitterChannel 分发通道

Poco::SplitterChannel将消息转发到一个或多个其他通道。
void addChannel(Channel* pChannel)为Poco::SplitterChannel添加一个新通道

#include "Poco/Logger.h"
#include "Poco/SplitterChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/SimpleFileChannel.h"
#include "Poco/AutoPtr.h"
using Poco::Logger;
using Poco::SplitterChannel;
using Poco::ConsoleChannel;
using Poco::SimpleFileChannel;
using Poco::AutoPtr;
int main(int argc, char** argv)
{AutoPtr<ConsoleChannel> pCons(new ConsoleChannel);AutoPtr<SimpleFileChannel> pFile(new SimpleFileChannel("test.log"));AutoPtr<SplitterChannel> pSplitter(new SplitterChannel);pSplitter->addChannel(pCons);pSplitter->addChannel(pFile);Logger::root().setChannel(pSplitter);Logger::root().information("This is a test");return 0;
}

4、Poco::LogStream 日志流

Poco::LogStream为Logger提供了ostream接口。
流的所有特性都可用于格式化日志消息。
日志消息必须以std::endl(或CR或LF字符)结束。

可以设置消息的优先级

  • LogStream& priority(Message::Priority prio)
  • LogStream& fatal()
  • LogStream& critical()
  • LogStream& error()
  • LogStream& warning()
  • LogStream& notice()
  • LogStream& information()
  • LogStream& debug()
  • LogStream& trace
#include "Poco/LogStream.h"
#include "Poco/Logger.h"
using Poco::Logger;
using Poco::LogStream;
int main(int argc, char** argv)
{Logger& logger = Logger::get("TestLogger");LogStream lstr(logger);lstr << "This is a test" << std::endl;return 0;
}

5、日志格式化

5.1 说明

Poco::FormattingChannel 和 Poco::Formatter 负责格式化日志消息。
在将消息传播到下一个通道之前,Poco::FormattingChannel 将它接收到的每个消息传递给 Poco::Formatter。
Formatter是所有格式化器类的基类。
与通道一样,格式化器也可以使用属性进行配置。

5.2 PatternFormatter

PatternFormatter根据printstyle打印模式格式化消息

#include "Poco/ConsoleChannel.h"
#include "Poco/FormattingChannel.h"
#include "Poco/PatternFormatter.h"
#include "Poco/Logger.h"
#include "Poco/AutoPtr.h"
using Poco::ConsoleChannel;
using Poco::FormattingChannel;
using Poco::PatternFormatter;
using Poco::Logger;
using Poco::AutoPtr;
int main(int argc, char** argv)
{AutoPtr<ConsoleChannel> pCons(new ConsoleChannel);AutoPtr<PatternFormatter> pPF(new PatternFormatter);pPF->setProperty("pattern", "%Y-%m-%d %H:%M:%S %s: %t");AutoPtr<FormattingChannel> pFC(new FormattingChannel(pPF, pCons));Logger::root().setChannel(pFC);Logger::get("TestChannel").information("This is a test");return 0;
}

6、性能

创建消息需要花费一些时间(必须确定当前时间、当前进程ID和当前线程ID)。
创建一个有意义的消息可能需要更多的时间,因为字符串连接和数字格式等是必要的。
消息通常通过引用在通道链中传递。
特别的:formatingchannel和AsyncChannel创建消息的副本。

对于每个日志记录器,总是分别启用或禁用日志记录(或者更准确地说,设置日志级别),因此,一旦有了对日志记录器的引用,确定为特定日志记录器设置哪个日志级别是一个常数时间操作(简单的内联整数比较)。

获取对记录器的引用是一个具有对数复杂度的操作(基本上是std::map查找)。记录器的名称用作查找中的键,因此记录器名称的长度线性地影响查找时间(字符串比较)。然而,这一点可能可以忽略不计。

通常,对记录器(logger::get())的引用只在应用程序中获得一次。例如,在一个类中,可以在类的构造函数中获得对其日志记录器的引用,然后从此只使用该引用。
应该避免频繁调用Logger::get()。最好是对将要使用的每个记录器调用它一次,然后存储对记录器的引用以供以后使用。
日志性能取决于你要使用的通道。实际信道性能是高度依赖于系统的。

构造日志消息通常是一个耗时的操作,包括字符串创建、字符串连接、数字格式化等。
在这种情况下,使用is()、fatal()、critical()等方法,在构造消息之前检查消息是否会被记录是一个好主意。
还有一些宏在构造消息之前做检查:poco_fatal(msg), poco_critical(msg), poco_error(msg)

if (logger.warning())
{std::string msg("This is a warning");logger.warning(msg);
}

等同于:poco_warning(logger, “This is a warning”);

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

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

相关文章

微服务组件Sentinel的学习(2)

限流规则 流控模式直接模式关联模式链路模式 流控效果快速失败warm up排队等待 热点参数限流 流控模式 添加限流规则&#xff0c;可点击高级选项&#xff0c;有三种流控模式选择&#xff1a; 直接:统计当前资源的请求&#xff0c;触发闻值时对当前资源直接限流&#xff0c;也是…

Axure之动态面板轮播图

目录 一.介绍 二.好处 三.动态面板轮播图 四.动态面板多方式登录 五.ERP登录 六.ERP的左侧菜单栏 七.ERP的公告栏 今天就到这了哦&#xff01;&#xff01;&#xff01;希望能帮到你了哦&#xff01;&#xff01;&#xff01; 一.介绍 Axure中的动态面板是一个非常有用的组…

2024年视频监控行业发展趋势预测及EasyCVR视频分析技术应用

随着技术的改进&#xff0c;视频监控领域在过去十年迅速发展。与此同时&#xff0c;该行业正在通过先进创新技术&#xff08;如人工智能和云计算等技术&#xff09;的积极商业化&#xff0c;获得了新的增长机会。视频监控系统不再仅仅用于记录图像&#xff0c;而是已经成为全球…

力扣题目学习笔记(OC + Swift) 12. 整数转罗马数字

12. 整数转罗马数字 罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两个并列的 1。12 写做 XI…

LVM异常分析

环境信息 硬件环境 软件环境 相关软件包 云上鲲鹏RH220 操作系统&#xff1a;麒麟V10sp1-0711 系统自带多路径&#xff1a;multipath-tools-0.8.4-6 光纤连接华为存储Oceanstor18500 v5 内核版本&#xff1a;4.19.90 故障描述 云上鲲鹏RH220安装系统麒麟V10sp1-071…

ssm+vue的高校智能培训管理系统分析与设计(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的高校智能培训管理系统分析与设计&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

npm ,yarn 更换使用国内镜像源,阿里源,清华大学源

在平时开发当中&#xff0c;我们经常会使用 Npm&#xff0c;yarn 来构建 web 项目。但是npm默认的源的服务器是在国外的&#xff0c;如果没有梯子的话。会感觉特别特别慢&#xff0c;所以&#xff0c;使用国内的源是非常有必要的。 在这里插入图片描述 Nnpm&#xff0c; yarn …

1130 - Host “WIN-CA4FHERGO9J‘ is not allowed to connect to this MySQL server

1、知识小课堂 1.1 Mysql MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB公司开发&#xff0c;属于Oracle旗下产品。它是最流行的关系型数据库管理系统之一&#xff0c;在WEB应用方面&#xff0c;MySQL是最好的RDBMS (Relational Database Management System&am…

elementui + vue2实现表格行的上下移动

场景&#xff1a; 如上&#xff0c;要实现表格行的上下移动 实现&#xff1a; <el-dialogappend-to-bodytitle"条件编辑":visible.sync"dialogVisible"width"60%"><el-table :data"data1" border style"width: 100%&q…

antd+vue:tree组件:父级节点禁止选择并不展示选择框——基础积累

antdvue:tree组件&#xff1a;父级节点禁止选择并不展示选择框——基础积累 1.判断哪些是父节点&#xff0c;给父节点添加disabled属性——this.permissionList是数据源2.通过css样式来处理disabled的父节点3.完整代码如下&#xff1a; 最近在写后台管理系统的时候&#xff0c;…

[GXYCTF2019]Ping Ping Ping (文件执行漏洞)

本题考点&#xff1a; 1、命令联合执行 2、命令绕过空格方法 3、变量拼接 1、命令联合执行 ; 前面的执行完执行后面的| 管道符&#xff0c;上一条命令的输出&#xff0c;作为下一条命令的参数&#xff08;显示后面的执行结果&#xff09;|| 当前面的执行出错时&#xff08;为…

C#winform实现单页面自由切换窗口

一、介绍 这是效果图&#xff0c;由于视频压缩画质很差&#xff0c;看个效果就好。 左侧是打开界面的按钮&#xff0c;点击左侧按钮右侧打开不同窗口&#xff0c;点击右侧窗口中的按钮&#xff0c;也可以切换页面&#xff0c;可以方便的进行返回、下一页等操作。 每个窗口打开…

JavaSE语法之七:封装

文章目录 一、封装的概念二、访问限定符三、封装扩展之包1. 包的概念2. 导入包中的类3. 自定义包4. 常见的包 四、实现封装五、static成员1. 再谈学生类成员变量2. static修饰成员变量3. static修饰成员方法4. static成员变量初始化 六、代码块1. 代码块概念及其分类2. 普通代码…

香槟过了保质期还能喝吗?

香槟是起泡酒的高级代表&#xff0c;是浪漫和喜庆的化身&#xff0c;它浑身上下都散发着无穷的魅力。那么&#xff0c;这么精贵的葡萄酒有没有保质期&#xff0c;会不会变质呢&#xff1f;云仓酒庄的品牌雷盛红酒分享当然会。一瓶酒的生命离不开它的保存期限&#xff0c;酒的质…

理解Socket

前言 我在去年就学习过Java中Socket的使用&#xff0c;但对于Socket的理解一直都是迷迷糊糊的。看了网上很多关于Socket的介绍&#xff0c;看完还是不太理解到底什么是Socket&#xff0c;还是很迷。直到最近在学习计算机网络&#xff0c;我才对Socket有了一个更深地理解。之前一…

HBuilder X

选择一款编程软件有以下几个好处&#xff1a; &#xff08;1&#xff09;提高效率&#xff1a;编程软件通常强调代码编辑和自动完成&#xff0c;可以帮助程序员更快速、更准确地输入代码。 &#xff08;2&#xff09;降低错误率&#xff1a;编程软件还可以检测代码中的错误&a…

如何提升数据结构方面的算法能力?

谈及为什么需要花时间学算法&#xff0c;我至少可以列举出三个很好的理由。 (1)性能&#xff1a;选择正确的算法可以显著提升应用程序的速度。仅就搜索来说&#xff0c;用二分查找替 换线性搜索就能为我们帶来巨大的收益。 (2)安全性&#xff1a;如果你选用了错误的算法&…

设计模式之结构型设计模式(二):工厂模式 抽象工厂模式 建造者模式

工厂模式 Factory 1、什么是工厂模式 工厂模式旨在提供一种统一的接口来创建对象&#xff0c;而将具体的对象实例化的过程延迟到子类或者具体实现中。有助于降低客户端代码与被创建对象之间的耦合度&#xff0c;提高代码的灵活性和可维护性。 定义了一个创建对象的接口&…

【通用】Linux,VSCode,IDEA,Eclipse等资源相对位置

正文 不论是 IDEA、Linux、VSCode、cmd等等吧&#xff0c;都遵循这个规则&#xff1a; 如果以斜杠开头&#xff0c;表示从根开始找&#xff1a; IDEA的根是classpath&#xff08;classpath就是项目被编译后&#xff0c;位于 target下的 classes文件夹&#xff0c;或者位于ta…

软实力篇---第三篇

系列文章目录 文章目录 系列文章目录前言一、专业技能怎么写二、排版注意事项三、其他一些小tips前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、专业技能怎么…