一、简单介绍五种

  1. 最简单的方式,就是system.println.out(error) ,这样直接在控制台打印消息了;
  2. Java.util.logging ; 在JDK 1.4 版本之后,提供了日志的API ,可以往文件中写日志了;
  3. log4j , 最强大的记录日志的方式。 可以通过配置 .properties 或是 .xml 的文件, 配置日志的目的地,格式等等;
  4. commons-logging, 最综合和常见的日志记录方式, 经常是和log4j 结合起来使用;
  5. logback是java的日志开源组件,是log4j创始人写的,性能比log4j要好;

二、java.util.logging

1、简介
Java 中的 Logging API 让 Java 应用可以记录不同级别的信息,Java 为此定时了8个级别,它们是分别SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST 以及 ALL. 它们按照优先级降序排列,在应用运行的任何时间点,日志级别可以被更改。

2、重要类说明

  • Logger 对外发布的日志记录器,应用系统可以通过该对象完成日志记录的功能
  • Level 日志的记录级别
  • LoggingMXBean 接口对象,对外发布的日志管理器
  • LogRecord 日志信息描述对象
  • LoggerManager 日志管理器
  • Filter 日志过滤器,接口对象,在日志被 Handler 处理之前,起过滤作用
  • Handler 日志处理器,接口对象,决定日志的输出方式
  • Formatter 日志格式化转换器,接口对象,决定日志的输出格式

3、Filter
作为一个接口, Filter:为所记录的日志提供日志级别控制以外的细粒度控制。

4、Handler

  • Handler负责从Logger中取出日志消息并将消息发送出去,比如发送到控制台、文件、网络上的其他日志服务或操作系统日志等。
  • Handler也具有级别概念,用于判断当前Logger中的消息是否应该被发送出去,可以使用定义好的各种日志级别(如Level.OFF表示关闭等)。
  • 除了级别概念,一个Handler还可以具有自己的过滤器(Filter)、格式化器(Formatter)、错误管理器(ErrorManager)以及编码字符集等,这些属性借助LogManager中的配置信息进行设置。
  • Handler是一个抽象类,需要根据实际情况创建真正使用的具体Handler(如ConsoleHandler、FileHandler等),实现各自的publish、flush以及close等方法。

Handler 实现类说明

  1. MemoryHandler,将当前日志信息写入内存缓冲区中同时丢弃缓存中以前的内容。将内存缓冲区中的信息转发至另一个Handler
  2. StreamHandler所有基于I/O流的Handler的基类,将日志信息发送至给定的java.io.OutputStream中
  3. ConsoleHandler,将消息发送至System.err(而非System.out),默认配置与其父类StreamHandler相同。
  4. FileHandler,将消息发送至单个一般文件或一个可回滚的文件集合。可回滚文件集中的文件依据文件大小进行回滚,久文件名称通过当前文件名附加编号0、1、2等方式依次进行标示。默认情况下日志信息都存放在I/O缓冲中,但如果一条完整的日志信息会触发清空缓冲的动作。与其父类StramHandler不同的是,FileHandler的默认格式器是java.util.logging.XMLFormatter:
  5. SocketHandler,负责将日志信息发送至网络,默认情况下也采用java.util.logging.XMLFormatter格式。

二、log4j

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码.

1、引入log4j

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

2、配置log4j.properties或者log4j.xml

