技术标签: # SpringBoot
目录
1)程序媛小张,开发了一个大型系统;
2)最开始系统中使用 System.out.println("");将关键数据打印在控制台
3)后面发现这样不容易查看之前的日志信息,于是小张开发了一个小框架来记录系统的一些运行时信息,将所有运行信息统一保存到了文件中,最原始的日志框架就叫“zhanglogging.jar”
4)在不断的开发实践中,小张觉得之前的框架需要改进,决定再加几个功能:如异步模式、自动分类归档等, 改进版的框架名字叫“zhanglogging-good.jar”
5)因为日志框架升级,以前的项目如果要使用新的日志框架,那就不得不修改源码,假设哪一天又升级了日志框架叫“zhanglogging-prefect.jar”,这样反复修改项目源码仍然不太合适
6)后面发现数据库 JDBC 的 数据库驱动的模式,由Java 提供统一的JDBC 接口,不同的数据库供应商提供实现,切换数据库的时候,只需要直接更新数据库驱动即可,并不需要修改源码
7)于是小张也写了一个统一的日志接口层,叫 “日志门面”(日志的一个抽象层),名字叫 logging-abstract.jar;给项目中导入具体的日志实现就行了;
1、市面上的日志框架;JUL、JCL(Apache 基金会的)、Jboss-logging、logback、log4j、log4j2、slf4j....
2、其中 SLF4j 与 Log4j 、 Logback 出自同一人之手,Logback 是 Log4j 的升级版;而 Log4j2 只是借用了 Log4j 的名号而已
3、SpringBoot 底层是 Spring 框架,而 Spring 框架默认是用 JCL,但是 SpringBoot 选用的是 SLF4j 和 logback,所以Spring Boot 的日志框架重点是学习使用 SLF4j 和 logback
4、所以为了开发日志系统扩展性更好的应用,就得从上表中左右两边各选择一个进行日志接口和实现进行开发,而且编码的时候应该调用左边的接口,而不是右边的实现,这样利于将来扩展。
1、官网地址:https://www.slf4j.org/,官网有非常详细的使用文档以及 Jar 包下载和 Maven 依赖配置 等
2、SLF4J Maven 依赖获取网址:https://mvnrepository.com/artifact/org.slf4j/slf4j-api
3、开发的时候,为了应用日志系统的将来的扩展,日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法;这样以后即使更换了实现类也没有关系。
4、通俗的说就是系统里面导入 slf4j 和 logback 的 jar 包之后,记录日志时应该调用的是 slf4j 的API 而不是 logback,官方 "Hello Wolrd" 例子代码如下:
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");
}
}
5、每一个日志的实现框架都有自己的配置文件,使用 slf4j 日志门面以后,配置文件还是要用日志实现框架自己本身的配置文件,如果使用的是 logback 实现,同理也要用 logback 的配置文件。
1、第一列“SLF4J unbound”:意思是如果应用中只导入“slf4j-api.jar日志门面”,没有导入slf4j实现时,则所有调用日志记录的方法都会无效,即不会有记录
2、第二列“SLF4J bound to logback-classic”:意思是如果导入了“slf4j-api.jar日志门面”及实现“logback-classic”的jar包,则调用SLF4J之后底层会以logback进行记录
3、第三列“SLF4J bound to log4j”:意思是导入了“slf4j-api.jar日志门面”及实现“log4j.jar”包之后,中间还要导入一个适配包“slf4j-log412.jar”,所以当应用中调用SLF4J记录日志的时候,会先经过适配包,最后调用实现包
4、因为 log4j 使用的时间很久了,之前并没有考虑到后来的星星之火 slf4j 可以燎原,所以导致现在使用时需要借助适配包。而logback 本身就是专门为 slf4 写的实现包,所以不需要任何适配 。后面的 JUL 也是同理,不再累述。
springboot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉。
1、在应用中的 pom.xml 中导入依赖
2、所有的依赖配置都可以从 Maven 中央仓库中找到:“https://mvnrepository.com/”
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
#指定输出信息的级别--以及输出的位置
log4j.rootLogger=DEBUG,console,logFile
#表示Logger不会在父Logger的appender里输出,默认为true
log4j.additivity.org.apache=true
#控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout.ConversionPattern=%5p [%t] (%c:%L) %d{yyyy-MM-dd HH:mm:ss,SSS} ---- %m%n
#日志文件
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=E:/logs_wmx/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
package www.wmx.com;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(App.class);
logger.info("Hello World");
logger.warn("严重警告.....");
}
}
控制台输出如下:
INFO [main] (www.wmx.com.App:12) 2018-07-14 13:40:28,643 ---- Hello World
WARN [main] (www.wmx.com.App:13) 2018-07-14 13:40:28,646 ---- 严重警告.....
Process finished with exit code 0
SpringBoot底层默认使用slf4j+logback的方式进行日志记录 ,这里简单介绍一下logback的使用。
logbac日志级别从低到高分别为TRACE, DEBUG, INFO, WARN, ERROR
我们一般是在类路径下建立一个logback.xml,也可命名为(logback-spring.xml , logback-spring.groovy , logback.xml ,logback.groovy)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>spring-boot-logging</contextName>
<property name="log.path" value="log" />
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 级别过滤 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/spring-boot-logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logback为java中的包 -->
<logger name="com.baiding"/>
</configuration>
1.根节点包含的属性
<configuration></configuration>
2. 设置上下文名称
<contextName>spring-boot-logging</contextName>
每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来打印日志上下文名称。
3.设置变量
用来定义变量值的标签, 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量
<property name="log.path" value="log" />
####4.子节点appender
appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。
控制台输出ConsoleAppender
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- 级别过滤 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
filter是一个过滤器,表示对输出到控制台的日记进行过滤。有两种过滤器,分别为LevelFilter 和ThresholdFilter。执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。返回DENY,日志将立即被抛弃不再经过其他过滤器;返回NEUTRAL,有序列表里的下个过滤器接着处理日志;返回ACCEPT,日志会被立即处理,不再经过剩余过滤器。
其中LevelFilter 为级别过滤器,根据日志级别进行过滤。其下有三个子节点,level表示过滤的级别,用于配置符合过滤条件的操作,ACCEPT符合级别的输出到控制台,用于配置不符合过滤条件的操作,DENY不符合的拒绝输出到控制台。
ThresholdFilter为临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。
表示对日志进行格式化
%d{HH:mm:ss.SSS} :日志的输出时间
%contextName : 上下文名称
%thread : 输出日志的进程名字,这在Web应用以及异步任务处理中很有用
%-5level : 日志级别,并且使用5个字符靠左对齐
%logger{36} : 日志输出者的名字(一般为类名),名字最长36个字符,否则按照句点分割
%msg : 具体的日志消息
%n :换行符
输出到文件RollingFileAppender
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/spring-boot-logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
<!-- 日志保存周期 -->
<maxHistory>30</maxHistory>
<!-- 总大小 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender用于切分文件日志。
其中file属性定义文件的带全路径的文件名,重要的是rollingPolicy的定义。
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"是最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责触发滚动
<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MMdd}.log.zip</fileNamePattern>定义了日志的切分方式——把每一天的日志归档到一个文件中,同理,可以使用%d{yyyy-MM-dd HH-mm}来定义精确到分的日志切分方式。
<maxHistory>30</maxHistory>表示只保留最近30天的日志
<totalSizeCap>1GB</totalSizeCap>用来指定日志文件的上限大小,例如设置为1GB的话,那么到了这个值,就会删除旧的日志
####5. 子节点root
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性,默认是DEBUG。
其中可以包含零个或多个元素,表示我们定义的appender将会添加到我们定义的loger子节点中。
6. 子节点loger
<loger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>
<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性
name:用来指定受此loger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity:是否向上级loger传递打印信息。默认是true。
<loger> 的实际使用有两种情况
第一种是不指定level,不指定appender
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<logger name="com.baiding.logging.SpringBootLoggingApplicationTests"/>
此logger指定了level为warn,addtivity为false,不在向上级传递打印信息,若设置了<appender-ref>属性,但没有设置addtivity为false,则com.baiding包下的日志会先在名为console的appender记录一次,之后传递给上级,root又会在名为console和file的appender记录一次,这样就打印了两次了。
Spring Boot在使用logback记录日志时,推荐使用logback-spring.xml的格式,这样的话,日志框架就不直接加载日志的配置项,而是由SpringBoot解析日志配置,就可以使用SpringBoot 的高级Profile功能
如下logback-spring.xml
<springProfile name="dev">
<logger name="com.baiding" level="info"/>
</springProfile>
<springProfile name="prod">
<logger name="com.baiding" level="warn"/>
</springProfile>
可以在不同的节点中使用springProfile
功能,用于指定某段配置只在某个环境下生效 。当然使用前,要激活profile。
开始在命令行中使用Git打开shell选择适用于您操作系统的shellMac OSX的TerminalWindows上的GitBashLinux上的Linux Terminal下载后打开就ok啦~接下来就通过命令行进行如下操作↓↓↓检查Git是否已经安装Mac和Linux上通常会预装Git。键入如下命令:git --version该命令会输出您计算机上所安装的Git版..._gitlab上新建项目时从仓库导入项目
伴随着“元宇宙室内空间”界定的逐步完善,为其基石之一的区块链应用链游戏也慢慢地转换成了游戏工作人员的生日蛋糕。当下链游飞船开发,农民世界链游开发可是针对依然处在界定成形初期的链游而言,要从传统的的设计开发逻辑思维上进行变换_区域链游戏飞船
内核Linux 内核是几乎所有的 Android 设备上极其重要的软件组成部分。本部分介绍了 Linux 内核开发和版本模型(如下)、稳定的长期支持 (LTS) 内核(包括所有 Android 设备都应使用稳定版本而非择优挑选补丁程序的原因)、内核配置和加固、接口和模块化内核要求(在 Android O 中推出)、内核调试和网络测试以及 SquashFS。Linux 内核开发Linux 内核是迄今...
大于1的整数如果可以分解为两个素数,则称为水数,例如6是水数,而12不是。首先我们需要创建一个项目,在项目中创建3个源代码。1,main.cpp放主函数2,head.h放class,一些必要的库函数,和一些调用所需要的函数3,head.cpp 对于class和 函数进行编辑如下:1,main.cpp#include"head.h"#include<iostream>using namespace std;int main(void){ wanshu a1; a1.se
本文作者:陈伟: 计算机博士,长期从事Linux系统技术与linux产业发展研究, 现任信息产业部软件与集成电路促进中心总工程师,是中国Linux基础平台(china linux basic platform)项目负责人。如果需要可以联系通过[email protected]联系他康华:计算机硕士,主要从事Linux操作系统内核、Linux技术标准、计算机安全、软件测试等领域的_计算机硕士 想从事操作系统开发
from time import sleepimport requests单模板发送地址url = ‘https://open.ucpaas.com/ol/sms/sendsms’账户sidsid = ‘你的账户sid’认证令牌token = ‘你的认证令牌’应用IDappid = ‘f241ee6a820c421d94118017f1600f1c’模板IDtemplatei..._open.ucpaas 短信
背景Jmeter有很多的配置元件可以定义变量值在测试过程中使用比如最常见的两个:用户自定义变量CSV数据文件设置配置元件主要是用于测试前配置,将配置转换为变量设置到Jmeter context中。而Jmeter默认并没有配置文件(.properties)读取器,但由于Jmeter是开源的,我们自己可以自定义一个配置元件来读取配置文件。目标启动Jmeter后,我们可以从配置元件中..._jmeter 插件扩展
RDB是redis常用持久化方式,通过执行bgsave命令,会在指定目录下生成rdb文件,默认名称为:dump.rdbdbfilename "dump.rdb"dir "/opt/app/redis/redis_6379/data"127.0.0.1:6379> bgsaveBackground saving started127.0.0.1:6379> exitdbadmin@_redis集群 迁移rdb文件不成功
场景:项目需求使用threeJS加载模型,模型数据放在OSS上;前端开发时,使用mock模拟接口数据。因为mock会对所有的http请求进行拦截,源码会根据是否有匹配的数据模板,来决定走原生XHR还是mockXHR,附上mock初始化request的源码:// 初始化 Request 相关的属性和方法Util.extend(MockXMLHttpRequest.prototype, { // https://xhr.spec.whatwg.org/#the-open()-method_this.custom.xhr.send
SpringCloudAlibaba集成Sentinel之热点参数限流的使用:SpringCloudAlibaba集成Sentinel之热点参数限流的使用_霸道流氓气质的博客-程序员宅基地在上面进行限流之后回调方法的设置时是通过如下方式如果要限制的接口较多总不能每一个接口都要写一个限流的处理回调方法吧,有没有可以全局设置通用的回调处理方法。实现业务和配置的低耦合。注:博客:霸道流氓气质的博客_程序员宅基地-C#,架构之路,SpringBoot领域博主关注公众号霸道的程序猿获取编程相关电子书、教_sentinel配置全局限流
由于当初安装系统设计不合理,有些分区的过小,以及网络通讯故障等造成日志文件速度增长等其他原因都可以表现为磁盘空间满,造成无法读写磁盘,应用程序无法执行等。下面就给你支几招(以/home空间满为例):1.定期对重要文件系统扫描,并作对比,分析那些文件经常读写#IS-IR/home>;files.txt#diff filesold.txt files.txt通过分析预测空间的增长情况,同时可以考..._bleachbit 清理后磁盘满了
原标题:你能分清电脑“休眠”和“睡眠”的区别吗?小A以前纠结过几个问题:电脑休眠是什么呢?为什么我的电脑里没这个选项?和电脑睡眠模式有什么区别? 01关机关闭所有程序,所有硬件全部停止工作并断电。重新开机时,所有硬件都要逐一加电自检,系统数据要从硬盘转入内存,开机时间较长。 02休眠将内存中的所有数据写入硬盘,包括未完成的各种工作,对硬件进行断电。开机时仍然需要进行系统自检,启动速度和“关机”模式..._计算机关闭盖子睡眠和休眠