教程前面一部分概念来自该博客:https://www.cnblogs.com/xrq730/p/8619156.html 。对于slf4j不清楚是什么的可以先去看看。
开始正文
- Sfl4j是什么
slf4j是门面模式的典型应用,因此在讲slf4j前,我们先简单回顾一下门面模式,
门面模式,其核心为外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。用一张图来表示门面模式的结构为:
门面模式的核心为Facade即门面对象,门面对象核心为几个点:
- 知道所有子角色的功能和责任
- 将客户端发来的请求委派到子系统中,没有实际业务逻辑
- 不参与子系统内业务逻辑的实现
大致上来看,对门面模式的回顾到这里就可以了,开始接下来对SLF4J的学习。
- 我们为什么需要使用这个框架
我们为什么要使用slf4j,举个例子:
我们自己的系统中使用了logback这个日志系统
我们的系统使用了A.jar,A.jar中使用的日志系统为log4j
我们的系统又使用了B.jar,B.jar中使用的日志系统为slf4j-simple
这样,我们的系统就不得不同时支持并维护logback、log4j、slf4j-simple三种日志框架,非常不便。
解决这个问题的方式就是引入一个适配层,由适配层决定使用哪一种日志系统,而调用端只需要做的事情就是打印日志而不需要关心如何打印日志,slf4j或者commons-logging就是这种适配层,slf4j是本文研究的对象。
从上面的描述,我们必须清楚地知道一点:slf4j只是一个日志标准,并不是日志系统的具体实现。理解这句话非常重要,slf4j只做两件事情:
- 提供日志接口
- 提供获取具体日志对象的方法
slf4j-simple、logback都是slf4j的具体实现,log4j并不直接实现slf4j,但是有专门的一层桥接slf4j-log4j12来实现slf4j。
- 用法
在springmvc和maven环境下面。
-
- Maven里面引入一下配置
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
如果没有maven的,请导入如下jar
-
- 编写配置文件
配置log4j.propertier,可以使用log4j.xml进行配置。如果不去修改配置文件的默认位置,则需要把配置文件放到项目的根目录下面,不然框架找不到日志配置文件。
### 设置,文件必须放到这里目录###
### 把指定级别以上的日志信息输出到指定的一个或者多个位置。把DEBUG以上的日志输出到Console和File
#Console和File是自己自定义的名称,可以配置更多需要输出的目录
#OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL 紧急程度依次降低。all里面会包括了他上面的所有日志。debug里面会包含上面的所有日志。
log4j.rootLogger = DEBUG,Console,File
### 输出信息到控制抬 ###
log4j.appender.Console = org.apache.log4j.ConsoleAppender
log4j.appender.Console.Threshold = DEBUG
log4j.appender.Console.Target=System.out
log4j.appender.Console.Encoding=UTF-8
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/debug.log ###
log4j.appender.File = org.apache.log4j.DailyRollingFileAppender
#相对路径,d:/logs/debug.log
#如果写成这个:logs/debug.log ,那么log文件就在: tomcat85\bin\logs目录下面
#${log4jFileName}在项目启动的时候设置了
log4j.appender.File.File = logs/${log4jFileName}/info.log
log4j.appender.File.Append = true
log4j.appender.File.Threshold = INFO
#一天生成一个日志文件
log4j.appender.File.datePattern = '_'yyyy-MM-dd'.log'
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
注意:低层级的日志级别,会把比它高的级别日志也打印出来。上面的配置可以实现出现DEBUG及以上的日志时,在控制台会显示;出现了INFO及以上级别的日志的时候,会把日志保存在配置文件里面,配置文件一天一个。
下面演示一种把配置文件放到指定位置,且修改了日志文件的存放路径。在项目加载的时候,动态修改日志文件的配置文件的加载路径,并在系统变量里面加入一个日志文件路径变量:
public void initLog4j(ServletContextEvent servletContextEvent) {
//获取项目名称
String prefix = servletContextEvent.getServletContext().getRealPath("/");
//在系统变量里面设置log4jFilename,用来指定日志文件的路径
System.setProperty("log4jFileName", servletContextEvent.getServletContext().getContextPath());
String customerLog4jLocation = servletContextEvent.getServletContext().getInitParameter("log4jLocation");
if (StringUtils.isEmpty(customerLog4jLocation)) {
customerLog4jLocation = prefix + "WEB-INF\\classes\\log4j\\log4j.properties";
} else {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(new PathMatchingResourcePatternResolver());
try {
Resource[] resources = resolver.getResources(customerLog4jLocation);
PropertyConfigurator.configure(resources[0].getInputStream());
customerLog4jLocation = resources[0].getFile().getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
customerLog4jLocation = prefix + "WEB-INF\\classes\\log4j\\log4j.properties";
}
}
PropertyConfigurator.configure(customerLog4jLocation);
logger.debug("lsx log4j properties location:" + customerLog4jLocation);
}
-
- 在web里面配置一个系统变量
<context-param>
<param-name>log4jLocation</param-name>
<!--重新定位log4j配置文件位置-->
<param-value>classpath:log4j/log4j.properties</param-value>
</context-param>
-
- 代码里面使用
private final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.debug("debug");
log.info("info");
log.error("error");
}
以上配置文件,会让生成的日志文件在tomcat/bin/logs下面。