作者:风中的百合香迷人 | 来源:互联网 | 2023-10-13 06:35
市面上的日志框架日志门面(日志的抽象层)日志实现JCL(JakartaCommonsLogging)(2014)SLF4j(SimpleLoggingFacadeforJava)
市面上的日志框架
日志门面 (日志的抽象层) |
日志实现 |
JCL(Jakarta Commons Logging)(2014) SLF4j(Simple Logging Facade for Java) jboss-logging |
Log4j JUL(java.util.logging) Log4j2 Logback |
补充说明:Logback, Log4j , Log4j2都出于同一作者之手, 但Logback更新。
在使用日志时, 都是选一个左边门面(抽象层)、再选一个右边的实现;该用方法时只用右边门面方法 ,
Spring框架选用JCL日志,需要引用commons-logging.jar , SpringBoot框架选用 SLF4j和logback;
每一个日志的实现框架都有自己的配置文件。就算使用slf4j门面,日志实现框架用的还是自己本身的配置文件;
总结:
1)、SpringBoot底层也是使用slf4j+logback的方式进行日志记录;
2)、SpringBoot也把其他的日志都替换成了slf4j;
3)、中间替换包(以jck-over-slf4j.jar为例),其实内部被换成了SLF4JLogFactory
@SuppressWarnings("rawtypes")
public abstract class LogFactory {
static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
static LogFactory logFactory = new SLF4JLogFactory();
4)、如果我们要引入其他框架?一定要把这个框架的默认日志依赖移除掉,比如Spring框架用的是commons-logging;
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<exclusions>
<exclusion>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
exclusion>
exclusions>
dependency>
日志测试
logback测试用例
@RunWith(SpringRunner.class)
@SpringBootTest
public class LoggingTest {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
ApplicationContext ac;//注入上下文
@Test
public void contextLoads() {
//日志的级别;
//由低到高 trace//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
logger.trace("这是trace日志...");
logger.debug("这是debug日志...");
//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别(用了info级别)
logger.info("这是info日志...");
logger.warn("这是warn日志...");
logger.error("这是error日志...");
}
public ApplicationContext getAc() {
return ac;
}
public void setAc(ApplicationContext ac) {
this.ac = ac;
}
}
application.properties配置文件
# springboot日志的配置文件,本处由application.properties中的spring.profiles.active=logging来启用本文件
# 指定log文件,也可以写固定的绝对路径, 如果file和path都指定了,那么file优先级更高
#logging.file=springboot02.log
# 指定log路径,默认使用使用spring.log作为文件名, 如果以/开头,则在当前磁盘的根目录下创建路径,如果不以/开头,则在当前应用目录下创建日志路径
logging.path=/springbootlog01/logs
# 日志占位符说明
# %d表示日期时间
# %thread表示线程名
# %-5level:级别从左显示5个字符宽度,左对齐
# %logger{50} 表示logger包路径加类名字最长50个字符
# %msg:日志消息
# %n是换行符
# 在控制台输出的日志的格式
logging.pattern.cOnsole=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定com下的所有日志输出级别为trace
logging.level.com=trace
logback默认配置位于该目录: spring-boot-1.5.14.RELEASE.jar!/org/springframework/boot/logging/logback/defaults.xml和base.xml
日志配置
给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了
日志系统 |
自定义文件 |
说明 |
|
Logback |
logback.xml |
直接被日志框架识别,不经过springboot , 不支持SpringBoot的profile功能. |
|
Logback |
logback-spring.xml |
日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能 |
|
Log4j2 |
log4j2.xml |
|
|
Log4j2 |
log4j2-spring.xml |
|
|
JDK (Java Util Logging) |
logging.properties |
|
|
logback-spring.xml 使用SpringBoot的profile功能如下:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%npattern>
springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%npattern>
springProfile>
layout>
appender>
日志切换
|
slf4j+log4j的方式 (已亲测) processon地图 |
log4j2 (未亲测) |
|
pom.xml内容 |
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
exclusion>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>log4j-over-slf4jartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
dependency>
|
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-loggingartifactId>
<groupId>org.springframework.bootgroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-log4j2artifactId>
dependency>
|
|
说明 |
此处直接去掉了slf4j的实现 , 必须换成log4j的实现 |
此处引用的是spring-boot-starter-log4j2场景启动器,替换了spring-boot-starter-logging场景启动器的功能 |
|
|
|
|
|
自己喜欢的简易风
日志配置
# 在控制台输出的日志的格式
logging.pattern.cOnsole=%d{yyyy-MM-dd HH:mm:ss}\t↓%n%msg%n
日志格式
2019-12-04 09:59:37 ↓
Root WebApplicationContext: initialization completed in 813 ms
2019-12-04 09:59:38 ↓
Initializing ExecutorService 'applicationTaskExecutor'
2019-12-04 09:59:38 ↓
Tomcat started on port(s): 8080 (http) with context path '/es'
2019-12-04 09:59:38 ↓
在日志上打印请求唯一log标识
重点语句
org.slf4j.MDC;
MDC.put(TRACE_ID, traceId);
MDC.remove(TRACE_ID);
使用拦截器实现
package com.interceptors.logtag.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
/**
* 日志拦截器
*
* @author zetting
* @date 2018/8/27 11:18
*/
@Component
public class LogInterceptor extends HandlerInterceptorAdapter {
private Logger log = LoggerFactory.getLogger(this.getClass());
/**
* 日志跟踪标识
*/
private static final String TRACE_ID = "TRACE_ID";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String traceId = UUID.randomUUID().toString();
if (StringUtils.isEmpty(MDC.get(TRACE_ID))) {
MDC.put(TRACE_ID, traceId);
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
MDC.remove(TRACE_ID);
}
}
【Springboot之搜索日志妙招】在日志上打印请求唯一log标识==>https://www.jianshu.com/p/b74ade8bbb57