log4j.rootLogger=debug,Console,File
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.Console.Threshold = DEBUGlog4j.appender.File=org.apache.log4j.RollingFileAppender
log4j.appender.File.File=logfile.log
log4j.appender.File.MaxFileSize=512KB
log4j.appender.File.MaxBackupIndex=3
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.File.Threshold = DEBUG
  • 这里指定了日志输出的级别 debug.
  • Console, File指定日志输出的目的地。 这两个名字可以随便取,比如 A或B都可以。 实际的配置是 org.apache.log4j.ConsoleAppender 和RollingFileAppender 用于指定是控制台还是文件。 另外还指定了输出的格式, 已经产生的file 的规则。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration><!-- 将日志信息输出到控制台 --><appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"><!-- 设置日志输出的样式 --><layout class="org.apache.log4j.PatternLayout"><!-- 设置日志输出的格式 --><param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" /></layout><!--过滤器设置输出的级别--><filter class="org.apache.log4j.varia.LevelRangeFilter"><!-- 设置日志输出的最小级别 --><param name="levelMin" value="WARN" /><!-- 设置日志输出的最大级别 --><param name="levelMax" value="ERROR" /><!-- 设置日志输出的xxx,默认是false --><param name="AcceptOnMatch" value="true" /></filter></appender><!-- 将日志信息输出到文件,但是当文件的大小达到某个阈值的时候,日志文件会自动回滚 --><appender name="RollingFileAppender" class="org.apache.log4j.RollingFileAppender"><!-- 设置日志信息输出文件全路径名 --><param name="File" value="D:/log4j/RollingFileAppender.log" /><!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --><param name="Append" value="true" /><!-- 设置保存备份回滚日志的最大个数 --><param name="MaxBackupIndex" value="10" /><!-- 设置当日志文件达到此阈值的时候自动回滚,单位可以是KB,MB,GB,默认单位是KB --><param name="MaxFileSize" value="10KB" /><!-- 设置日志输出的样式 --><layout class="org.apache.log4j.PatternLayout"><!-- 设置日志输出的格式 --><param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" /></layout></appender><!-- 将日志信息输出到文件,可以配置多久产生一个新的日志信息文件 --><appender name="DailyRollingFileAppender" class="org.apache.log4j.DailyRollingFileAppender"><!-- 设置日志信息输出文件全路径名 --><param name="File" value="D:/log4j/DailyRollingFileAppender.log" /><!-- 设置日志每分钟回滚一次,即产生一个新的日志文件 --><param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm'.log'" /><!-- 设置日志输出的样式 --><layout class="org.apache.log4j.PatternLayout"><!-- 设置日志输出的格式 --><param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" /></layout></appender>

输出方式appender一般有5种:
org.apache.log4j.RollingFileAppender(滚动文件,自动记录最新日志)
org.apache.log4j.ConsoleAppender (控制台)
org.apache.log4j.FileAppender (文件)
org.apache.log4j.DailyRollingFileAppender (每天产生一个日志文件)
org.apache.log4j.WriterAppender (将日志信息以流格式发送到任意指定的地方)

日记记录的优先级priority,优先级由高到低分为 OFF ,FATAL ,ERROR ,WARN ,INFO ,DEBUG ,ALL。
Log4j建议只使用FATAL ,ERROR ,WARN ,INFO ,DEBUG这五个级别。

log4j layout日志信息格式

  • org.apache.log4j.HTMLLayout(以HTML表格形式布局),
  • org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
  • org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
  • org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

PatternLayout是我们以后推荐使用的,很灵活; 有个ConversionPattern属性,灵活配置输出属性:

  • %c 输出所属类的全名,可在修改为 %d{Num},Num类名输出的维(如:“org.apache.elathen.ClassName”,%C{2}将输出elathen.ClassName)
  • %d输出日志时间其格式为 %d{yyyy-MM-dd HH:mm:ss,SSS},可指定格式 如 %d{HH:mm:ss}
  • %l 输出日志事件发生位置,包括类目名、发生线程,在代码中的行数
  • %n 换行符
  • %m输出代码指定信息,如info(“message”),输出message
  • %p输出优先级,即 FATAL ,ERROR 等
  • %r 输出从启动到显示该log信息所耗费的毫秒数
  • %t 输出产生该日志事件的线程名
