java slf4j,Commons Logging与log4j,Logback,tinylog和异常配合使用

maven 官网仓库地址:maven repo

历史背景

1、日志是什么?

        日志是每天记录我们程序情况的。日志管理的目的是为了记录日志。

2、为什么会有日志?

        1、问题追溯,通过日志文件的记录可以使我们运维或者程序员快速查找问题根源。

        2、状态检测,检测我们系统状况,为项目出现的问题做好预警。

        3、安全审计

3、日志级别划分

日志级别一共分为五层:1、ERROR(错误) 2、WARNING(警告)3、INFO(常规状态)4、Debug(调试信息)5、Trace(调试,信息更详细)
 

private  static Logger logger=Logger.getLogger(String.valueOf(类名.class));//对哪里做检测
public static void main(String[] args) {
    logger.info("这是一个inf");//各种行为产生的日志级别以及相应的反馈。
    logger.warning("警告!警告!");                                                         
}

4、日志对性能的影响

        1、static对Logger实例化的影响。

        2、合理判定日志等级。

        3、优先使用参数,减少字符串的拼接。

Java自带的日志类库有很多,如jdk自带的Logger、log4j、Logback,他们之间互不兼容,slf4j是解决他们之间不兼容的适配器接口。

log4j、Logback非常相似,都是java日志的框架实现,但是为什么要在log4j之后又做一个Logback呢?

是因为:

1、Logback实现了对内核的重写使得性能提高,初始化内存加载小。

2、测试充分,经过数年间Logback经受了大大小小不同级别的测试。

3、  Logback-classic非常自然地实现了slf4j,所以切换到其他的日志狂阶非常容易只需要提供几个jar包就可以了。

4、自动从新加载配置文件。当我们对配置文件做了更改之后Logback-classic自动对我们的配置文件做加载。

5、Lilith不仅仅是能够对log事件观测,还能处理大量log文件。
 

异常处理最佳实践
在Java中,异常处理是一项非常重要的技能,良好的异常处理能够使程序更加健壮和可靠。以下是一些异常处理的最佳实践:

1.不要捕获所有异常。应该尽可能地具体地捕获异常,并处理它们。

2.不要在catch语句块中使用System.out.println()等输出语句。应该使用日志记录工具,例如Log4j、Slf4j等等。

3.不要在finally语句块中使用return语句。如果在finally语句块中使用return语句,那么可能会覆盖try语句块中的return语句,导致程序出现意外行为。

4.不要忽略异常。即使是无法处理的异常,也应该在日志中记录下来,以便于后续的调试和分析。

5.不要在循环中捕获异常。应该尽可能地将try-catch语句块放在循环外面。
 

slf4j和log4j

slf4j是通用的接口规范,log4j是具体实现的日志插件,slf4j也可以搭配其他实现的jar包一起使用。

一、What
1、slf4j和log4j的区别是什么?
log4j:log for java,Apache的一个开源项目,可以通过一个配置文件灵活配置日志的输送目的地、记录级别、输出格式。

slf4j:simple log facade for java,译为简单日志门面。官方介绍为,SLF4J作为各种日志系统的简单Facade或抽象,允许最终用户在部署时插入所需的日志框架。

总结:slf4j是通用的接口规范,log4j是具体实现的日志插件。

二、Why
1、log4j为什么搭配slf4j一起使用?
在知晓了slf4j是一套接口、log4j是一套具体实现后,就需要理解编程中“接口”的意义(统一规范、解耦、提高编程灵活性和可维护性)。
同理,在实现不同项目开发中“日志记录”的过程中,引入一套通用的日志接口规范后,既能兼容不同项目中使用的不同日志实现插件,又能在后期维护中随时更换其他的日志实现插件。

