SpringBoot从入门到放弃,第二章

原创
2019/11/13 11:19
阅读数 376

SpringBoot从入门到放弃,第二章

一、Profile多环境支持

1、多Profile文件

我们在主配置文件编写的时候文件名可以是:application-{profile}.properties/yml

默认使用application.properties

2、yml支持多文档块方式

server:
  port: 8080
spring:
  profiles:
    active: dev ##激活dev配置块
    
---
server:
  port: 8081
spring:
  profiles: dev
  
---
server:
  port: 8082
spring:
  profiles: prod

3、激活指定的profile

1、在配置文件中指定 spring.profiles.active=dev
2、在JVM参数中激活 -Dspring.profiles.active=dev
3、命令行  java -jar boot-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

二、配置文件加载位置

springboot启动会扫描一下位置的application.properties或者application.yml文件作为springboot的默认配置文件

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

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。

我们也可以通过配置spring.config.location来改变默认配置

三、SpringBoot与日志

常见的日志框架:JUL JCL Jboss-loggin logback log4j log4j2 slf4j

接口抽象层 实现
JCL SLF4J JBOSS-LOGGING log4j JUL(java.util.logging) log4j2 logback

springboot选用SLF4J和logback

1、SLF4J使用

日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法

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、遗留问题

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

统一日志记录,即是是别的框架也一起使用SLF4J进行输出

(1)将系统中其他日志框架先排除出去

(2)用中间包来替换原有的日志框架

(3)再来导入slf4j其他的实现,如logback

3、SpringBoot日志关系

springboot开发需要添加如下日志依赖

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

但是呢,实际开发中我们不需要直接添加该依赖。

你会发现 spring-boot-starter 其中包含了 spring-boot-starter-logging ,该依赖内容就是 Spring Boot 默认的日志框架 logback 。

总结:

1》springboot底层也是使用了slf4j+logback的方式进行日志记录
2》springboot也把其他的日志都替换成了SLF4J
3》springboot也增加了中间替换包
4》如果我们要引入其他框架,一定要把这个框架的默认日志依赖移除掉
	例如 Spring (默认使用commons-logging)
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <exclusions>
    	<exclusion>
        	<groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4、日志使用

SpringBoot的默认配置写在,org.springframework.boot:spring-boot:2.2.1.RELEASE文件下的logging包中,如base.xml defaults.xml console-appender.xml 和 file-appender.xml等

springboot默认已经配置好了日志

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..");

}

日志级别由低到高

trace<debug<info<warn<error<fatal

如果设置为 WARN ,则低于 WARN 的信息都不会输出。

可以调整输入日志的级别,springboot默认使用info级别的日志

logging.file ,设置文件,可以是绝对路径,也可以是相对路径。如: logging.file=my.log

logging.path ,设置目录,会在该目录下创建 spring.log 文件,并写入日志内容,如: logging.path=/var/log

如果只配置 logging.file ,会在项目的当前路径下生成一个 xxx.log 日志文件。

如果只配置 logging.path ,在 /var/log 文件夹生成一个日志文件为 spring.log

注:二者不能同时使用,如若同时使用,则只有 logging.file 生效

默认情况下,日志文件的大小达到 10MB 时会切分一次,产生新的日志文件

因为在 springboot默认配置文件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>

更改日志级别

logging:
  # 分割文件设置 超过 10MB就进行分割,最大保留历史 90天
  maxFileSize: 10MB
  maxHistory: 90
  level:
  	root: INFO ##这里是用的root级别,即项目的所有日志,我们也可以使用package级别,即指定包下使用相应的日志级别
  path: log ##该属性用来配置日志文件的路径
  file: springboot.log ##该属性用来配置日志文件名,如果该属性不配置,默认文件名为spring.log
  pattern:
  	console: ##控制台输入的日志格式
  	file: ##文件中日志输出格式
  	
##logging.level.com.lee.boot.dao=WARN  将指定包下的日志级别设置为WARN
  	

日志输出格式:

%d表示日期时间
%thread表示线程名
%-5level级别从左显示5个字符宽度
%logger{50}表示logger名字最长50个字符,否则按照句点分隔
%msg:日志消息
%n是换行符

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