//使用方式
package com;
import org.apache.log4j.Logger;public class Test {private static Logger logger = Logger.getLogger(Test.class);  /** * @param args */  public static void main(String[] args) {  // System.out.println("This is println message.");  // 记录debug级别的信息  logger.debug("This is debug message.");  // 记录info级别的信息  logger.info("This is info message.");  // 记录error级别的信息  logger.error("This is error message.");  }  }

三、 commons-logging

1、简介
Commons-logging 也是Apache 提供的日志jar档。Apache Commons Logging(JCL) 提供了一个简单的日志抽象,允许开发人员使用特定的日志实现。JCL可以使用其他的日志实现,包括Log4J、Avalon LogKit(Avalon的日志框架)、JDK logging(JUL)。

2、配置
① 在classpath下寻找配置文件commons-logging.properties,并使用文件中org.apache.commons.logging.Log属性定义的Log实现类;
② 如果找不到commons-logging.properties文件,查找系统环境变量org.apache.commons.logging.Log对应的Log实现类;
③ 否则,查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类;
④ 否则,使用JDK自身的日志实现类(JDK1.4以后才有日志实现类);
⑤ 否则,使用commons-logging自己提供的一个简单的日志实现类SimpleLog;

3、依赖
<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version>
</dependency>

4、简单实现
新建commons-logging.properties文件,放置在classpath根路径下
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog代码中使用
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class CommonsTest {private final static Log logger = LogFactory.getLog(CommonsTest.class);public static void main(String[] args) {logger.debug("DEBUG ...");logger.info("INFO ...");logger.error("ERROR ...");}
}

5、Commons-logging的解耦功能
commons-logging最核心有用的功能是解耦,它的SimpleLog实现性能比不上其他实现,如log4j等。
①添加依赖

<dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version>
</dependency>
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

②修改配置文件:修改commons-logging.properties文件:显示地指定log4j

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

并添加log4j.properties的配置文件:

log4j.rootLogger=DEBUG,console# 输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
# 设置输出样式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
# 日志输出信息格式为
log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n

③代码中使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class CommonsTest {private final static Log logger = LogFactory.getLog(CommonsTest.class);public static void main(String[] args) {logger.debug("DEBUG ...");logger.info("INFO ...");logger.error("ERROR ...");}
}

四、logback

1、介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网站:http://logback.qos.ch。它当前分为下面下个模块:

  • logback-core:其它两个模块的基础模块
  • logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging
  • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

2、logback取代log4j的理由:

  1. 更快的实现:Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。
  2. Logback-classic非常自然实现了SLF4j:Logback-classic实现了SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了slf4j
    , 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。
  3. 自动重新加载配置文件,当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。

3、配置

  • Logger、appender及layout
    Logger作为日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。
    Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、PostreSQL、
    Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。   
    Layout 负责把事件转换成字符串,格式化的日志信息的输出。

  • logger context   
    各个logger 都被关联到一个 LoggerContext,LoggerContext负责制造logger,也负责以树结构排列各logger。其他所有logger也通过org.slf4j.LoggerFactory 类的静态方法getLogger取得。 getLogger方法以 logger名称为参数。用同一名字调用LoggerFactory.getLogger 方法所得到的永远都是同一个logger对象的引用。

  • 有效级别及级别的继承   
    Logger 可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN 和ERROR,定义于ch.qos.logback.classic.Level类。如果 logger没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。

  • 打印方法与基本的选择规则   
    打印方法决定记录请求的级别。例如,如果 L 是一个 logger 实例,那么,语句 L.info("…")是一条级别为 INFO的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger的有效级别为 q,只有则当 p>=q时,该请求才会被执行。
    该规则是 logback 的核心。级别排序为: TRACE < DEBUG < INFO < WARN < ERROR

4、配置详解

(1)根节点configuration包含下面三个属性:

  • scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  • scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  • debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <!--其他配置省略-->
</configuration> 

(2)子节点contextName:用来设计上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。

<configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>myAppName</contextName> <!--其他配置省略-->
</configuration>

(3)子节点property :用来定义变量值,它有两个属性name和value,通过定义的值会被插入到logger上下文中,可以使“${}”来使用变量。

  • name: 变量的名称
  • value: 变量的值
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="APP_Name" value="myAppName" /> <contextName>${APP_Name}</contextName> <!--其他配置省略-->
</configuration>

(4)子节点timestamp:获取时间戳字符串,他有两个属性key和datePattern

  • key: 标识此timestamp 的名字;
  • datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/> <contextName>${bySecond}</contextName> <!-- 其他配置省略-->
</configuration>

(5)子节点appender:负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名

  • ConsoleAppender 把日志输出到控制台,有以下子节点:  
    encoder:对日志进行格式化。(具体参数稍后讲解 )  
    target:字符串System.out(默认)或者System.err(区别不多说了)
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <!-- 表示把 >= DEBUG级别的日志都输出到控制台 --><root level="DEBUG"> <appender-ref ref="STDOUT" /> </root>
</configuration>

(5.1)RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:

  • file:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值;
  • append:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true;
  • rollingPolicy:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名;
    -fileNamePattern:必要节点,包含文件名及“%d”转换符,“%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM};
  • maxHistory:可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且maxHistory是6,则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除;
  • maxFileSize:这是活动文件的大小,默认值是10MB;
  • prudent:当为true时,不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有两个限制,1不支持也不允许文件压缩,2不能设置file属性,必须留空;
  • triggeringPolicy: 告知 RollingFileAppender 合适激活滚动;
<!--表示每天生成一个日志文件,保存30天的日志文件-->
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root>
</configuration>

(6)子节点loger:用来设置某一个包或具体的某一个类的日志打印级别、以及指定appender。loger仅有一个name属性,一个可选的level和一个可选的addtivity属性。可以包含零个或多个appender-ref元素,标识这个appender将会添加到这个loger;

  • name: 用来指定受此loger约束的某一个包或者具体的某一个类。
  • level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前loger将会继承上级的级别。
  • addtivity: 是否向上级loger传递打印信息。默认是true。同loger一样,可以包含零个或多个appender-ref元素,标识这个appender将会添加到这个loger。
(7)常用logger配置
<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" /><!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>

java打印日志的几种方式相关推荐

  1. [Java]打印数组的三种方式

    1.for循环打印 第一种方式: for(int i=0;i<arr.length;i++){System.out.println(arr[i]); } 第二组方式:foreach增强型for循 ...

  2. centos6配置日志外发_CentOS6下记录后台操作日志的两种方式

    CentOS6下记录后台操作日志的两种方式 平时为了记录登录CentOS Linux系统的操作命令,需要将操作日志记录下来,下面介绍两种方式 1.利用script以及scriptreplay工具 sc ...

  3. Java 实现抽奖的两种方式

    Java实现抽奖的两种方式 方式一:随机数在哪个区间内返回区间下标 方式二:随机数加入区间点集合排序返回随机数下标 代码示例: ①抽奖入参类型为BigDecimal: package com.cfay ...

  4. Java解析Xml的三种方式总结

    转自:http://blog.csdn.net/zjf280441589/article/details/50613881 XML解析技术有两种 DOM SAX DOM方式  根据XML的层级结构在内 ...

  5. 12月18日云栖精选夜读 | Java 中创建对象的 5 种方式!...

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  6. Java中创建对象的几种方式

    Java中创建对象的几种方式 1.使用new创建对象,在堆上创建. 2.克隆 3.反序列化 4.反射创建对象 5.NIO中可以使用本地方法直接分配堆外内存. 转载于:https://www.cnblo ...

  7. 采集Nginx日志的几种方式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | https://dwz.cn/ofiCxRK0 ...

  8. 闭眼入!采集 Nginx 日志的几种方式!

    作者:xiejava 来源:cnblogs.com/xiejava/p/12452434.html 由于nginx功能强大,性能突出,越来越多的web应用采用nginx作为http和反向代理的web服 ...

  9. Java中创建对象的四种方式

    为什么80%的码农都做不了架构师?>>>    Java中创建对象的四种方式 (1) 用new语句创建对象,这是最常见的创建对象的方法.    (2) 运用反射手段,调用java.l ...

最新文章

  1. 机房收费系统总结【3】-数据库细节
  2. 理解 ajax、fetch和axios
  3. 在pcduino上实现图像识别的程序
  4. 计算机科学与技术第二章ppt,计算机科学与技术-编译原理-第二章重点.ppt
  5. C#/.Net Core/WPF框架初建(国际化、主题色)
  6. [vue] 说说你觉得认为的vue开发规范有哪些?
  7. 七. 多线程编程11.线程的挂起、恢复和终止
  8. FSR 是提高性能和视觉效果
  9. 融入常识知识的生成式对话摘要
  10. 使用ffmpeg步骤
  11. focal loss小结
  12. 在腾讯云 EMR 上使用 GooseFS 加速大数据计算服务
  13. 从零开始学习深度学习,推荐几本书单,建议按照先后顺序排名进行学习
  14. 温习古文之生于忧患,死于安乐
  15. MATLAB APP Designer设计之图片处理
  16. win10系统崩溃怎么修复_手把手教你“无损”修复win10系统
  17. 爆款制作获1200w播放,B站UP主+品牌如何迈入2023
  18. 漫画 | 程序员大战公务员!到底谁猛?
  19. 宝洁网测管道题技巧_宝洁笔试网测小技巧分享
  20. 苹果公司战略管理分析

热门文章

  1. 脉宽调制(PWM)的基本原理及其应用实例
  2. 机器学习需要掌握的数学知识点---详细整理
  3. Win10 1809美化
  4. 存储过程报错:Error converting data type varchar to bigint.
  5. 企业微信私聊安全吗?管理员看得到吗?
  6. 开箱即用,这些 Vue3 后台管理系统模板绝对让你爽歪歪!
  7. 十分钟实现灭霸打响指灰飞烟灭的效果,android路由器app
  8. Autojs脚本 最新加密工具 Autojs庖丁 3.2.0 去强制更新
  9. 第一章:costmap_2d代价地图生成原理
  10. (三)Animation创建动画