Java常用类
一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车,在这篇博客中 我会总结一些在学习和实际开发中用到的一些比较常见的类库和API。
常见的类库-日志
slf4j标准
日志库大概是我们接触到的最多的了,因为每一个项目中都需要他们,打印日志是服务器端应用中最重要的事情,日志也是了解你的程序到底发生了什么的唯一途径,在Java中尽管jdk附带自己的日志库,但是还有很多更好的选择可以使用,如Log4j,SLF4J和LogBack
在java中日志分为两个体系一个日志门面接口和日志框架作为接口的具体实现
而slf4j (Simple logging Facade for Java) 它是把不同的日志系统的实现进行了具体的抽象化,只提供了统一的日志使用接口,使用时只需要按照其提供的接口方法进行调用即可,由于它只是一个接口,并不是一个具体的可以直接单独使用的日志框架,所以最终日志的格式、记录级别、输出方式等都要通过接口绑定的具体的日志系统来实现,这些具体的日志系统就有log4j,logback,java.util.logging等,它们才实现了具体的日志系统的功能。,下面是他们的关系图
为什么要使用SLF4J?
- slf4j是一个日志接口,自己没有具体实现日志系统,只提供了一组标准的调用api,这样将调用和具体的日志实现分离,使用slf4j后有利于根据自己实际的需求更换具体的日志系统,比如,之前使用的具体的日志系统为log4j,想更换为logback时,只需要删除log4j相关的jar,然后加入logback相关的jar和日志配置文件即可,而不需要改动具体的日志输出方法,试想如果没有采用这种方式,当你的系统中日志输出有成千上万条时,你要更换日志系统将是多么庞大的一项工程。如果你开发的是一个面向公众使用的组件或公共服务模块,那么一定要使用slf4的这种形式,这有利于别人在调用你的模块时保持和他系统中使用统一的日志输出。
- slf4j日志输出时可以使用{}占位符,如,logger.info(“testlog: {}”, “test”),而如果只使用log4j做日志输出时,只能以logger.info(“testlog:”+“test”)这种形式,前者要比后者在性能上更好,后者采用+连接字符串时就是new 一个String 字符串,在性能上就不如前者。
1、slf4j是java的一个日志门面,实现了日志框架一些通用的api,log4j和logback是具体的日志框架。
2、log4j和logback他们可以单独的使用,也可以绑定slf4j一起使用。
单独使用,分别调用框架自己的方法来输出日志信息。绑定slf4j一起使用。调用slf4j的api来输入日志信息,具体使用与底层日志框架无关(需要底层框架的配置文件)。显然不推荐单独使用日志框架。假设项目中已经使用了log4j,而我们此时加载了一个类库,而这个类库依赖另一个日志框架。这个时候我们就需要维护两个日志框架,这是一个非常麻烦的事情。而使用了slf4j就不同了,由于应用调用的抽象层的api,与底层日志框架是无关的,因此可以任意更换日志框架。
参考自:https://www.cnblogs.com/hanszhao/p/9754419.html 写的很详细
单独使用log4j
引入jar,使用log4j时需要的jar为:log4j.jar。
-
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
定义配置文件log4j.properties或log4j.xml
-
### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG 级别以上的日志到=E://logs/error.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = E://logs/log.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ## [ %p ] 日期 %m%n 类名 具体的输出内容 ### 输出ERROR 级别以上的日志到=E://logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =E://logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
-
在具体的类中进行使用:
-
在需要日志输出的类中加入 static final Logger logger= Logger.getLogger(LogTest.class);
-
在需要输出日志的地方调用相应方法即可:logger.debug(“System ……”)
-
public static void main(String[] args) { logger.debug("this is degug message"); logger.info("this is info message"); logger.error("this is error message"); }
-
打印结果会按照properties文件输出
[DEBUG] 2021-05-05 21:11:12,065 method:log4j.LogTest.main(LogTest.java:14) this is degug message [INFO ] 2021-05-05 21:11:12,071 method:log4j.LogTest.main(LogTest.java:15) this is info message [ERROR] 2021-05-05 21:11:12,072 method:log4j.LogTest.main(LogTest.java:16) this is error message
-
输出到指定文件的error日志。
单独使用log4j2
-
引入jar
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.12.1</version> </dependency>
-
定义配置文件
log4j和log4j2 配置文件还是有些区别的
log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为".xml",".json"或者".jsn".
系统选择配置文件的优先级(从先到后)如下:
(1).classpath下的名为log4j2-test.json 或者log4j2-test.jsn的文件.
(2).classpath下的名为log4j2-test.xml的文件.
(3).classpath下名为log4j2.json 或者log4j2.jsn的文件.
(4).classpath下名为log4j2.xml的文件.
我们一般默认使用log4j2.xml进行命名。如果本地要测试,可以把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml即可。
官网上默认xml配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
这里level的等级为debug>info>error,如果level为error则只输出error信息,如果为debug级别,则会输出debug,info和error三种级别的日志消息。
-
官网的文档里列举了各种配置及注意事项以及各种详细说明
-
示例代码
public class Log4j2Test { static final Logger LOGGER = LogManager.getLogger(Log4j2Test.class); public static void main(String[] args) { LOGGER.debug("this is degug message"); LOGGER.info("this is info message"); LOGGER.error("this is error message"); } }
-
控制台输出结果
22:01:51.339 [main] DEBUG Log4j2Test - this is degug message
22:01:51.342 [main] INFO Log4j2Test - this is info message
22:01:51.342 [main] ERROR Log4j2Test - this is error message
Process finished with exit code 0
单独使用logback
logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现(即直接实现了slf4j的接口。
,logback一共有以下几个模块:
-
logback-core:其它两个模块的基础模块
-
logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging
-
logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能
-
同样,单独使用它时,需要引入以上jar,然后进行配置文件的配置,最后就是在相关类中进行使用,使用时加入以下语句:
private final static Logger logger = LoggerFactory.getLogger(Test.class); public static void main(String[] args) { logger.info("打印日志"); }
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
如果系统中之前已经使用了log4j做日志输出,想使用slf4j作为统一的日志输出,该怎么办呢?
总结
log4j并没有直接实现slf4j,所以就需要一个适配器slf4j-log4j12.jar,同样log4j2也需要一个适配器log4j-slf4j-impl来完成slf4j 调用和具体实现相分离
这里以log4j2为例:
-
首先添加适配器
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.9.0</version> </dependency>
-
修改Logger实例为slf4j
/*import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4j2Test {
//static final Logger LOGGER = LogManager.getLogger(Log4j2Test.class); //单独使用log4j2
static final Logger LOGGER =LoggerFactory.getLogger(Log4j2Test.class);//使用slf4j 打印日志
public static void main(String[] args) {
LOGGER.debug("this is degug message");
LOGGER.info("this is info message");
LOGGER.error("this is error message");
}
}
**在真实的项目中,日志远比这些要复杂,但是理清了他们关系以及原理就不那么懵了**