SpringBoot from getting started to giving up, Chapter 2

I. Profile multi environment support

1. Multiple Profile files

When we write the main configuration file, the file name can be: application-{profile}.properties/yml

application.properties is used by default

2. yml supports multi document block mode

server:
  port: 8080
spring:
  profiles:
    active: dev ##Activate dev configuration block
    
---
server:
  port: 8081
spring:
  profiles: dev
  
---
server:
  port: 8082
spring:
  profiles: prod

3. Activate the specified profile

1. Specify spring.profiles.active=dev in the configuration file
2. Activate - Dspring.profiles.active=dev in the JVM parameter
3. Command line java -jar boot-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

II. Configuration file loading location

Spring boot will scan the application.properties or application.yml file in the location as the default configuration file of spring boot

-file:./config/
-file:./
-classpath:/config/
-classpath:/

The above is in the order of priority from high to low. Files in all locations will be loaded, and the high priority configuration content will overwrite the low priority configuration content.

We can also change the default configuration by configuring spring.config.location

3. SpringBoot and log

Common log framework: Jul JCL JBoss logging logback log4j log4j2 slf4j

Interface abstraction layer Realization
JCL SLF4J JBOSS-LOGGING log4j JUL(java.util.logging) log4j2 logback

Select SLF4J and logback for springboot

1. SLF4J

The call of logging method should not directly call the log implementation class, but the method in the log abstraction layer

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

2. Remaining problems

a(slf4j+logback): Spring (commons-logging),Hibernate(jboss-logging),Mybatis,XXX

Unified logging, that is, other frameworks also use SLF4J for output

(1) exclude other log frames from the system first

(2) replace the original log framework with the tundish

(3) import other slf4j implementations, such as logback

3. Spring boot log relationship

The following log dependencies need to be added for spring boot development

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    <version>2.2.1.RELEASE</version>
    <scope>compile</scope>
</dependency>

However, in actual development, we do not need to add the dependency directly.

You will find that Spring Boot starter includes Spring Boot starter logging. This dependency is Spring Boot's default logging framework, logback.

Conclusion:

1. The bottom layer of springboot also uses slf4j+logback for logging
2. springboot also replaced SLF4J with other logs
3. springboot also adds an intermediate replacement package
4. If we want to introduce other frameworks, we must remove the default log dependency of this framework
	For example, Spring (common logging is used by default)
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <exclusions>
    	<exclusion>
        	<groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4. Log usage

The default configuration of spring boot is written in the logging package under the org.springframework.boot: spring boot: 2.2.1.release file, such as base.xml defaults.xml console-appender.xml and file-appender.xml

springboot has configured the log by default

private Logger logger = LoggerFactory.getLogger(SpringBootTest.class);

@Test
public void testLog(){

    logger.trace("this is trace log..");
    logger.debug("this is debug log..");
    logger.info("this is info log..");
    logger.warn("this is warn log..");
    logger.error("this is error log..");

}

Log level from low to high

trace<debug<info<warn<error<fatal

If it is set to WARN, no information below WARN will be output.

You can adjust the level of the input log. springboot uses the info level log by default

logging.file, setting file, can be absolute path or relative path. For example: logging.file=my.log

Logging.path, set the directory, in which the spring.log file will be created and the log content will be written, such as logging.path=/var/log

If only logging.file is configured, a xxx.log log file will be generated under the current path of the project.

If only logging.path is configured, a log file is generated in the / var/log folder as spring.log

Note: both cannot be used at the same time. If they are used at the same time, only logging.file will take effect

By default, when the log file size reaches 10MB, it will be cut once to generate a new log file

Because the following configuration is available in the springboot default configuration file file appender:

<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <fileNamePattern>${ROLLING_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
    <maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
</rollingPolicy>

Change log level

logging:
  # Split file is set to be more than 10MB, with a maximum history of 90 days
  maxFileSize: 10MB
  maxHistory: 90
  level:
  	root: INFO ##Here is the root level, that is, all the logs of the project. We can also use the package level, that is, the corresponding log level under the specified package
  path: log ##This property is used to configure the path of the log file
  file: springboot.log ##This attribute is used to configure the log file name. If this attribute is not configured, the default file name is spring.log
  pattern: 
  	console: ##Log format for console input
  	file: ##Log output format in file
  	
##logging.level.com.lee.boot.dao=WARN set the log level under the specified package to WARN
  	

Log output format:

%d Represents date time
%thread Represents the thread name
%-5level Level 5 character width from left
%logger{50}Express logger Names can be up to 50 characters long, otherwise they are separated by periods
%msg:Log message
%n Newline character

eg: 
	%d{yyyy-MM-dd HH:mm:ss.SSS} {%thread} %-5level %logger{50} -%msg%n

Define your own log profile

Default profile name:

(the default naming rules can be placed under src/main/resources; spring does not use its default configuration.)

logging system customization
logback logback-spring.xml OR logback.xml, etc
log4j2 log4j2-spring.xml OR log4j2.xml
java util logging logging.properties

If you want to fully control the log configuration, but do not want to use logback.xml as the name of Logback configuration, application.yml can specify a custom name through the logging.config property:

logging.config=classpath:logging-config.xml

logback-spring.xml is recognized by springboot

logback.xml is recognized by the logback log framework

So it is recommended to use logback-spring.xml

logback-spring.xml can use springboot to configure log labels according to test dev prod and other environments

Use with spring.profiles.active=dev, etc. (activate environment)

<springProfile name="dev,staging">
    .....
</springProfile>
<springProfile name="!dev">
    .....
</springProfile>

5. Composition of logback configuration file

Root node < configuration > < configuration >

Properties contained in the root node:

scan: when this property is set to true, if the configuration file changes, it will be reloaded. The default value is true.

scanPeriod: set the time interval for monitoring whether the configuration file has been modified. If no time unit is given, the default unit is milliseconds.
This property takes effect when scan is true. The default time interval is 1 minute.

debug: when this property is set to true, the logback internal log information will be printed out and the logback will be viewed in real time 
Operation status. The default is false.

There are five child nodes under the root.

5.1), < root > node:

The root node is a required node, which is used to specify the most basic log output level. There is only one level attribute, which is used to set the print level. The options are as follows: TRACE,DEBUG,INFO,WARN,ERROR,ALL,OFF The default is DEBUG.

It can contain zero or more elements, and the identifier will be added to the logger.

<root level="debug">
 <appender-ref ref="console" />
 <appender-ref ref="file" />
</root>

5.2), < contextname > set context name

Each logger is associated with a logger context. The default context name is "default". But you can use a record set to a different name to distinguish between different applications. Once it is set, it cannot be modified. You can print the log context name through% contextName. Generally speaking, we do not use this property. It is optional.

<contextName>logback</contextName>

5.3), < property > set variable

The label used to define the variable value has two attributes, name and value. The value of name is the name of the variable, and the value of value is the value defined by the variable. The value defined by is inserted into the logger context. After defining variables, you can make "${}" use variables.

<property name="logback.logdir" value="/Users/inke/dev/log/tomcat"/>
<property name="logback.appname" value="app"/>

5.4),<appender>

appender is used to format the log output node. It has two attributes: name and class. Class is used to specify which output policy is used. Console output policy and file output policy are commonly used.

Console output ConsoleAppender:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    
    <contextName>logback-demo</contextName>
    
    <!--Output to console ConsoleAppender-->
    <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
        <!--Display format layout-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -1 %msg%n</pattern>
        </layout>
    </appender>
    
    <!--Output to console ConsoleAppender-->
    <appender name="consoleLog2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d -2 %msg%n</pattern>
        </encoder>
    </appender>
    
    <!--Specify the most basic log output level-->
    <root level="INFO">
        <!--appender Will be added to this loger-->
        <appender-ref ref="consoleLog1"/>
        <appender-ref ref="consoleLog2"/>
    </root>
</configuration>

