1、编辑pom文件,添加日志依赖(可以不需要添加)
<!--引入日志依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
2、发现springboot已经整合了logback,不需要手工加入依赖包
找到项目的父pom文件:
<!-- 核心配置,包含默认依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
ctrl + 鼠标左键点进去,找到:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
ctrl + 鼠标左键点进去,找到:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
ctrl + 鼠标左键点进去,找到:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.1.8.RELEASE</version>
<scope>compile</scope>
</dependency>
ctrl + 鼠标左键点进去,找到:
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.11.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
从springboot的底层框架spring-boot-starter-logging可以看出,它依赖了3个框架分别为:slf4j、logback、log4j
3、在src/main/resources下建立logback.xml
<configuration>
<property name="log.base" value="/appserver/logs/myboot" />
<property name="app.name" value="myboot" />
<property name="pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{sessionId}] %-5level [%thread] %logger{80} :%msg%n" />
<!-- 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!--root -->
<appender name="root"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/${app.name}-root.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/${app.name}-root-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!--错误日志输出 -->
<appender name="errors"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<file>${log.base}/${app.name}-errors.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/${app.name}-errors-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 接口模块,的请求和响应信息 -->
<appender name="interface"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/${app.name}-interface.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/${app.name}-interface-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 业务模块,业务处理所有信息,以及调用外部 -->
<appender name="app"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/${app.name}-app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/${app.name}-app-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<appender name="catalina"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/catalina.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/%d{yyyy-MM-dd}/catalina-%i.%d{yyyy-MM-dd}.log.gz
</fileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>30MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 日志过滤 -->
<logger name="org.springframework">
<level value="info" />
</logger>
<logger name="org.apache">
<level value="info" />
</logger>
<logger name="org.apache.catalina" additivity="false">
<level value="info" />
<appender-ref ref="catalina" />
</logger>
<logger name="org.apache.coyote" additivity="false">
<level value="info" />
<appender-ref ref="catalina" />
</logger>
<!-- root级别控制 -->
<root level="info">
<appender-ref ref="root" />
<appender-ref ref="stdout" />
</root>
</configuration>
4、YamlTest添加测试方法testLog
package myboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.example.myboot.MybootApplication;
import com.example.properties.AcmeProperties;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybootApplication.class)
public class YamlTest {
protected static Logger logger = LoggerFactory.getLogger(YamlTest.class);
@Value("${model1.name}")
private String str1;
@Value("${model2.name}")
private String str2;
@Value("${key2}")
private String key2;
@Value("${application.name}")
private String env;
@Autowired
private AcmeProperties acmeProperties;
@Test
public void testYaml() {
System.out.println("model1.name: " + str1);
System.out.println("model2.name: " + str2);
System.out.println("acme.address: " + acmeProperties.getRemoteAddress());
System.out.println("acme.password: " + acmeProperties.getSecurity().getPassword());
System.out.println("acme.username: " + acmeProperties.getSecurity().getUsername());
}
@Test
public void testKey() {
System.out.println("key2 is: " + key2);
}
@Test
public void testProfiles() {
System.out.println("env is: " + env);
}
@Test
public void testLog() {
logger.info("testLog start...");
logger.info("env: {}", env);
logger.info("testLog end...");
}
}
5、执行结果
2019-10-09 18:12:34.144 [] INFO [main] org.springframework.boot.test.context.SpringBootTestContextBootstrapper :Neither @ContextConfiguration nor @ContextHierarchy found for test class [myboot.YamlTest], using SpringBootContextLoader
2019-10-09 18:12:34.149 [] INFO [main] org.springframework.test.context.support.AbstractContextLoader :Could not detect default resource locations for test class [myboot.YamlTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2019-10-09 18:12:34.274 [] INFO [main] org.springframework.boot.test.context.SpringBootTestContextBootstrapper :Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
2019-10-09 18:12:34.283 [] INFO [main] org.springframework.boot.test.context.SpringBootTestContextBootstrapper :Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@436813f3, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@74fe5c40, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@3febb011, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@10e31a9a, org.springframework.test.context.support.DirtiesContextTestExecutionListener@131774fe, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@158d2680, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@77847718, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@7f3b84b8, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@57a3af25, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@2b662a77]
2019-10-09 18:12:34.617 [] INFO [main] myboot.YamlTest :Starting YamlTest on DESKTOP-PB5DAU8 with PID 16208 (started by User in D:\workspace\study\myboot)
2019-10-09 18:12:34.617 [] INFO [main] myboot.YamlTest :The following profiles are active: model1,model2,dev
2019-10-09 18:12:35.838 [] INFO [main] org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor :Initializing ExecutorService 'applicationTaskExecutor'
2019-10-09 18:12:35.987 [] WARN [main] o.s.b.a.t.ThymeleafAutoConfiguration$DefaultTemplateResolverConfiguration :Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
2019-10-09 18:12:36.165 [] INFO [main] myboot.YamlTest :Started YamlTest in 1.842 seconds (JVM running for 2.481)
2019-10-09 18:12:36.412 [] INFO [main] myboot.YamlTest :testLog start...
2019-10-09 18:12:36.412 [] INFO [main] myboot.YamlTest :env: dev environment
2019-10-09 18:12:36.415 [] INFO [main] myboot.YamlTest :testLog end...
2019-10-09 18:12:36.423 [] INFO [Thread-2] org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor :Shutting down ExecutorService 'applicationTaskExecutor'
6、分析1:slf4j、logback、log4j的区别
1)logback、log4j:是日志实现框架,就是实现怎么记录日志的
2)slf4j:提供了java中所有的日志框架的简单抽象(日志的门面设计模式),说白了就是一个日志api(没有实现类),它不能单独使用,故必须结合logback、log4j日志框架来实现
7、分析2:springboot的日志搭配
1)springboot2.0默认采用了slf4j + logback的日志搭配
2)在开发过程中,我们都是采用了slf4j的api去记录日志,底层的实现是根据配置logback或log4j日志框架
参考资料:
https://www.cnblogs.com/zhangjianbing/p/8992897.html
注:最新代码上传至https://github.com/csj50/myboot