概述
我们在平时开发项目的时候想知道程序运行情况一般可以使用sysout.print();打印一些关键的代码或者通过debug查看运行状态,但是对于这种sysout.print();很现任出现代码多余。市场上也就出现许多记录运行状态的框架。例如Log4j、JUL、logback等,我们在项目中选择一个使用即可,但是如果过段时间出来一个新的日志框架,我们去掉之前框架,使用新的框架,又的修改api,我们是不是可以采用面向接口开发的思想,定制一个抽象层的日志接口层,分装统一的api,使用指定的日志框架,但是抽象层的接口一直使用日志抽象层,这样,我们想换日志框架的时候,直接导入新的依赖,无需修改已有的api。
1、市面上的日志框架以及日志抽象层类
日志抽象层框架:JCL、SLF4j、jboss-logging
日志实现层框架:log4j、logback、JUL、log4j2
开发中我们从日志抽象层框架选一个作为抽象接口层,再从日志实现层框架选一个作为实现类,用来记录我们项目中的日志
2、Springboot默认日志记录
在springboot中,boot默认抽象接口层使用slf4j,实现层用logback,当我们我们可以从项目中查看,如下
我创建了一个demo项目,pom中引入的依赖文件如下
项目中如果使用logback作为日志处理框架,logback 包括,logback-core、logback- classic、logback-access。logback-core是其它两个模块的基础模块,如果项目中引入了spring-boot-starter-web的依赖树,不再单独导入logback,可以看web依赖树
Springboot项目引入web模块后,底层默认配置好了slf4j+logback日志记录,我们只需通过日志记录器根据需要选择不同级别的日志打印输出即可,也可以同时使用spring的AOP思想自定义一个日志记录类记录日志
记录器方式如下,需要的地方记录即可
public class TestController{
//记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
//日志级别,由低到高,调整日志级别,只输出高级别日志,
logger.trace("这是trace跟踪信息");
logger.debug("这是debug调试信息");
//springboot默认输出info以后的级别,也就是root级别
logger.info("这是info自定义信息");
logger.warn("这是warn警告信息");
logger.error("这是error错误信息");
}
}
通过AOP思想记录日志
@Aspect//切面
@Component//组件
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 这里把切点切再controller(web)层下的每个方法
*/
@Pointcut("execution(* com.javayihao.myweb.controller.*.*(..))")
public void log() {
}
/**
* 执行com.javayihao.myweb.controller下所有的方法之前执行这个方法
* 获取要记录的url ip 请求的方法 以及请求时候所带的参数
* @param joinPoint
*/
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String url = request.getRequestURL().toString();
String ip = request.getRemoteAddr();
//类名.方法
String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
//参数
Object[] args = joinPoint.getArgs();
//调用自己封装的对象
RequestLog requestLog = new RequestLog(url, ip, classMethod, args);
logger.info("Request : {}", requestLog);
}
@After("log()")
public void doAfter() {
// logger.info("--------doAfter--------");
}
//执行com.javayihao.myweb.controller下所有的方法之后要执行的方法
@AfterReturning(returning = "result",pointcut = "log()")
public void doAfterRuturn(Object result) {
logger.info("Result : {}", result);
}
private class RequestLog {
private String url;
private String ip;
private String classMethod;
private Object[] args;
public RequestLog(String url, String ip, String classMethod, Object[] args) {
this.url = url;
this.ip = ip;
this.classMethod = classMethod;
this.args = args;
}
@Override
public String toString() {
return "{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", classMethod='" + classMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
我们没有配置任何其它配置,就看到在控制台下打印日志,Logback默认打印debug级别日志,但是我们注意到debug级别的日志没有记录下来,那是因为Spring Boot为Logback提供了默认的配置文件,base.xml,另外Spring Boot 提供了两个输出端的配置文件console-appender.xml和file-appender.xml,base.xml引用了这两个配置文件。所以Springboot默认日志级别是info,可以看到base.xml引用两个配置,
以下是从git上找到spring-boot用的base.xml
在这里, 您可以看到 Spring boot已通过将根记录器设置为INFO来覆盖 Logback 的默认日志记录级别, 这是我们在上面的示例中没有看到调试消息的原因。
可以简单的在application.properties中对logback配置
#修改指定包下的日志输出级别
logging.level.com.javayihao=trace
#当前项目下生成mylog.log日志记录输出的日志
#logging.file=mylog.log
#在指定的路径下输出日志
#logging.file=f:/mylog.log
#当前的磁盘根路径下创建spring文件家和里面的log文件夹,以spring.log作为日志文件名字
logging.path=/spring/log
#指定控制台输出日志的格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS}+++[%thread] %-5level %logger{50} - %msg%n
#执行日志文件中输出日志的格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS}===[%thread] %-5level %logger{50} - %msg%n
通过application.properties文件配置Logback,对于大多数Spring Boot应用来说已经足够了,但是对于一些大型的企业应用来说似乎有一些相对复杂的日志需求。在Spring Boot中你可以在logback.xml或者在logback-spring.xml中对Logback进行配置,相对于logback.xml,logback-spring.xml更加被偏爱。如果是其他名字,只需在application.propertions
中配置logging.config=classpath:logback-boot.xml使用自己的日志配置文件即可
这里贴上我自己常用的logback-spring.xml
class="ch.qos.logback.core.rolling.RollingFileAppender"> %d %p (%file:%line\)- %m%n
当然,我们也可以按部署环境配置日志级别,如下生产环境和测试环境使用不同的方式
3.总结
通过上面我们知道以后项目中如果要记录日志,不应该直接使用一个日志实现类记录,而是通过一个日志抽象层+一个日志抽象实现类,然后调用抽象层里面的接口记录接口,如下使用日志抽象类SLF4j
boot就是这么做的,这里主要总结一下日志抽象类SLF4j和其他日志实现类的使用
官网:https://www.slf4j.org/
使用方法,官网的一张图说的很明白
问题:x系统使用Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx框架实现,每个框架有不同的日志记录框架,如何统一使用都使用slf4j
解决方法
1、将系统中其他日志框架先排除出去;
2、用中间包来替换原有的日志框架;
3、我们导入slf4j其他的实现
比如我们要使用slf4j+log4j的方式来记录日志,依赖如下
org.springframework.boot
spring‐boot‐starter‐web
logback‐classic
ch.qos.logback
log4j‐over‐slf4j
org.slf4j
org.slf4j
slf4j‐log4j12
再如我们要使用slf4j+log4j2的方式来记录日志,依赖如下
org.springframework.boot
spring‐boot‐starter‐web
spring‐boot‐starter‐logging
org.springframework.boot
org.springframework.boot
spring‐boot‐starter‐log4j2
但是在boot项目中不推荐slf4j+log4j2或者slf4j+log4j组合来记录日志,springboot官方推荐slf4+logback
公众号 java一号 更多java实战项目资料、技术干活。更重要的是小猿愿成为你编程路上的一个朋友!
文章首发地址: www.javayihao.top
首发公众号: java一号