You can see that both layout and encoder can convert events to formatted log records, but layout is used for console output and encoder is used for file output.

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    
    <contextName>logback-demo</contextName>
    
    <!--Output to console ConsoleAppender-->
    <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
        <!--Display format layout-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
            </pattern>
        </layout>
        <!--
     <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>ERROR</level>
     </filter>
      -->
    </appender>
    
    <!--Specify the most basic log output level-->
    <root level="INFO">
        <!--appender Will be added to this loger-->
        <appender-ref ref="consoleLog1"/>
        <appender-ref ref="consoleLog2"/>
    </root>
    
</configuration>

< encoder > means to code the log:

%d{HH: mm:ss.SSS} -- log output time
%thread -- the process name of the output log, which is very useful in Web applications and asynchronous task processing
%-5level -- log level, with 5 characters left justified
%logger{36} -- the name of the log exporter
%msg -- log message
%n -- newline for platform

Another common log output to file, with the application running longer and longer, the log will grow more and more, it is not a good way to output them to the same file RollingFileAppender is used to segment file logs:

<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    
    <! -- if you just want info level logs, just fi lt ering info will still output Error logs, because the Error level is high,
     So we use the following strategy to avoid outputting the Error log -- >
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <! -- fi lt er error -- >
        <level>ERROR</level>
        <! -- prohibit matching -- >
        <onMatch>DENY</onMatch>
        <! -- no matching is allowed -- >
        <onMismatch>ACCEPT</onMismatch>
    </filter>
    
    
    <! -- log name. If there is no File attribute, only the File path rule of FileNamePattern will be used
     If there are < File > and < filenamepattern > at the same time, the log of the day is < File > and will automatically set today
     The log of was renamed today's date. That is, the logs of < File > are of the same day.
     -->
    <File>${logback.logdir}/info.${logback.appname}.log</File>
    
    
    [! -- scroll policy, scroll by timebasedrollingpolicy -- >
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <! -- file path, which defines the log segmentation method -- archive the daily logs to a file to prevent the logs from filling the entire disk space -- >
        <FileNamePattern>${logback.logdir}/info.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern>
        <! -- only keep the last 90 days of logs -- >
        <maxHistory>90</maxHistory>
        <! -- used to specify the maximum size of the log file. When this value is reached, the old log will be deleted -- >
        <!--<totalSizeCap>1GB</totalSizeCap>-->
    </rollingPolicy>
    
    
    <! -- log output code format -- >
    <encoder>
        <charset>UTF-8</charset>
        <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
    </encoder>
    
</appender>


<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    
    <! -- if you just want Error level logs, you need to filter them. The default is info level, thresholdfilter -- >
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>Error</level>
    </filter>
    
    <! -- log name. If there is no File attribute, only the File path rule of FileNamePattern will be used
     If there are < File > and < filenamepattern > at the same time, the log of the day is < File > and will automatically set today
     The log of was renamed today's date. That is, the logs of < File > are of the same day.
     -->
    
    <File>${logback.logdir}/error.${logback.appname}.log</File>
    
    [! -- scroll policy, scroll by timebasedrollingpolicy -- >
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <! -- file path, which defines the log segmentation method -- archive the daily logs to a file to prevent the logs from filling the entire disk space -- >
        <FileNamePattern>${logback.logdir}/error.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern>
        <! -- only keep the last 90 days of logs -- >
        <maxHistory>90</maxHistory>
        <! -- used to specify the maximum size of the log file. When this value is reached, the old log will be deleted -- >
        <!--<totalSizeCap>1GB</totalSizeCap>-->
    </rollingPolicy>
    
    <! -- log output code format -- >
    <encoder>
        <charset>UTF-8</charset>
        <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
    </encoder>
    
</appender>

If there are < File > and < filenamepattern > at the same time, the logs are divided according to the date.

If you want to distinguish logs at the Info and Error levels, you need to use a policy of filtering rules.

5.5),<loger>

< logger > is used to set the log printing level of a package or a specific class, and to specify < appender >. < logger > has only one name attribute, one optional level and one optional addtivity attribute.

name: used to specify a package or a specific class constrained by this logger.

Level: used to set the printing level regardless of case: TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF. There is also a special value of implied or the synonym NULL, which represents the level of enforcing the superior. If this property is not set, the current logger inherits the level of the parent.

addtivity: whether to transfer printing information to the superior logger. The default is true.

There are two situations when using the logger

First: configuration with logger, no level or appender specified

logback-spring.xml add loger configuration as follows:

<logger name="com.dudu.controller"/>
<logger name="com.dudu.controller" /> 
It will control the printing of logs of all classes under the controller package, but it does not use to set the printing level,
So inherit his superior's log level "info" 

addtivity is not set. It is true by default. The printing information of this logger is passed to the superior;

The appender is not set, and the logger itself does not print any information.

Set the print level of root to "info" and specify an appender named "console".

When executing the login method of com.dudu.controller.LearnController class, LearnController is in the package com.dudu.controller, so first execute ` ', pass the log information with the level of "info" and greater than "info" to root, and do not print itself;

root receives the information from the lower level, and hands it to the configured appender named "console" for processing. The "console" appender prints the information to the console;

Second: configuration with multiple loger s, specify the level, and specify the appender

ogback-spring.xml add logger configuration as follows:

<configuration>
    <!--logback.LogbackDemo: Full path of class -->
    <logger name="com.lee.controller.LearnController" level="WARN" additivity="false">
        <appender-ref ref="console"/>
    </logger>
</configuration>

Control the log printing of com.lee.controller.LearnController, with the printing level of "WARN";

The additivity property is false, which means that the printing information of this logger is no longer passed to the superior;

6. Log file configuration used in the project

First

<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds">

	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d{yyyy-M-d HH:mm:ss} %t %p %m%n</pattern>
		</encoder>
	</appender>
	
	<appender name="springboot"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- <Encoding>UTF-8</Encoding> -->
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<FileNamePattern>logs/logback/springboot_%d{yyyy-M-d}.log
			</FileNamePattern>
			<MaxHistory>10</MaxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>%d{yyyy-M-d HH:mm:ss} %t %p %m%n</pattern>
		</encoder>
	</appender>
	
	<appender name="redpigmall"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<FileNamePattern>logs/logback/redpigmall_%d{yyyy-M-d}.log
			</FileNamePattern>
			<MaxHistory>10</MaxHistory>
		</rollingPolicy>
		<encoder>
			<pattern>%d{yyyy-M-d HH:mm:ss} %t %p %m%n</pattern>
		</encoder>
	</appender>

	<logger name="org.springframework.boot" level="debug"
		additivity="false">
		<appender-ref ref="springboot" />
	</logger>
	
	<!-- name Package must be able to scan all classes, including startup classes -->
	<logger name="com.redpigmall" level="debug" additivity="false">
		<appender-ref ref="redpigmall" />
	</logger>
	
	<root level="debug">
		<appender-ref ref="stdout" />
	</root>
	
</configuration>  

The second

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!--Rolling record file-->
    <appender name="eas" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>/Users/air/Desktop/project/project_my/logs/eas_log/eas.log</File>
        <!--Rolling strategy:Generate log by day,And automatically compress-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/Users/air/Desktop/project/project_my/logs/eas_log/eas.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <append>true</append>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--Rolling record file-->
    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>/Users/air/Desktop/project/project_my/logs/eas_log/error.log</File>
        <!--Rolling strategy:Generate log by day,And automatically compress-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/Users/air/Desktop/project/project_my/logs/eas_log/error.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <append>true</append>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--Output log to console,To specifically control which classes to output logs logger Label control-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoding>UTF-8</encoding>
        <encoder>
            <pattern>[%d{HH:mm:ss.SSS}][%p][%c{40}][%t] %m%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="console"/>
        <appender-ref ref="error"/>
    </root>

    <!--Printing cn.xqd.eas Content under package,Log level is INFO-->
    <logger name="cn.xqd.eas" additivity="false" level="INFO" >
        <appender-ref ref="eas" />
        <appender-ref ref="console"/>
    </logger>

    <!--Printing cn.xqd.eas.mapper Content under package,Namely Mybatis Related log information,Log level is DEBUG-->
    <logger name="cn.xqd.eas.dao" level="DEBUG"/>
</configuration>

Keywords: Programming Spring xml SpringBoot encoding

Added by tim on Wed, 13 Nov 2019 06:54:26 +0200