定义自己的log配置文件

默认配置文件名称:

( 默认的命名规则,并且放在 src/main/resources 下面即可;spring就不使用它默认的配置了)

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

如果你即想完全掌控日志配置,但又不想用 logback.xml 作为 Logback 配置的名字, application.yml 可以通过 logging.config 属性指定自定义的名字:

logging.config=classpath:logging-config.xml

logback-spring.xml是被springboot识别的

logback.xml是被logback日志框架识别的

所以推荐使用logback-spring.xml

logback-spring.xml可以使用springboot的根据test dev prod等环境来配置日志标签

同spring.profiles.active=dev等一同使用(激活环境)

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

5、logback配置文件组成

根节点<configuration></configuration>

根节点包含的属性:

scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true 。

scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当 scan 为 true 时,此属性生效。默认的时间间隔为1分钟。

debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 
运行状态。默认值为 false 。

根下面有5个子节点。

5.1)、<root>节点:

root 节点是必选节点,用来指定最基础的日志输出级别,只有一个 level 属性,用于设置打印级别,大小写无关 ,可选如下:TRACE,DEBUG,INFO,WARN,ERROR,ALL,OFF。 默认是DEBUG。

可以包含零个或多个元素,标识这个appender将会添加到这个loger。

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

5.2)、<contextName>设置上下文名称

每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过 %contextName 来打印日志上下文名称,一般来说我们不用这个属性,可有可无。

<contextName>logback</contextName>

5.3)、 <property>设置变量

用来定义变量值的标签, 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。

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

5.4)、<appender>

appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。

控制台输出 ConsoleAppender :

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    
    <contextName>logback-demo</contextName>
    
    <!--输出到控制台 ConsoleAppender-->
    <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
        <!--展示格式 layout-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d -1 %msg%n</pattern>
        </layout>
    </appender>
    
    <!--输出到控制台 ConsoleAppender-->
    <appender name="consoleLog2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d -2 %msg%n</pattern>
        </encoder>
    </appender>
    
    <!--指定最基础的日志输出级别-->
    <root level="INFO">
        <!--appender将会添加到这个loger-->
        <appender-ref ref="consoleLog1"/>
        <appender-ref ref="consoleLog2"/>
    </root>
</configuration>

可以看到 layout 和 encoder ,都可以将事件转换为格式化后的日志记录,但是控制台输出使用 layout ,文件输出使用 encoder 。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    
    <contextName>logback-demo</contextName>
    
    <!--输出到控制台 ConsoleAppender-->
    <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
        <!--展示格式 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>
    
    <!--指定最基础的日志输出级别-->
    <root level="INFO">
        <!--appender将会添加到这个loger-->
        <appender-ref ref="consoleLog1"/>
        <appender-ref ref="consoleLog2"/>
    </root>
    
</configuration>

<encoder> 表示对日志进行编码:

%d{HH: mm:ss.SSS}——日志输出时间
%thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
%-5level——日志级别,并且使用5个字符靠左对齐
%logger{36}——日志输出者的名字
%msg——日志消息
%n——平台的换行符

另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。 RollingFileAppender 用于切分文件日志:

<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    
    <!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高,
     所以我们使用下面的策略,可以避免输出 Error 的日志-->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <!--过滤 Error-->
        <level>ERROR</level>
        <!--匹配到就禁止-->
        <onMatch>DENY</onMatch>
        <!--没有匹配到就允许-->
        <onMismatch>ACCEPT</onMismatch>
    </filter>
    
    
    <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
     如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
     的日志改名为今天的日期。即,<File> 的日志都是当天的。
     -->
    <File>${logback.logdir}/info.${logback.appname}.log</File>
    
    
    <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
        <FileNamePattern>${logback.logdir}/info.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern>
        <!--只保留最近90天的日志-->
        <maxHistory>90</maxHistory>
        <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
        <!--<totalSizeCap>1GB</totalSizeCap>-->
    </rollingPolicy>
    
    
    <!--日志输出编码格式化-->
    <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">
    
    <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>Error</level>
    </filter>
    
    <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
     如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
     的日志改名为今天的日期。即,<File> 的日志都是当天的。
     -->
    
    <File>${logback.logdir}/error.${logback.appname}.log</File>
    
    <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
        <FileNamePattern>${logback.logdir}/error.${logback.appname}.%d{yyyy-MM-dd}.log</FileNamePattern>
        <!--只保留最近90天的日志-->
        <maxHistory>90</maxHistory>
        <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
        <!--<totalSizeCap>1GB</totalSizeCap>-->
    </rollingPolicy>
    
    <!--日志输出编码格式化-->
    <encoder>
        <charset>UTF-8</charset>
        <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
    </encoder>
    