2、为什么推荐使用slf4j作为日志接口规范?
日志实现插件可以根据需要更换Logback或其他。日志接口规范还有Commons Logging,而slf4j的出现主要因为对前者的不满意,所以slf4j是对Commons Logging的改进。这里改进主要看一点:支持带占位符的字符串。
例如
 

 String me = "jettech";
    String you = "zhangsan";
    // Commons Logging 打印日志
    log.info("Hello, " + you + ". I'm " + me + ".");
    // slf4j 打印日志
    log.info("Hello, {}. I'm {}.", you, me);  
————————————————

三、How

1、log4j怎样搭配slf4j使用?

1.1 引入依赖

maven坐标为


        org.slf4j
        slf4j-api
        1.7.13
    
    
        org.slf4j
        slf4j-log4j12
        1.7.13
    

报错:

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
 

 检查自己的maven依赖,发现已经引入了slf4j-api-xx.jar了,这是为什么呢?其原因是,SLF4J本身不是一个日志实现库,而是一个日志库的抽象层,它必须依赖底层的日志库,SLF4J必须和其他日志库配合才能正常运行。一般来说,需要将抽象层(例如slf4j-api-xx.jar)+中间层(例如slf4j-log4j12)+实现层(例如log4j)这三层都配置好才能保证SLF4J正常运行。有的日志库也可以去掉中间层,例如slf4j-api和slf4j-simple就可以直接配合。

slf4j+log4j组合

1)抽象层+中间层+实现层的方式解决

        
            org.slf4j
            slf4j-api
            2.0.7
        
        
            org.slf4j
            slf4j-log4j12
            2.0.7
        





        
            log4j
            log4j
            1.2.17
        

还要加个log4j配置文件:log4j.properties 在resources资源下面创建

# Set root logger level to DEBUG and its only appender to console.
log4j.rootLogger=DEBUG, console

# console is set to be a ConsoleAppender.
log4j.appender.console=org.apache.log4j.ConsoleAppender

# console uses PatternLayout.
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold = DEBUG
log4j.appender.console.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

或者用slf4j+logback组合

    
            org.slf4j
            slf4j-api
            2.0.7
        
        
            ch.qos.logback
            logback-core
            1.3.0
        
        
            ch.qos.logback
            logback-classic
            1.3.0
        

2).抽象层+实现层的方式解决

引入下面的依赖,重新编译后就正常了,注意假如你从maven库里复制来的有 test,需要改成 compile或者就不加这个scope,不加的时候默认是compile,才能正常使用,test表示只有在测试环境下,才可以使用,而springboot是运行在main方法中,不属于测试环境,所以这个包就相当于没有加入依赖,也就没有被加载到。改成compile则表示编译的时候就会加载此jar包.

可以看到,无论是第一个错误还是第二个错误,都是依赖版本的问题,官方在Jdk1.9开始对于slf4j-api以及其他如slf4j-log4j12等依赖的绑定机制不同了,Jdk1.9对应slf4j-api以及slf4j-log4j12的版本从1.8.0开始。所以,为了解决以上两个问题,(如果我们使用的是Jdk1.8及以下)我们可以直接降低这两个依赖的版本到1.8.0以下,或者升级为Jdk1.9再使用这两个依赖的版本为1.8.0以上。
 

       
            org.slf4j
            slf4j-api
            1.7.30
        
        
        
            org.slf4j
            slf4j-log4j12
            1.7.30

        

!!!特别注意:以上slf4j-log4j12的scope要么直接去掉,要么改为compile,因为test代表只有在测试(@Test)的时候该依赖才起作用。 

1.2 创建一个静态常量的日志对象

在需要打印日志的Java Bean 中,定义属性成员:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
...
private static final Logger logger = LoggerFactory.getLogger(getClass());
...
...
logger.info("Hello, world.")

PS: 日志对象在类的实例中一般不需要修改和多份对象,所以常用static和final修饰。

2、常用的日志框架该如何组合选择?

常用组合方式为:
1. Slf4j + Logback
2. Slf4j + Log4j
3. Commons Logging + Log4j

PS: Logback更适合搭配Slf4j,不建议搭配Commons Logging, 因为Logback与Slf4j为同一作者,兼容性更好

你可能感兴趣的:(java,log4j,logback)