SpringBoot3快速入门笔记
springboot3简介
SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用(说明:SpringBoot底层是Spring)
大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术
特性:
● 快速创建独立 Spring 应用
○ SSM:导包、写配置、启动运行
● 直接嵌入Tomcat、Jetty or Undertow(无需部署 war 包)【Servlet容器】
○ linux java tomcat mysql: war 放到 tomcat 的 webapps下
○ jar: java环境; java -jar
● 重点:提供可选的starter,简化应用整合
○ 场景启动器(starter):web、json、邮件、oss(对象存储)、异步、定时任务、缓存...
○ 导包一堆,控制好版本。
○ 为每一种场景准备了一个依赖; web-starter(只需要导入这一个,所有有关web的依赖都会导入且会控制好版本)。mybatis-starter
● 重点:按需自动配置 Spring 以及 第三方库
○ 如果这些场景我要使用(生效)。这个场景的所有配置都会自动配置好。
○ 约定大于配置:每个场景都有很多默认配置。
○ 自定义:配置文件中修改几项就可以
● 提供生产级特性:如 监控指标、健康检查、外部化配置等
○ 监控指标、健康检查(k8s)、外部化配置
● 无代码生成、无xml
总结:简化开发,简化配置,简化整合,简化部署,简化监控,简化运维。
快速入门
* 步骤:
* ①创建maven项目,在pom.xml中导入依赖
* 1 所有springboot项目都必须继承自 spring-boot-starter-parent
* <parent>
* <groupId>org.springframework.boot</groupId>
* <artifactId>spring-boot-starter-parent</artifactId>
* <version>3.0.5</version>
* </parent>
* 2 导入web开发的场景启动器
* <dependency>
* <groupId>org.springframework.boot</groupId>
* <artifactId>spring-boot-starter-web</artifactId>
* </dependency>
* ②创建启动SpringBoot项目的主入口程序
* 随便是那个类都可以,在该类上添加@SpringBootApplication注解,代表这是一个SpringBoot应用程序
* 在方法中通过SpringApplication调用静态方法run(当前类.class,args)
* ③正常创建三层架构
代码举例
Pom.xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 所有springboot项目都必须继承自 spring-boot-starter-parent --> <parent><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.5</version></parent> <groupId>com.atguigu</groupId> <artifactId>boot3-01-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging><dependencies><!-- web开发的场景启动器 --> <dependency><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><!-- SpringBoot应用打包插件--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
<!--
mvn clean package把项目打成可执行的jar包
java -jar demo.jar启动项目
-->
…
启动类:
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}
注意
springboot的打包插件:
<!-- SpringBoot应用打包插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${project.parent.version}</version> <!-- 与父模块一致 -->
</plugin>
</plugins>
</build>
在target目录下可以找到两个jar包,在文件路径下打开它,在改文件路径下打开终端窗口输入java -jar 文件名(回车);即可运行该项目
依赖管理机制
补充:
● 官方提供的场景:命名为:spring-boot-starter-*(官方默认提供了许多场景)
● 第三方提供场景:命名为:*-spring-boot-starter
starter(spring-boot-starter-web--->也叫web场景启动器)的starter(spring-boot-starter)
1、为什么导入starter-web所有相关依赖都导入进来?
(只要导入一个场景启动器,这个场景启动器会自动吧它用到的所有功能的以及相关的依赖导入)
● 开发什么场景,导入什么场景启动器。
● maven依赖传递原则。A-B-C: A就拥有B和C
● 导入 场景启动器。 场景启动器 自动把这个场景的所有核心依赖全部导入进来
2、为什么版本号都不用写?
● 每个boot项目都有一个父项目spring-boot-starter-parent
● parent的父项目是spring-boot-dependencies
● 父项目 (spring-boot-dependencies)版本仲裁中心,把所有常见的jar的依赖版本都声明好了。
● 比如:mysql-connector-j
3、自定义版本号
● 利用maven的就近原则
○ 直接在当前项目properties标签中声明父项目用的版本属性的key
○ 直接在导入依赖的时候声明版本
4 第三方的jar包
● boot父项目没有管理的需要自行声明好版本号
自动配置机制
初步理解
● 自动配置的 Tomcat、SpringMVC 等
○ 导入场景,容器中就会自动配置好这些场景的核心组件。
代码测试:
@SpringBootApplication
public class Boot302DemoApplication {
public static void main(String[] args) {
//java10:局部变量类型的自动推断
var ioc = SpringApplication.run(Boot302DemoApplication.class, args);
//1 获取ioc容器中所有组件的名字------->SpringBoot把以前配置的核心组件都给我们配置好了。
String[] names = ioc.getBeanDefinitionNames();
for (String name:names) {
System.out.println("name = " + name);
}
}
}
● 默认的包扫描规则
○ @SpringBootApplication 标注的类就是主程序类
○ SpringBoot只会扫描主程序所在的包及其下面的子包,自动的component-scan功能
○ 自定义扫描路径
方式1 @SpringBootApplication(scanBasePackages = "com.atguigu")-----------用属性
方式2 @ComponentScan("com.atguigu") 直接指定扫描的路径
本质: @SpringBootApplication=@ComponentScan+@SpringBootConfiguration+@EnableAutoConfiguration
● 配置默认值
○ 配置文件的所有配置项是和某个类的对象值进行一一绑定的。
○ 绑定了配置文件中每一项值的类: 属性类。
○ 比如:
■ ServerProperties绑定了所有Tomcat服务器有关的配置
■ MultipartProperties绑定了所有文件上传相关的配置
● 按需加载自动配置
○ 导入场景spring-boot-starter-web
○ 场景启动器除了会导入相关功能依赖,导入一个spring-boot-starter,是所有starter的starter,基础核心starter
○ spring-boot-starter导入了一个包 spring-boot-autoconfigure。包里面都是各种场景的AutoConfiguration自动配置类
○ 虽然全场景的自动配置都在 spring-boot-autoconfigure这个包,但是不是全都开启的。
■ 导入哪个场景就开启哪个自动配置
总结: 导入场景启动器、触发 spring-boot-autoconfigure这个包的自动配置生效、容器中就会具有相关场景的功能
常用注解
组件注解
@Configuration 、//说明这是一个配置类
@SpringBootConfiguration 、 //代表此类是一个Springboot的配置类
@Bean、//替代bean标签
@Scope、//组件默认是单实例的,可以通过此注解设置单个还是多个
@Controller、 @Service、@Repository、@Component
@Import、//导入第三方组件到ioc容器(给容器中方指定类型的组件,组件的名字默认是全类名)
@ComponentScan
组件注册步骤:
1、@Configuration 编写一个配置类
2、在配置类中,自定义方法给容器中注册组件。配合@Bean
3、或使用@Import 导入第三方的组件
条件注解
如果注解指定的条件成立,则触发指定行为
@ConditionalOnXxx
@ConditionalOnClass(name="类的权限定符"):如果类路径中存在这个类,则触发指定行为
@ConditionalOnMissingClass:如果类路径中不存在这个类,则触发指定行为
@ConditionalOnBean:如果容器中存在这个Bean(组件),则触发指定行为
@ConditionalOnBean(value=组件类型,name=组件名字):判断容器中是否有这个类型的组件,并且名字是指定的值
@ConditionalOnMissingBean:如果容器中不存在这个Bean(组件),则触发指定行为
注意:这些注解还可以用在类上;
放在类级别:如果注解判断生效整个配置配才生效;
放在方法级别:只是单独对这个方法判断;
场景:
● 如果存在FastsqlException这个类,给容器中放一个Cat组件,名cat01,
● 否则,就给容器中放一个Dog组件,名dog01
● 如果系统中有dog01这个组件,就给容器中放一个 User组件,名zhangsan
● 否则,就放一个User,名叫lisi
测试代码:
@SpringBootConfigurationpublic class AppConfig {@ConditionalOnClass(name="com.alibaba.druid.FastsqlException")@Beanpublic Cat cat01(){return new Cat();//组件名就是方法名}@ConditionalOnMissingClass(value="com.alibaba.druid.FastsqlException")@Beanpublic Dog dog01(){return new Dog();}@ConditionalOnBean(value= Dog.class)@Beanpublic User user1(){User user = new User();user.setUserName("zhangsan");return user;}@ConditionalOnMissingBean(value= Dog.class)@Beanpublic User user2(){User user = new User();user.setUserName("lisi");return user;}}
属性绑定
@ConfigurationProperties: 声明组件的属性和配置文件哪些前缀开始项进行绑定(名字要一致)(既能表在类上也能标在方法上,用了此注解,组件一定要加入到ioc容器)
@EnableConfigurationProperties:快速注册注解
常用于导入第三方组件进行属性绑定,springboot默认只扫描自己主程序所在的包,所以别人写好的类使用@Component与@ConfigurationProperties(prefix = "…")配置好了组件,我们也无法扫描到,所以只能使用@EnableConfigurationProperties配置属性值并将起放入到ioc容器中
将容器中任意组件(Bean)的属性值和配置文件的配置项的值进行绑定
步骤:
● 1、给容器中注册组件(@Component、@Bean)----------------组件只有在容器中才有这些功能
● 2、使用@ConfigurationProperties 声明组件和配置文件的哪些配置项进行绑定
@ConfigurationProperties+@Component代码举例:
文件:
pig.id=1
pig.name=佩奇
pig.age=5
要放入ioc的组件的类
@Component
@ConfigurationProperties(prefix = "pig")
/*
注意:配置文件的的名字只要与类中的属性名一一对应就可以赋值
*/
@Data
public class Pig {
private Long id;
private String name;
private Integer age;
}
@EnableConfigurationProperties代码举例
配置文件:
sheep.id=2
sheep.name=苏西
sheep.age=4
实体类
@Data
@ConfigurationProperties(prefix = "sheep")//没有搭配@Component了因为在配置类上开启了开启组件的属性绑定
public class Sheep {
private Long id;
private String name;
private Integer age;
}
在配置类上加:
@EnableConfigurationProperties(Sheep.class)
/**
* 1 开启组件的属性绑定
* 2 默认会将组件放入到ioc容器中
* 注意:还是要使用@ConfigurationProperties(prefix = "sheep")指明前缀
*/
深入了解自动配置原理
springboot完整流程
①springboot怎么实现导入一个starter,写一些简单配置,应用就能跑起来,我们无需关心整合
②为什么tomcat的端口号可以配置在appliction.properties中,并且Tomcat能启动成功
③导入场景后那些自动配置能生效
1、导入starter-web:导入了web开发场景
● 1、场景启动器导入了相关场景的所有依赖:starter-json、starter-tomcat、springmvc
● 2、每个场景启动器都引入了一个spring-boot-starter,核心场景启动器。
● 3、核心场景启动器引入了spring-boot-autoconfigure包。
● 4、spring-boot-autoconfigure里面囊括了所有场景的所有配置。(所以导入的所有依赖都不需要写版本)--所有场景要用的组件在配置类里都写好了,这些配置类就在spring-boot-autoconfigure包中。
● 5、只要这个包下的所有类都能生效,那么相当于SpringBoot官方写好的整合功能就生效了。
● 6、SpringBoot默认却扫描不到 spring-boot-autoconfigure下写好的所有配置类。(这些配置类给我们做了整合操作),默认只扫描主程序所在的包。
2、主程序:@SpringBootApplication
● 1、@SpringBootApplication由三个注解组成@SpringBootConfiguration、@EnableAutoConfiguratio、 @ComponentScan
● 2、SpringBoot默认只能扫描自己主程序所在的包及其下面的子包,扫描不到 spring-boot-autoconfigure包中官方写好的配置类
● 3、@EnableAutoConfiguration:SpringBoot 开启自动配置的核心。
○ 1. 是由@Import(AutoConfigurationImportSelector.class)提供功能:批量给容器中导入组件。
○ 2. SpringBoot启动会默认加载 142个配置类。
○ 3. 这142个配置类来自于spring-boot-autoconfigure下 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件指定的
○ 项目启动的时候利用 @Import 批量导入组件机制把 autoconfigure 包下的142 xxxxAutoConfiguration类导入进来(自动配置类)
○ 虽然导入了142个自动配置类
● 4、按需生效:
○ 并不是这142个自动配置类都能生效
○ 每一个自动配置类,都有条件注解@ConditionalOnxxx,只有条件成立,才能生效
3、xxxxAutoConfiguration自动配置类
● 1、给容器中使用@Bean 放一堆组件。
● 2、每个自动配置类都可能有这个注解@EnableConfigurationProperties(ServerProperties.class),用来把配置文件中配的指定前缀的属性值封装到 xxxProperties属性类中
● 3、以Tomcat为例:把服务器的所有配置都是以server开头的。配置都封装到了属性类中。
● 4、给容器中放的所有组件的一些核心参数,都来自于xxxProperties。xxxProperties都是和配置文件绑定。
● 5、只需要改配置文件的值,核心组件的底层参数都能修改
4、写业务,全程无需关心各种整合(底层这些整合写好了,而且也生效了)
1、导入starter,就会导入autoconfigure包。
2、autoconfigure 包里面 有一个文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面指定的所有启动要加载的自动配置类
3、@EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来(通过@Import批量导入)xxxAutoConfiguration(配置类) 是有条件注解进行按需加载
4、xxxAutoConfiguration给容器中导入一堆组件,组件都是从 xxxProperties(属性类,它绑定了配置文件,所以只要修改配置文件就可以修改组件参数)中提取属性值
5、xxxProperties又是和配置文件进行了绑定
效果:导入starter、修改配置文件,就能修改底层行为。
yaml文件语法
痛点:SpringBoot 集中化管理配置,application.properties
问题:配置多以后难阅读和修改,层级结构辨识度不高
YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(是另一种标记语言)。
● 设计目标,就是方便人类读写
● 层次分明,更适合做配置文件
● 使用.yaml或 .yml作为文件后缀
1. 基本语法
● 大小写敏感
● 使用缩进表示层级关系,k: v,使用冒号+空格分割k,v
● 缩进时不允许使用Tab键,只允许使用空格。换行
● 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
● # 表示注释,从这个字符一直到行尾,都会被解析器忽略。
细节
● birthDay 推荐写为 birth-day
● 文本:(\n在单引号内不生效,在双引号内生效)
○ 单引号不会转义【\n 则为普通字符串显示】
○ 双引号会转义【\n会显示为换行符】
例如:name:'zhangsan \n 123'---->打印:name=zhangsan \n 123
name:"张三 \n 457"----》打印:name=张三(换行) 123
● 大文本
○ |开头,大文本写在下层,保留文本格式,换行符正确显示
○ >开头,大文本写在下层,折叠换行符(若没有缩进会压缩换行,即将换行变为空格;若有缩进则保留原文本格式)
例如:
text:
- abc
- gii
- |
dogs:
- dogName: xiaohei
dogAge: 1
- dogName: xiaohuang
dogAge: 1
- >
cghdsku
gsdvkj
ghusduvch
打印:
● 多文档合并
○ 使用---可以把多个yaml文档合并在一个文档中,每个文档区依然认为内容独立
支持的写法:
● 对象:键值对的集合,如:映射(map)/ 哈希(hash) / 字典(dictionary)
● 数组:一组按次序排列的值,如:序列(sequence) / 列表(list)
● 纯量:单个的、不可再分的值,如:字符串、数字、bool、日期
.properties测试代码:
@Component@ConfigurationProperties(prefix = "person")//和配置文件person前缀的所有配置进行绑定@Data@NoArgsConstructor//自动生成一个无参构造器@AllArgsConstructor//自动生成一个全参构造器public class Person {private String name;private Integer age;private Date birthDay;private Boolean like;private Child child;//嵌套对象private List<Dog> dogs;//数组(里面每一个元素又是一个对象)private Map<String,Cat> cats;//表示map}
child类
@Data
public class Child {
private String name;
private Integer age;
private Date birthDay;
private List<String> text;
}
dog类
@Data
public class Dog {
private String dogName;
private int dogAge;
}
cat类
@Data
public class Cat {
private String catName;
private int catAge;
}
Applicationl.properties文件
#properties表示复杂对象
person.name=张三
person.age=30
person.birthDay=1996/10/12 12:12:12
person.like=true
person.child.name=李四
person.child.age=12
person.child.brithDay=2013/12/12
person.child.text[0]=abc
person.child.text[1]=gcs
person.dogs[0].dogName=小黄
person.dogs[0].dogAge=1
person.dogs[1].dogName=小黑
person.dogs[1].dogAge=1
person.cats.c1.catName=小暖
person.cats.c1.catAge=1
person.cats.c2.catName=小白
person.cats.c2.catAge=1
#子对象用嵌套;数组用[];Map用.
.yaml测试代码:
person:
name: zhangsan
age: 30
birthDay: 1996/12/10
like: true
child:
name: lisi
age: 12
birthDay: 2013/2/23
# text: ["abc","gdk"]
text:
- abc
- gii
dogs:
- dogName: xiaohei
dogAge: 1
- dogName: xiaohuang
dogAge: 1
cats:
c1:
catName: xiaonuan
catAge: 1
c2: {catName: xiaobai,catAge: 2}
#对象也可以用{}表示
日志
整合原理
简介:
1. Spring使用commons-logging作为内部日志,但底层日志实现是开放的。可对接其他日志框架。
a. spring5及以后 commons-logging被spring直接自己写了。
2. 支持 jul,log4j2,logback。SpringBoot 提供了默认的控制台输出配置,也可以配置输出为文件。
3. logback是默认使用的。
4. 虽然日志框架很多,但是我们不用担心,使用 SpringBoot 的默认配置就能工作的很好。
SpringBoot怎么把日志默认配置好的
1、每个starter场景,都会导入一个核心场景spring-boot-starter
2、核心场景引入了日志的所用功能spring-boot-starter-logging
3、默认使用了logback + slf4j 组合作为默认底层日志
4、日志是系统一启动就要用,xxxAutoConfiguration是系统启动好了以后放好的组件,后来用的。
5、日志是利用监听器机制配置好的。ApplicationListener。
6、日志所有的配置都可以通过修改配置文件实现。以logging开始的所有配置。
日志格式与记录日志
默认输出格式:
● 时间和日期:毫秒级精度
● 日志级别:ERROR, WARN, INFO, DEBUG, or TRACE.
● 进程 ID
● ---: 消息分割符
● 线程名: 使用[]包含
● Logger 名: 通常是产生日志的类名
● 消息: 日志记录的内容
注意: logback 没有FATAL级别,对应的是ERROR
记录日志:
Logger logger = LoggerFactory.getLogger(getClass());------------》logger.info("要记录的内容")
或者使用Lombok的@Slf4j注解----------------》log.info("要记录的内容")
例如:
@Slf4j
@RestController
public class HelloController {
Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/h")
public String hello(){
/**
* 实现:方法一进来就打印日志
* 方法一:通过LoggerFactory调用getLogger(getClass())传入当前类-----得到一个 Logger对象logger,
* 通过对象logger调用info就可以记录想要的东西了
* 方法二:注解@Slf4j中有一个log
* 通过log调用info也可以传入属性
*/
logger.info("哈哈哈,方法进来了1");
log.info("哈哈哈,方法进来了2");
return "hello";
}
}
日志级别
● 由低到高:ALL,TRACE, DEBUG, INFO, WARN, ERROR,FATAL,OFF;
○ 只会打印指定级别及以上级别的日志
○ ALL:打印所有日志
○ TRACE:追踪框架详细流程日志,一般不使用
○ DEBUG:开发调试细节日志
○ INFO:关键、感兴趣信息日志
○ WARN:警告但不是错误的信息日志,比如:版本过时
○ ERROR:业务错误日志,比如出现各种异常
○ FATAL:致命错误日志,比如jvm系统崩溃(logback 没有FATAL级别,对应的是ERROR)
○ OFF:关闭所有日志记录
● 不指定级别的所有类,都使用root指定的级别作为默认级别
● SpringBoot日志默认级别是 INFO
1. 在application.properties/yaml中配置logging.level.<logger-name>=<level>指定日志级别(我们可以精确的调节某一个类的日志级别后某一个包下的日志级别)
2. level可取值范围:TRACE, DEBUG, INFO, WARN, ERROR, FATAL, or OFF,定义在 LogLevel类中
3. root 的logger-name叫root,可以配置logging.level.root=warn,代表所有未指定日志级别都使用 root 的 warn 级别
代码举例:
@Slf4j
@RestController
public class HelloController {
Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/h")
public String hello(String a,String b){
log.trace("trac 日志....");
log.debug("debug 日志....");
log.info("info 日志....");
log.warn("warn 日志....,参数a:{} b:{}",a,b);
log.error("error 日志....");
/**
* 只打印了info,warn,error日志
* springboot底层默认的日志级别是info(只会打印info及以后级别的日志)
*/
return "hello";
}
}
Applicaton.properties文件
#默认所有日志没有精确指定级别就使用root的默认级别(info)
#将默认级别调整为debug级别
logging.level.root=debug
#将controller包下的日志级别调整为warn级别
logging.level.com.atgiugu.logging1.controller=warn
日志分组
将相关的logger分组在一起,统一配置。SpringBoot 也支持。比如:Tomcat 相关的日志统一设置
例如:
#日志分组
#调整某个包下的日志级别
#logging.level.com.atgiugu.logging1.controller=debug
#logging.level.com.atgiugu.logging1.service=debug
#logging.level.com.aaa=debug
#logging.level.com.bbb=debug
logging.group.abc=com.atgiugu.logging1.controller,com.atgiugu.logging1.service,com.aaa,com.bbb
logging.level.abc=debug
springboot预定义了两个组
Name | Loggers |
Web | org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans |
Sql | org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener |
文件输出(将日志信息保存到文件中)
SpringBoot 默认只把日志写在控制台,如果想额外记录到文件,可以在application.properties中添加logging.file.name or logging.file.path配置项。
例如:
Application.properties文件
#指定日志文件的路径(只给了一个地址的话,会在指定路径下生成一个默认名字的文件)
#logging.file.path=
#指定日志文件的名
#logging.file.name=
#日志文件的名与路径都不配,那么默认配置文件只在控制台输出
#logging.file.name
#1 只写名字,就生成到当前项目同位置的demo.log
#logging.file.name=demo.log
#2 名字+路径,就生成到指定位置的指定文件
logging.file.name=C://demo.log
#注意:如果logging.file.path=与logging.file.name=同时存在,那么以logging.file.name优先
logging.file.name | logging.file.path | 示例 | 效果 |
未指定 | 未指定 | 仅控制台输出 | |
指定 | 未指定 | my.log | 写入指定文件。可以加路径 |
未指定 | 指定 | /var/log | 写入指定目录,文件名为spring.log |
指定 | 指定 | 以logging.file.name为准 |
文件归档与滚动切割
归档:每天的日志单独存到一个文档中。
切割:每个文件10MB,超过大小切割成另外一个文件。
1. 每天的日志应该独立分割出来存档。如果使用logback(SpringBoot 默认整合),可以通过application.properties/yaml文件指定日志滚动规则。
2. 如果是其他日志系统,需要自行配置(文件名一定为log4j2.xml或log4j2-spring.xml)
3. 支持的滚动规则设置如下
配置项 | 描述 |
logging.logback.rollingpolicy.file-name-pattern | 日志存档的文件名格式(默认值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz) |
logging.logback.rollingpolicy.clean-history-on-start | 应用启动时是否清除以前存档(默认值:false) |
logging.logback.rollingpolicy.max-file-size | 存档前,每个日志文件的最大大小(默认值:10MB) |
logging.logback.rollingpolicy.total-size-cap | 日志文件被删除之前,可以容纳的最大大小(默认值:0B)。设置1GB则磁盘存储超过 1GB 日志后就会删除旧日志文件 |
logging.logback.rollingpolicy.max-history | 日志文件保存的最大天数(默认值:7). |
例如:
Application.properties文件:
#归档与切割
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
#${LOG_FILE}就是前面配置的文件名;%d{yyyy-MM-dd}格式化一个日期,是年月日;%i是当天的第几个文件;gz是压缩包格式
#只要文件攒够1MB就切割为一个单独文件
logging.logback.rollingpolicy.max-file-size=1MB
自定义日志系统
通常我们配置 application.properties 就够了。当然也可以自定义。比如:
日志系统 | 自定义 |
Logback | logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
自定以文件后,就按照自定义文件的规则来输出日志
如果可能,我们建议您在日志配置中使用-spring 变量(例如,logback-spring.xml 而不是logback.xml)。如果您使用标准配置文件,spring 无法完全控制日志初始化。
切换日志组合
利用maven的就近原则
步骤:①在spring-boot-starter中排除logback依赖(spring-boot-starter-logging)
②导入log4j2的依赖(spring-boot-starter-log4j2)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
导第三方日志如果它依赖了一个日志(jul),排除掉这个框架的默认日志
总结:
1. 导入任何第三方框架,先排除它的日志包,因为Boot底层控制好了日志
2. 修改 application.properties 配置文件,就可以调整日志的所有行为。如果不够,可以编写日志框架自己的配置文件放在类路径下就行,比如logback-spring.xml,log4j2-spring.xml
3. 业务中使用slf4j-api记录日志。不要再 sout 了
相关文章:
SpringBoot3快速入门笔记
springboot3简介 SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用(说明:SpringBoot底层是Spring) 大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术 特性: ● 快速创建…...
vue3中,element-plus中el-input的v-model和value的用法示例
el-input的v-model,邦定响应式变量 <el-col :span"6"><el-form-item label"检验类别" prop"verifyType"><el-input v-model"applyAllInfo.applyBasicInfo.verifyTypeName" readonly /></el-form-item…...
python求π近似值
【问题描述】用公式π/4≈1-1/31/5-1/7..1/(2*N-1).求圆周率PI的近似值。 从键盘输入一个整数N值,利用上述公式计算出π的近似值,然后输出π值,保留小数后8位。 【样例输入】1000 【样例输出】3.14059265 def countpi(N):p0040nowid0for i i…...
Gerapy二次开发:搜索器组件设计开发与应用(Vue父子组件通信)
搜索器组件设计开发与应用 写在前面搜索器字段定义与样式设计具体实现components/Search.vuedeploy/Index.vue后端views.py运行效果总结欢迎加入Gerapy二次开发教程专栏! 本专栏专为新手开发者精心策划了一系列内容,旨在引领你深入探索Gerapy框架的二次迭代之旅。 本专栏将全…...
深入解析Python爬虫技术:从基础到实战的功能工具开发指南
一、引言:Python 爬虫技术的核心价值 在数据驱动的时代,网络爬虫作为获取公开数据的重要工具,正发挥着越来越关键的作用。Python 凭借其简洁的语法、丰富的生态工具以及强大的扩展性,成为爬虫开发的首选语言。根据 Stack Overflow 2024 年开发者调查,68% 的专业爬虫开发者…...
Python爬虫-爬取全球股市涨跌幅和涨跌额数据
前言 本文是该专栏的第52篇,后面会持续分享python爬虫干货知识,记得关注。 本文中,笔者将基于Python爬虫,实现批量采集全球股市行情(亚洲,美洲,欧非,其他等)的各股市“涨跌幅”以及“涨跌额”数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。…...
【NLP 59、大模型应用 —— BPE 算法】
你和生生不息的河流,生动了我人生中的美好瞬间 —— 25.4.11 一、词表的构造问题 为了nlp模型训练,词表(字表)是必要的 统计训练语料中的所有字符(或词)是一种做法,但是容易出现一些问题&…...
SQL基础入门:从CRUD到JOIN再到索引(通俗易懂版)
一、为什么需要SQL? 想象你在管理一个图书馆: 传统方法:手动记录每本书的位置、借阅者、归还日期SQL方法:用数据库系统自动管理,快速查询《Java编程思想》在哪个书架 SQL(Structured Query Language&…...
系统编程1(进程的概念与原理)
进程的概念与原理 计算机组成部分一般遵循冯诺依曼结构,也就是由控制器、运算器、存储器、输入设备、输出设备五个部分组成。 ⦁ 程序的编译 一般在编写出程序之后,并不能直接运行,而是需要把程序通过编译器进行编译,生成可执行…...
Git基础知识
Git基础知识 目录 一、Git简介 1.1 什么是Git?1.2 基本概念1.3 Git与其他版本控制系统的区别 二、Git安装与配置 2.1 安装Git2.2 基础配置2.3 高级配置2.4 多账户配置 三、基本操作 3.1 创建仓库3.2 基本工作流3.3 分支操作3.4 查看历史 四、高级操作 4.1 撤销修改…...
【Flink运行时架构】核心组件
在Flink的运行架构中,有两大比较重要的组件:作业管理器(JobManager)和任务管理器(TaskManager)。 Flink的作业提交与任务处理时的系统如下图所示。 其中,客户端并不是处理系统的一部分ÿ…...
【区块链安全 | 第四十篇】合约审计之delegatecall(二)
文章目录 漏洞代码代码分析攻击流程攻击代码前文重现修复建议审计思路 在阅读本文之前,请确保已先行阅读:【区块链安全 | 第三十九篇】合约审计之delegatecall(一) 漏洞代码 存在一漏洞代码如下: // 库合约…...
Redis实现分布式定时任务
设计思路 任务表示:每个任务通过一个特定格式的键来表示。键名可以包含任务ID等信息,值可以是任务的具体内容或指向任务详情的引用。过期机制:利用Redis的EXPIRE命令为任务设置过期时间,当到达设定的时间点时,Redis会…...
ERC20合约的基本调用
文章目录 ERC20合约的基本调用合约功能compile.js 代码读取文件 进行合约编译获取二进制对象导出对象 index.js 代码编译合约读取私钥设置收款账户构造 web3 对象获取账户地址获取 abi 和 bin创建合约交易部署合约构造转账交易验证转账后余额 测试项目目录执行查询 ERC20合约的…...
『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解
『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解 Pod 结构 每个 Pod 中都可以包含一个或者多个容器,这些容器可以分为两类 用户程序所在的容器,数量可多可少Pause 容器,这是每个 Pod 都会有的一个根容器,它的作用有两个 可…...
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
什么是 Vite? Vite 是一个基于原生 ES Modules 开发的前端构建工具,由 Evan You(Vue 的作者)开发。它最大的特点包括: 极速冷启动:因为利用了浏览器原生的 ES Modules,所以在开发时无需等待整…...
JS实现文件点击或者拖拽上传
B站看到了渡一大师课的切片,自己实现了一下,做下记录 效果展示 分为上传前、上传中和上传后 实现 分为两步 界面交互网络请求 源码如下 upload.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset&q…...
【Vue #3】指令补充样式绑定
一、指令修饰符 Vue 的指令修饰符(Directive Modifiers)是 Vue 模板语法中的重要特性,它们以半角句号 . 开头,用于对指令的绑定行为进行特殊处理 修饰符作用如下: 简化事件处理(如阻止默认行为、停止冒泡…...
Vue.js组件安全工程化演进:从防御体系构建到安全性能融合
——百万级流量场景下的安全组件架构与源码级解决方案 文章目录 总起:安全工程化的组件革命 分论: 一、现存组件架构的七宗罪与安全改造路径 1.1 组件生态安全赤字现状 1.2 架构级安全缺陷深度剖析 1.3 性能与安全的死亡螺旋 二、百万级…...
LINUX基础 [二] - Linux常见指令
目录 💻前言 💻指令 🎮ls指令 🎮pwd指令 🎮whoami指令 🎮cd指令 🎮clear指令 🎮touch指令 🎮mkdir指令 🎮rmdir指令 🎮rm指令 &#…...
Linux进阶命令
目录 一、touch 1. 基本语法 2. 常用选项 二、which 1. 基本语法 2. 主要功能 3. 常用选项 三、find 1. 基本语法 2. 常用选项和表达式 四、more 1. 基本语法 2. 常用操作 3. 对比 more 和 less 五、grep 1. 基本语法 2. 常用选项 六、wc 1. 基本语法 2. 常…...
【Spring Boot 过滤器】
文章目录 前言一、什么是过滤器 Filter?二、Spring Boot 中使用 Filter 的方式1. 使用 Component 注解2. 使用 FilterRegistrationBean 显式注册 三、自定义过滤器示例1. 引入必要依赖2. 创建一个自定义 Filter3. 使用 FilterRegistrationBean 显式注册 四、多个 Fi…...
SPI通讯的软硬件NSS SSM SSI
学习自记: 1. NSS(Slave Select,从设备选择) 功能: NSS是SPI通信中用于选择从设备的信号线。主设备通过拉低NSS信号选中某个从设备,使其参与通信。通信结束后,主设备释放NSS&#…...
Java基础:集合List、Map、Set(超详细版)
集合体系概述 Collection常用方法 补充:addAll() Collection的遍历方式 迭代器 增强for(空集合可以,null不可以) lambda 集合对象存储对象原理 遍历方式的区别 List集合 特点、特有方法 遍历方式 (同上)…...
vue+leaflet 区域划分_反向遮罩层
leaflet 区域划分_遮罩层 geojson在线生成器网址:(https://datav.aliyun.com/portal/school/atlas/area_selector) 点击前往阿里云geojson生成器 效果图: 实现下面效果,只需要把addSateLayer函数的调用取消掉就好了. //添加遮罩层代码function addMask() {var latlngs;var fe…...
聊一聊原子操作和弱内存序
1、原子操作概念 在并发编程中,原子操作(Atomic Operation)是实现线程安全的基础机制之一。从宏观上看,原子操作是“不可中断”的单元,但若深入微观层面,其本质是由底层处理器提供的一组特殊指令来保证其原…...
免费送源码:Java+ssm+MySQL 校园二手书销售平台设计与实现 计算机毕业设计原创定制
摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对校园二手书销售平台等问题,对校…...
DAPP实战篇:使用ethersjs连接智能合约并输入地址查询该地址余额
本系列目录 专栏:区块链入门到放弃查看目录-CSDN博客文章浏览阅读400次。为了方便查看将本专栏的所有内容列出目录,按照顺序查看即可。后续也会在此规划一下后续内容,因此如果遇到不能点击的,代表还没有更新。声明:文中所出观点大多数源于笔者多年开发经验所总结,如果你…...
14.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--CAP
CAP 是一款专为 .NET 生态设计的开源框架,其核心目标是解决微服务中跨服务数据一致性问题。在分布式系统中,传统事务无法跨服务保证数据一致性,CAP 通过本地事务与消息记录绑定,再利用消息中间件(如 RabbitMQ、Kafka 等…...
智能资源管理机制-重传机制
一、发送端资源管理的核心机制 1. 滑动窗口(Sliding Window) 这是TCP协议的核心优化设计: 窗口动态滑动:发送端不需要保留所有已发送的分组,只需维护一个"发送窗口"窗口大小:由接收方通告的接…...
【Linux网络与网络编程】08.传输层协议 UDP
传输层协议负责将数据从发送端传输到接收端。 一、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中,用 "源IP","源端口号","目的 IP","目的端口号"&…...
局域网下ESP32-S3 LED灯的UDP控制
在局域网下通过IP地址控制ESP32-S3上的LED,可以使用UDP或TCP协议。以下是一个基于UDP协议的完整示例,包括ESP32-S3的服务器代码和一个简单的Python客户端代码。 ESP32-S3 服务器代码 import socket import time import network import machineled Non…...
call、bind、apply
call、bind、apply它们三个都是函数的方法,都可以用于改变this的指向问题。 var person "liangxiao" let obj {name:"张三",say:function() {console.log(this.name);} }obj.say(); setTimeout(function() {obj.say(); },1000) obj.say()打…...
Redis 哨兵模式 搭建
1 . 哨兵模式拓扑 与 简介 本文介绍如何搭建 单主双从 多哨兵模式的搭建 哨兵有12个作用 。通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。 当哨兵监测到master宕机,会自动将slave切换成master,然后通过…...
客户端负载均衡与服务器端负载均衡详解
客户端负载均衡与服务器端负载均衡详解 1. 客户端负载均衡(Client-Side Load Balancing) 核心概念 定义:负载均衡逻辑在客户端实现,客户端主动选择目标服务实例。典型场景:微服务内部调用(如Spring Cloud…...
Ningx负载均衡
Ningx负载均衡 upstream(上游)配置负载均衡1、weight(加权轮询)2、ip_hash(负载均衡)3、url hash负载均衡4、least_conn(最小连接负载均衡) upstream(上游)配置负载均衡 Nginx负载均衡 参考: nginx从安装…...
头歌软件工程导论UML画图题(基于starUML)
一.结构化分析方法-数据流图 本关卡需要画图的一共有5关,直接将此图画好每关提交一次即可,以下的所有图均以此方法提交 二.面向对象分析之用例图 三.面向对象分析之类图 注意此处创建Class之后,双击Class出现以下选项 点击相应的选项创建属性…...
智能车摄像头开源—9 动态权、模糊PID、速度决策、路径优化
目录 一、前言 二、动态权 1.概述 2.偏差值加动态权 三、模糊PID 四、速度决策 1.曲率计算 2.速度拟合 3.速度控制 五、路径 六、国赛视频 一、前言 在前中期通过识别直道、弯道等元素可进行加减速操作实现速度的控制,可进一步缩减一圈的运行速度ÿ…...
java基础 this和super的介绍
this和super this关键字的用法super关键字的用法this与super的区别和注意事项 this关键字的用法 this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针 class Person{private String name;private int age;public String …...
《Python星球日记》第25天:Pandas 数据分析
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 订阅专栏:《Python星球日记》 目录 一、引言二、数据分组与聚合1. 分组操…...
C++在Linux上生成动态库并调用接口测试
加减乘除demo代码 项目结构 CPP/ ├── calculator.cpp ├── calculator.h ├── main.cpp 头文件 #ifndef CALCULATOR_H #define CALCULATOR_H#ifdef __cplusplus extern "C" {#endifdouble add(double a, double b);double subtract(double a, double b…...
Cesium.js(6):Cesium相机系统
Camera表示观察场景的视角。通过操作摄像机,可以控制视图的位置、方向和角度。 帮助文档:Camera - Cesium Documentation 1 setView setView 方法允许你指定相机的目标位置和姿态。你可以通过 Cartesian3 对象来指定目标位置,并通过 orien…...
机器学习中的数学(PartⅡ)——线性代数:概述
首先引入代数和线性代数的概念: 在将一些直观的、基于经验或直觉的概念转化为严格的数学或逻辑定义时,一种常用方法是构建一组对象和一组操作这些对象的规则,这就是代数。线性代数是研究向量和某些操作向量的规则。 其次从更广泛的意义上定…...
基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真
欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2013Rb)软件。建议采用matlab2013 Rb及以上版本打开。(若需要其他版本可联系代为转换,高于该版本的matlab均可正…...
在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南
在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南 引言 本文将详细介绍如何在51单片机平台上,通过精确的50us定时器中断实现无闪烁的呼吸灯效果。相比常见的125us实现方案,50us定时器能提供更高的PWM频率和更细腻的亮度控制。 硬件设计 基本电路配置 主控芯片:SC92F8…...
asm汇编源代码之CPU型号检测
提供1个子程序: 1. CPU型号检测 CPUTYPE 无输入参数,返回值AX指示CPU类型(报歉,当时最新CPU型号只有80486) 函数的返回值详细描述如下 CPUTYPE PROC FAR ;OUT: AX01, 8086; AX02, 80286; AX03, 80386; AX04, 80486 UP; ; more source code at http://www.ahj…...
提高课:数据结构之树状数组
1,楼兰图腾 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm>using namespace std;typedef long long LL;const int N 200010;int n; int a[N]; int tr[N]; int Greater[N], lower[N];int lowbit(int x) {ret…...
python可变对象与不可变对象
文章目录 Python 中的可变对象与不可变对象不可变对象(Immutable Objects)可变对象(Mutable Objects)重要区别 Python 中的可变对象与不可变对象 在 Python 中,对象可以分为可变对象(mutable)和不可变对象(immutable),这是 Python 中非常重要的概念&…...
C++学习之金融类安全传输平台项目git
目录 1.知识点概述 2.版本控制工具作用 3.git和SVN 4.git介绍 5.git安装 6.工作区 暂存区 版本库概念 7.本地文件添加到暂存区和提交到版本库 8.文件的修改和还原 9.查看提交的历史版本信息 10.版本差异比较 11.删除文件 12.本地版本管理设置忽略目录 13.远程git仓…...
果篮问题 Python
# 给你两个长度为 n 的整数数组,fruits 和 baskets,其中 fruits[i] 表示第 i 种水果的 数量,baskets[j] 表示第 j 个篮子的 容量。 # 你需要对 fruits 数组从左到右按照以下规则放置水果: # 每种水果必须放入第一个 容量大于等于 …...