</appender>

如果同时有 <File> 和 <FileNamePattern> ,根据日期分割日志。

如果要区分 Info 和 Error 级别的日志,那么需要使用过滤规则的策略。

5.5)、<loger>

<loger> 用来设置某一个包或者具体的某一个类的日志打印级别、以及指定 <appender> 。 <loger> 仅有一个 name 属性,一个可选的 level 和一个可选的 addtivity 属性。

name :用来指定受此loger约束的某一个包或者具体的某一个类。

level :用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。

addtivity :是否向上级loger传递打印信息。默认是true。

loger在实际使用的时候有两种情况

第一种:带有 loger 的配置,不指定级别,不指定 appender

logback-spring.xml 增加 loger 配置如下:

<logger name="com.dudu.controller"/>
<logger name="com.dudu.controller" /> 
将控制 controller 包下的所有类的日志的打印,但是并没用设置打印级别,
所以继承他的上级的日志级别 “info” 

没有设置 addtivity ,默认为true,将此 loger 的打印信息向上级传递;

没有设置 appender ,此 loger 本身不打印任何信息。

将 root 的打印级别设置为 “info” ,指定了名字为 “console” 的 appender 。

当执行 com.dudu.controller.LearnController 类的 login 方法时, LearnController 在包com.dudu.controller中,所以首先执行 `` ,将级别为 “info” 及大于 “info” 的日志信息传递给 root ,本身并不打印;

root 接到下级传递的信息,交给已经配置好的名为“console”的 appender 处理, “console” appender 将信息打印到控制台;

第二种:带有多个 loger 的配置,指定级别,指定 appender

ogback-spring.xml 增加 loger 配置如下:

<configuration>
    <!--logback.LogbackDemo:类的全路径 -->
    <logger name="com.lee.controller.LearnController" level="WARN" additivity="false">
        <appender-ref ref="console"/>
    </logger>
</configuration>

控制 com.lee.controller.LearnController 类的日志打印,打印级别为“ WARN ”;

additivity 属性为 false ,表示此 loger 的打印信息不再向上级传递;

6、项目中用到的日志文件配置

第一个

<?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包必须能够扫描到所以类,包括启动类 -->
	<logger name="com.redpigmall" level="debug" additivity="false">
		<appender-ref ref="redpigmall" />
	</logger>
	
	<root level="debug">
		<appender-ref ref="stdout" />
	</root>
	
</configuration>  

第二个

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!--滚动记录文件-->
    <appender name="eas" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>/Users/air/Desktop/project/project_my/logs/eas_log/eas.log</File>
        <!--滚动策略:按天生成日志,并自动压缩-->
        <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>

    <!--滚动记录文件-->
    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>/Users/air/Desktop/project/project_my/logs/eas_log/error.log</File>
        <!--滚动策略:按天生成日志,并自动压缩-->
        <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>

    <!--将日志输出到控制台,要具体控制哪些类要输出日志则用logger标签控制-->
    <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>

    <!--打印cn.xqd.eas包下的内容,日志级别为INFO-->
    <logger name="cn.xqd.eas" additivity="false" level="INFO" >
        <appender-ref ref="eas" />
        <appender-ref ref="console"/>
    </logger>

    <!--打印cn.xqd.eas.mapper包下的内容,即Mybatis相关日志信息,日志级别为DEBUG-->
    <logger name="cn.xqd.eas.dao" level="DEBUG"/>
</configuration>
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部