5.Spring配置日志log4j
本章目标
- 日志框架简介
- 什么是log4j
本章内容
我们入门 JAVA 的第一行代码就是一行日志,那你现在还在使用System.out.println("Hello,java")记录日志吗?
一、日志框架简介
1、日志的作用:
-
监视代码中变量的变化情况,把数据周期性记录到文件中供其他应用进行统计分析工作
大数据的兴起,使得大量的日志分析成为可能,ELK也让日志分析门槛降低了很多。日志中蕴含了大量的用户数据,包括点击行为,兴趣偏好等,用户画像对于公司下一步的战略方向有一定指引作用。
-
跟踪代码运行时轨迹,作为日后审计的依据,日志可以帮助开发或者运维人员快速定位错误位置,提出解决方案.
-
担当集成开发环境中的调试器的作用,向文件和控制台打印代码的调试信息
2、常见日志框架
常见的日志框架有:slf4j、j.u.l、JCL、Jboss-logging、log4j、logback、log4j2 ……
Spring 框架选择使用了 JCL 作为默认日志输出。而 Spring Boot 默认选择了 SLF4J 结合 LogBack
- slf4j:
The Simple Logging Facade for Java
即java的简单日志门面,slf4j是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如log4j、logback、log4j2、common-logging)。 - j.u.l:j.u.l是java.util.logging包的简称,是JDK在1.4版本中引入的Java原生日志框架。
- log4j:log4j是apache实现的一个开源日志组件。
- logback:logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现。
- log4j2:Log4j2是log4j 1.x和logback的改进版,据说采用了一些新技术(无锁异步等),使得日志的吞吐量、性能比log4j 1.x提高了10倍,并解决了一些死锁的bug,而且配置更加简单灵活
为什么需要日志接口,直接使用具体的实现不就行了吗? 接口用于定制规范,可以有多个实现,使用时是面向接口的(导入的包都是slf4j的包而不是具体某个日志框架中的包),即直接和接口交互,不直接使用实现,所以可以任意的更换实现而不用更改代码中的日志相关代码。 对于Java工程师来说,关于日志工具的使用,最佳实践就是在应用中使用如log4j2 + slf4j这样的组合来进行日志输出。这样做的最大好处,就是业务层的开发不需要关心底层日志框架的实现及细节,在编码的时候也不需要考虑日后更换框架所带来的成本。这也是日志接口(门面模式)所带来的好处。
二、什么是log4j
Log4j 作为Apache的一个开放源代码的项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件等我们期望它输出到的地方;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
1、Log4j配置
文件名为log4j.properties
log4j.rootCategory=DEBUG, stdout , R
###stdout parameter
#output type
#org.apache.log4j.ConsoleAppender
#org.apache.log4j.FileAppender
#org.apache.log4j.DailyRollingFileAppender
#org.apache.log4j.RollingFileAppender
#org.apache.log4j.WriterAppender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[User] %p [%t] %C.%M(%L) --> %m%n
通过配置文件可知,我们需要配置3个方面的内容:
1、根目录(级别和目的地);
2、目的地(控制台、文件等等);
3、输出样式。
2、Log4J主要有三个组件构成:
- Logger - 日志写出器,供程序员输出日志信息
- Appender - 日志目的地,把格式化好的日志信息输出到指定的地方去
- ConsoleAppender - 目的地为控制台的Appender
- FileAppender - 目的地为文件的Appender
- RollingFileAppender - 目的地为大小受限的文件的Appender
- Layout - 日志格式化器,用来把程序员的logging request格式化成字符串
- PatternLayout - 用指定的pattern格式化logging request的Layout
3、配置根Logger
log4j.rootLogger = [ level ] , appenderName, appenderName. .
-
其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。
-
Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
-
appenderName就是指B日志信息输出到哪个地方。您可以同时指定多个输出目的地。
A: FATAL 指出每个严重的错误事件将会导致应用程序的退出。 B: ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。 C: WARN 表明会出现潜在的错误情形。 D: INFO 一般和在粗粒度级别上,强调应用程序的运行全程。 E: DEBUG 一般用于细粒度级别上,对调试应用程序非常有帮助。 F: TRACE 最低等级,用于打开所有日志记录。
springboot中集成log4j非常简单,只需要3步就可以配置完成。
5、Appender组件
Appender 为日志输出目的地,Log4j提供的appender有以下几种
- org.apache.log4j.ConsoleAppender(控制台)
- org.apache.log4j.FileAppender(文件)
- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
6、Layout组件
Layout组件用来决定日志的输出格式,它有以下几种类型
- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息)
7、PatternLayout的格式
Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:
- %m 输出代码中指定的消息
- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
- %r 输出自应用启动到输出该log信息耗费的毫秒数
- %c 输出所属的类目,通常就是所在类的全名
- %t 输出产生该日志事件的线程名
- %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
- %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
8、示例
创建一个maven项目,测试
-
pom文件
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
log4j.properties
# Configure logging for testing: optionally with log file log4j.rootLogger=WARN, stdout # log4j.rootLogger=WARN, stdout, logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.append=false log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
-
创建接口ISpeaker
public interface ISpeaker { void say(); }
-
创建实现类,在代码中使用Log4j
import org.apache.log4j.Logger; public class HelloSpeaker implements ISpeaker { Logger logger = Logger.getLogger(HelloSpeaker.class); @Override public void say() { logger.info(“start method”); System.out.println(“hello speaker”); logger.info(“end method”); } }
注意导的是org.apache.log4j.Logger
9、通过动态代理优化日志
-
创建实现类,在代码中使用Log4j
public class EmployeeServiceImplTest { EmployeeService employeeService; @Before public void setUp() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml"); employeeService = applicationContext.getBean("employeeService", EmployeeService.class); employeeService = (EmployeeService) LogProxy.getProxy(employeeService); } @Test public void queryByPageHelper() { PageInfo<Employee> pageInfo = employeeService.queryByPageHelper(1, 5); } }
-
创建动态代理类
package com.woniuxy.service.impl; import org.apache.log4j.Logger; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class LogProxy { public static Object getProxy(Object target){ Class<?> aClass = target.getClass(); return Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Logger logger = Logger.getLogger(LogProxy.class); logger.info(method.getName()+"开始执行了"); Object result = method.invoke(target, args); logger.info("方法执行结束"); return result; } }); } }
本文来自博客园,作者:icui4cu,转载请注明原文链接:https://www.cnblogs.com/icui4cu/p/18839044