Spring Boot-启动(相关配置,及原理)

简介:

Spring Boot应用开发的框架。Spring Boot来简化Spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的、产品级别的应用。
背景:J2EE笨重的开发,繁多的配置、底下的开发效率、复杂的部署流程、第三方技术集成难度大。
解决:
"Spring全家桶"的时代。
Spring Boot-->J2EE一站式解决方案。
Spring Cloud-->分布式整体解决方案。
优点:
快速创建独立运行的Spring项目以及与主流框架集成。
使用嵌入式的Servlet容器,应用无需打成war包。
starters自动依赖与版本控制。
大量的自动配置,简化开发,也可以需改默认值。
无需配置XML,无代码生成,开箱即用。
准生产环境的运行时应用监控。
与云计算的天然集成。

微服务

2014,martin fowler
微服务:架构风格
一个应用应该是一组小型服务,可以通过HTTP的方式进行沟通;

每一个功能元素最终都是一个可独立替换和独立升级的软件单元。
详细参考微服务文档……
单体应用:ALL IN ONE

学习Spring Boot你必须掌握以下内容:

Spring框架的使用经验。
熟练使用Maven进行项目的构建和依赖管理。
熟练使用Eclipse或IDEA

环境约束

JDK1.8:Spring Boot 1.7及以上版本
Maven3.x:maven 3.3及以上版本
IntelliJ IDEA 2017:IntelliJ IDEA 2018.2.5,还可以用Spring官方的STS工具。
Spring Boot 版本号:

统一环境:

MAVEN设置:
给maven的setting.xml文件添加profiles标签添加如下:(告诉它用JDK1.8来编译执行)

 <profiles>     
      <profile>       
           <id>jdk-1.8</id>       
           <activation>       
               <activeByDefault>true</activeByDefault>       
               <jdk>1.8</jdk>       
           </activation>       
           <properties>       
               <maven.compiler.source>1.8</maven.compiler.source>       
               <maven.compiler.target>1.8</maven.compiler.target>       
               <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>       
           </properties>       
    </profile>      
 </profiles> 

IDEA设置:
将IDEA中的MAVEN该为自己安装的MAVEN并设置自己的配置文件和仓库。

Spring Boot HelloWord

一个功能为例:浏览器发送一个Hello请求,服务器接受请求并处理,响应Hello Word字符串;

  1. 创建一个maven工程(jar);
  2. 导入依赖spring boot相关的依赖;
<!--导入Spring Boot的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
    <!--导入Spring Boot中的starter-web模块的依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  1. 编写一个主程序
package cn.tx.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 告诉Spring Boot这是一个Spring Boot的主程序应用
 * @SpringBootApplication:来标注这是一个主程序类,说明这是一个Spring Boot应用
 */
@SpringBootApplication
public class HelloWordMainApplication {
    public static void main(String[] args) {
        //Spring应用启动 使用本类的class和主程序中的参数args
        SpringApplication.run(HelloWordMainApplication.class, args);
    }
}
  1. 编写相关的Controller、Service
package cn.tx.main.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

//@Controller 表示这是一个处理器
@Controller
public class HelloController {

    //@RequestMapping("/hello") 表示用来处理浏览器发的hello请求的处理
    //@ResponseBody 把数据写出到浏览器注解

    @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        return "Hello World!";
    }
}
  1. 启动创建的主程序类即可。
    可能会出现问题:异常:This application has no explicit mapping for /error, so you are seeing this as a fallback解决方法。
    解决方案一:IDEA目录结构的问题,Application启动类的位置不对.要将Application类放在最外侧,即包含所有子包 。而我的controller则放在了最外层的包里面。导致找不到页面。
    解决方法二:添加@SpringBootApplication(scanBasePackages="controller")
    在你的启动的HelloWordMainApplication类中,添加注释,指定你的HelloController的位置,就可以指定加载,成功解决问题。
  2. 简单部署:
    把Spring Boot的Maven插件导入到项目中:
<!--这个插件,可以将应用打包成一个可执行的jar包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

打包方法:在Maven Projects中选择项目里面的Lifecycle(生命周期)中的package方法。

  1. 运行(cmd窗口):
    cd 到你打好jar包的目录回车;
    java -jar 项目名称回车;

Hello World探究

  1. pom文件

父项目:

<!--导入Spring Boot的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>
<!--所以我们以后导入的依赖默认是不需要写版本(但没有在dependencies里面管理的依赖自然需要声明版本号)-->

Spring Boot的版本仲裁中心:
所以我们以后导入依赖默认是不需要写版本的。

  1. 启动器
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

spring-boot-starter-web:
spring-boot-starter:Spring Boot场景启动器。帮我们导入了web模块正常运行所依赖的组件。依赖版本还是由Spring Boot的版本仲裁中心控制。

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
    </dependencies>

Spring Boot将所有的功能场景都抽取出来了,做成一个个的starters(启动器),只需要在项目中引入这些starters相关场景的所有依赖都会导入进来。要用什么功能,就导入什么场景的启动器。

主程序类,主入口类

package cn.tx.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 告诉Spring Boot这是一个Spring Boot的主程序应用
 * @SpringBootApplication:来标注这是一个主程序类,说明这是一个Spring Boot应用
 */
@SpringBootApplication
public class HelloWordMainApplication {
    public static void main(String[] args) {
        //Spring应用启动 使用本类的class和主程序中的参数args
        SpringApplication.run(HelloWordMainApplication.class, args);
    }
}

@SpringBootApplication:Spring Boot应用标准在某个类上说明这个类是Spring Boot的主配置类,Spring Boot就应该运行这个类的main方法来启动Spring Boot应用。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}), 
    @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}) 
})
public @interface SpringBootApplication {

@SpringBootConfiguration:Spring Boot的配置类;标注在某个类上,表示这是一个Spring Boot的配置类。
@Configuration:配置类上标注这个注解;
即:配置类--->配置文件;配置类也是容器中的一个组件。@Component
@EnableAutoConfiguration:开启自动配置功能;
以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉Spring Boot开启自动配置功能;这样配置功能才能生效。

@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})

@AutoConfigurationPackage:自动配置包;

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
//等价于
@Import(AutoConfigurationPackage.Registrar.class)
//Spring的底层注解@Import,给容器中导入组件;导入的组件由AutoConfigurationPackage.Registrar.class

作用是将:主配置类所在包及下面所有子包里面的所有组件扫描到Spring容器中
EnableAutoConfigurationImportSelector:导入哪些组件的选择器?
将所有需要导入的组件以全类名的方式返回;这些就会被添加到容器中。
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,并配置好这些组件。
有了自动配置类。免去了我们手动编写配置注入功能等组件。
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfinguration.class,classLoader);
Spring Boot在启动的时候从类路径下的META-INF/spring.faactories中获取EnableAutoConfiguration指定的值。将这些值作为自动配置类导入到容器中,自动配置类就生效了,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置都给我们配置了。

使用Spring Initializer快速创建Spring Boot项目

IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目;
选择我们需要的模块,向导会联网创建一个Spring Boot项目。具体 步骤如下:


步骤1.png

步骤2.png

步骤3.png

步骤4.png

项目结构图.png

这些没用的文件可以选择删除(.mvn、.gitignore、HELP.md、mvnw、mvnw.cmd)


自动生成的启动类.png

接下来我们看看maven帮我们生成的pom文件都包含什么:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--导入了一个父级依赖,管理了一些版本号-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.fantuan</groupId>
    <artifactId>spring-boot-01-helloword-quick</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-01-helloword-quick</name>
    <description>Demo project for Spring Boot</description>
    <!--定义了java版本号-->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--Spring Boot中的starter-web模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Spring Boot中的starter-test是用来单元测试的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <!--maven插件-->
    <!--这个插件,可以将应用打包成一个可执行的jar包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

前面选择的功能模块都以及替我们添加了,我们只用做自己的事就可以了,接下来我们创建一个控制层,代码如下:


控制层.png
package cn.fantuan.springboot01.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//@Controller
//@ResponseBody
//@Controller与@ResponseBody两个注解等同于@RestController
//@ResponseBody放在类上面表示该类的所有的方法返回的数据都是写给浏览器的,(如果对象转为JSON数据也可以返回出去)
@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "Hello World quick!";
    }
}

resources文件夹中目录结构解析:


resources.png

static:保存所有的静态资源(js、css、images)。
templates:保存所有的模板页面(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面)可以使用模板引擎(freemarker、thymeleaf)。
application.properties:Spring Boot应用到的配置文件,可以修改一些默认的设置。

########定义端口号
server.port=8081

Spring Boot的配置

配置文件

Spring Boot使用一个全局的配置文件,配置文件名是固定的。

  • application.properties
  • application.yml
    配置文件的作用:就是用来修改Spring Boot自动配置的默认值。Spring Boot在底层将所有的东西都给我们配置好了;
    yml是YAML(YAML Ain't Markup Languange)语言的文件,以数据为中心,比json、xml等更适合做配置文件。
    YAML A Markup Languange:是一个标记语言。
    YAML isn't Markup Languange:不是一个标记语言。
标记语言:

以前的配置文件,大多数都是使用json、xml等。
YAML:以数据为中心,比json、xml等更适合做配置文件。
YAML:配置例子(中间一定要有空格)

####配置服务器端口
server:
  port: 8081

YAML语法:

1.基本语法

K:(空格)V:表示一对键值对(空格是必须有的、key和value之间必须有空格)
空格的缩进来控制层级关系;只要是用空格使它左对齐的的都是同一层级关系。属性和值都是大小写敏感的。

2.值的写法

  • 字面量:普通的值(数字、字符串、布尔值):
    K:V:字面量直接来写就可以了:字符串默认不用加上单引号或双引号,单引号和双引号的用意不同。
    " ":双引号不会转义字符串里面的特殊字符。特殊字符会作为本身想表达的意思。如:name:"zhangsan\nlisi" 输出的就是 zhangsan换行lisi
    ' ':单引号会转义特殊字符串,最终会转义为一个普通的字符串。如:name:"zhangsan\nlisi" 输出的就是 zhangsan\nlisi
  • 对象、map(属性和值)也就是键值对:
    K:V:在下一行来写对象的属性和值的关系;注意用空格来控制缩进如:
####多行的写法
friends:
        name: zahngsan
        age: 23
####行内的写法
friends: {name: zhangsna,age:18}
  • 数组(List、Set):
    用- 值表示数组中的一个元素
####多行的写法
pets: 
- cat
- dog
- pig
####行内写法
pets: [cat,dog,pig]

获取配置文件的值、注入

配置文件

####配置服务器端口
server:
  port: 8081

Person:
  name: zhangsan
  age: 20
  boos: false
  brith: 2020/11/11 22:40:14
  maps: {key1: value1,key2: value2}
  lists:
  - lisi
  - wangwu
  - zhaoliu
  dog:
    dogName: 小狗
    dogAge: 2

javaBean

package cn.fantuan.springboot01.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 将配置文件中配置的每个属性的值,映射到这个组件中
 * @ConfigurationProperties:告诉Spring Boot将本类中的所有属性和配置文件中相关的属性、相关的配置进行绑定
 * prefix = "Person":配置文件中那个下面的所有属性进行一一映射
 * 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
 * 批量一次注入
 * @Component把对象加载到容器中
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private int age;
    private Boolean boos;
    private Date brith;

    private Map<String, Object> maps;
    private List<Object> lists;
    private Dog dog;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Boolean getBoos() {
        return boos;
    }

    public void setBoos(Boolean boos) {
        this.boos = boos;
    }

    public Date getBrith() {
        return brith;
    }

    public void setBrith(Date brith) {
        this.brith = brith;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + ", boos=" + boos + ", brith=" + brith + ", maps=" + maps + ", lists=" + lists + ", dog=" + dog + '}';
    }
}

我们可以导入一个配置文件的处理器,以后编写配置文件就有提示了

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

@Value获取值与@ConfigurationProperties(prefix = "?")获取值比较

@Value(" ")相当于:

<bean class="Person">
    <property name="name" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
 </bean>

@ConfigurationProperties(prefix = "?"):批量注入,一次性
@Value:一个一个的指定。
松散绑定(松散语法):@ConfigurationProperties支持、@Value不支持。即lastName可以写着last-name进行绑定,也可以用lastName进行绑定。
JSP303数据校验:@ConfigurationProperties支持、@Value不支持
SpEl语法:@ConfigurationProperties不支持、@Value支持。即@Value("#{11*2}")它会自动给我们计算最后的值。
复杂类型: @ConfigurationProperties支持、@Value 不支持它不能把值取出来。
不管是yml还是properties配置文件都能获取到值。
如果我们在某一个业务逻辑中需要获取一下配置文件中的某项值,使用@Value。
如果说,我们专门编写了一个javaBean来和配置文件进行映射;那么我们就直接使用@ConfigurationProperties它一次性全部注入进来。

配置文件注入值数据校验

必须使用:@ConfigurationProperties(prefix = "?"):才可以使用校验
放在类上的@Validated说明类需要需要校验。
放在变量上的@Email说明校验的格式为Email不然就报错。

package cn.fantuan.springboot01.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 将配置文件中配置的每个属性的值,映射到这个组件中
 * @ConfigurationProperties:告诉Spring Boot将本类中的所有属性和配置文件中相关的属性、相关的配置进行绑定
 * prefix = "Person":配置文件中那个下面的所有属性进行一一映射
 * 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
 * 批量一次注入
 *
 * @Component把对象加载到容器中
 * @Validated说明这个javaBean需要校验
 */
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
    /**
     * <bean class="Person">
     *     <property name="name" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * </bean>
     */
    //@Value("${person.name}")
    //使用@Validated校验数据,说明这个name的值必须是邮箱格式的
    @Email
    private String name;
    //@Value("#{11*2}")
    private int age;
   //@Value("true")
    private Boolean boos;
    private Date brith;

    private Map<String, Object> maps;
    private List<Object> lists;
    private Dog dog;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Boolean getBoos() {
        return boos;
    }

    public void setBoos(Boolean boos) {
        this.boos = boos;
    }

    public Date getBrith() {
        return brith;
    }

    public void setBrith(Date brith) {
        this.brith = brith;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + ", boos=" + boos + ", brith=" + brith + ", maps=" + maps + ", lists=" + lists + ", dog=" + dog + '}';
    }
}

@PropertySource & @ImportResource

@ConfigurationProperties(prefix = "person")默认是从全局配置文件中获取值。必须每个值都要有即使为空都可以,但必须配置。且类型必须相同。
@PropertySource作用:加载指定的配置文件。
@PropertySource(value = {"classpath:person.properties"}):值是一个数组,可以填写多个。告诉Spring Boot来加载我们指定的类路径下的配置文件的内容并绑定到现在这个类中。

/**
 * 将配置文件中配置的每个属性的值,映射到这个组件中
 * @ConfigurationProperties:告诉Spring Boot将本类中的所有属性和配置文件中相关的属性、相关的配置进行绑定。必须每个值都要有即使为空都可以,但必须配置。且类型必须相同。
 * prefix = "Person":配置文件中那个下面的所有属性进行一一映射
 * 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
 * 批量一次注入.
 * @ConfigurationProperties(prefix = "person")默认是从全局配置文件中获取值
 *
 * @Component把对象加载到容器中
 * @Validated说明这个javaBean需要校验
 * @PropertySource(value = {"classpath:person.properties"}):值是一个数组,可以填写多个。告诉Spring Boot来加载我们指定的类路径下的配置文件的内容并绑定到现在这个类中
 */
@Component
@ConfigurationProperties(prefix = "person")
//@Validated
@PropertySource(value = {"classpath:person.properties"})
public class Person {

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效。
Spring Boot里面没有Spring配置文件,我们自己编写的配置文件也不能自动识别,如果想要Spring配置文件生效,加载进来:@ImportResource标注在一个配置类上。
功能就是导入spring的配置文件。

/**
 * 告诉Spring Boot这是一个Spring Boot的主程序应用
 * @SpringBootApplication:来标注这是一个主程序类,说明这是一个Spring Boot应用
 * @ImportResource(locations = {"classpath:beans.xml"}):locations值是一个数组,可以写入多个配置文件。使配置文件生效
 */
@SpringBootApplication
@ImportResource(locations = {"classpath:beans.xml"})
public class SpringBoot01HellowordQuickApplication {

现在编写Spring的配置文件了

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="helloService" class="cn.fantuan.springboot01.service.HelloService"></bean>
</beans>

Spring Boot推荐给容器添加组件的方式:(推荐使用全注解的方式)

  1. 配置类===Spring的配置文件
  2. 使用@Bean注解来给容器中添加组件。
/**
 * @Configuration这个注解告诉Spring Boot这个类是一个配置类。就是来替代Spring的配置文件。
 * 在配置文件中用的是<bean></bean>添加组件的。
 */
@Configuration
public class MyConfig {

    //@Bean将方法的返回值添加到容器中。容器中这个组件的默认id就是方法名
    @Bean
    public HelloService helloService(){
        System.out.println("配置类通过@Bean注解添加组件了……");
        return new HelloService();
    }
}

配置文件占位符

  1. 随机数

{random.uuid}:表示一个随机的uuid。{random.int}:表示一个随机的整数。
{random.value}:表示一个随机的字符串类是uuid。{random.int(10)}、{random.long}、{random.int[1024,65536]}

  1. 占位符获取之前配置值
    {person.name}dog、{person.name:name}dog
########配置服务器端口
server.port=8081

########idea,properties默认使用ASCII编码
########配置person

########${random.uuid}:表示一个随机的uuid
person.name=漳卅三${random.uuid}
########${random.int}:表示一个随机的整数
peron.age=${random.int}
person.sbrith=2020/10/11
person.boos=true
person.lists=a,b,c
person.maps.key1=value1
person.maps.key2=value2
########${person.name}dog:表示获取上面设置的person.name的值后面再拼接一个_dog为这个person.dog.dogName的值
person.dog.dogName=${person.name}_dog
########${person.hello:10}20:表示获取上面设置的person.hello的值,如果没有:则用person.hello来代替它,如果有使用:则用:后面的值代替上面没有出现的值。即用:指定默认值,没有:则转为本身的字符串代替。
person.dog.dogAge=${person.hello:10}20

Profile

多Profile文件

我们在主配置文件编写的时候,文件名可以是 appliction-{profile}.properties/yml
可以创建多个配置文件,但默认使用的是application.properties/yml配置文件。

########配置服务器端口
server.port=8080
########配置项目的访问路径
server.servlet.context-path=/aaaa
########激活指定的环境
spring.profiles.active=prod
yml支持多文档块方式
########文档块使用三个-来定义:即---
########模块一、为默认环境,不指定激活环境则默认是模块一的环境
########配置服务器端口
server:
  port: 8081
#######激活指定环境
spring:
  profiles:
    active: dev
---
########模块二
########配置服务器端口
server:
  port: 8082
########开发环境
spring:
  profiles: dev
---
########模块三
########配置服务器端口
server:
  port: 8083
########生产环境
spring:
  profiles: prod

激活指定profile
  1. 在默认配置文件中指定要激活的环境:spring.profiles.active=dev
  2. 命令行方式:
  • --spring.profiles.active=指定的环境
  • java -jar 项目把包后的名称.jar --spring.profiles.active=指定的环境
  1. 虚拟机参数:
    在VM options中写入:-Dspring.profiles.active=指定的环境

配置文件的加载位置

  • Spring Boot启动会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件:

file:./config/ 指当前项目文件下的config文件夹中
file:./ 指当前项目文件路径下
classpath:/config 指类路径下的config
classpath:/ 指类路径的跟目录下

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖优先级低的配置内容。会形成一种互补配置。
我们也可以通过配置spring.config.location来改变默认配置。命令行指定的位置优先级是最高的!

spring.config.location=文件目录

项目以及打包好了之后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定的配置文件和默认加载的配置文件会共同起作用形成互补配置。

外部配置加载顺序

Spring Boot支持多种外部配置方式。他们优先级关系如下:(由高到低)

1.命令行参数
2.来自java:comp/env的JNDI属性
3.java系统属性(System.getProperties() )
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
10.@Configuration注解类上的@PropertySource
11.通过SpringApplication.setDefaultProperties指定的默认属性

参考官方文档:
https://docs.spring.io/spring-boot/docs/2.3.5.RELEASE/reference/htmlsingle/#boot-features-external-config

自动配置原理

配置文件到底能写什么?怎么写?自动配置的原理是什么?
配置文件能配置的属性参照:通用应用程序属性
自动配置原理:

  1. Spring Boot启动的时候加载主配置类,开启了自动注解功能 @EnableAutoConfiguration
  2. @EnableAutoConfiguration作用:
    利用AutoConfigurationImportSelector给容器中导入一些组件?
    可以查看public String[] selectImports(AnnotationMetadata annotationMetadata) {方法的内容。
    List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置。作用:

SpringFactoriesLoader.loadFactoryNames

扫描所有jar包类路径下的 META-INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties获取到EnableAutoConfiguration.class类(类名)添加到容器中

将类路径下的 META-INF/spring.factories 里面配置的EnableAutoConfiguration的值加入到了容器中。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置。这就是自动配置的开始。

  1. 每一个自动配置类自动配置功能。
  2. 以HttpEncodingAutoConfiguration为列Http编码自动配置,解释自动配置原理。
@Configuration(proxyBeanMethods = false)        //表示这是一个配置类,跟以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties({ServerProperties.class})        //启用ConfigurationProperties功能;将配置文件中对应的值于HttpEncodingAutoConfiguration绑定起来;并把ServerProperties加入到ioc容器中。
@ConditionalOnWebApplication(type = Type.SERVLET)        //Spring底层@Coditional注解作用:根据不同的条件,如果满足指定的条件,整个配置类的配置才会生效。    判断当前应用是不是web应用,如果是当前配置生效,不是则不生效。
@ConditionalOnClass({CharacterEncodingFilter.class})        //判断当前项目有没有这个类CharacterEncodingFilter;SpringMvc中进行乱码解决的过滤器。
@ConditionalOnProperty(prefix = "server.servlet.encoding",value = {"enabled"},matchIfMissing = true)        //判断配置文件中是否存在某个配置server.servlet.encoding.enabled;如果不存在判断也是成立的。    即使我们配置文件中不配置server.servlet.encoding.enabled=true,也是默认生效的。
public class HttpEncodingAutoConfiguration {
    //他已经和Spring Boot的映射文件映射了
    private final Encoding properties;
    //只有一个有参构造器,参数的值就会从容器中拿。
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    @Bean        //给容器中添加一个组件,这个注解的某些值需要从properties中获取
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
        return filter;
    }
    ……
}

根据当前不同的条件判断,决定这个配置是否生效。
一旦这个配置类生效;这个配置类就是会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的。

精髓:

  1. Spring Boot启动会加载大量的自动配置类。
  2. 我们需要的功能,有没有Spring Boot写好的自动配置类。
  3. 我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的的组件有,我们就不需要再来配置了,没有的话还是要自己配置的)。
  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值。

xxxAutoConfigurartion:自动配置类:给容器中添加组件。
xxxProperties:来封装配置文件中相关的属性。

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置类里面的所有内容才生效。


Conditional派生注解.png

可以通过,启用 debug=true属性 ,让控制台打印自动配置报告。
这样,就可以很方便的知道 ,哪些自动配置类生效。
Debug,默认是false ,True,表示开启Spring boot的debug模式 。

日志

日志框架

开发一个大型的系统;
很多时候都是用System.out.println("");将关键的数据打印在控制台;去掉?写在一个文件?
用框架来记录系统的一些运行时信息;日志框架
市面上的日志框架:
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j……


日志框架.png

左边选一个门面(抽象层)、右边选一个实现。
日志门面:SLF4J
日志实现:Logback

Spring Boot:底层框架是Spring,Spring框架默认是JCL、Spring Boot选用的是SLF4J和Logback;

SLF4J的使用

如何在系统中使用SLF4J框架:
以后开发的时候,日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法。应该给系统中导入SLF4J的jar包Logback的jar包

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

SLF4J的使用官方提供的使用,该导入的包官方也提示很全面。图示:

concrete-bindings.png

每一个日志的实现框架都有自己的配置文件。使用SLF4J配置文件还是做成日志实现框架的配置文件。

遗留问题

假设a系统开发的时候用的(SLF4J+Logback)但是要依赖Spring框架,可能还要依赖Hibernate框架、MyBatis框架等等,但可能每一个框架它的底层也用到了日志,还都不相同。比如Spring框架用到的(commons-logging)、Hibernate框架用到的(Jboss-logging)……
统一日志记录:即使是别的框架和我一起使用SLF4J进行统一使用。

官方图示:即排除掉原本框架调用的框架(狸猫换太子)

统一使用SLF4J.png

如何让系统中的所有日志都统一到SLF4J:
  1. 将系统中其他的日志框架先排除出去。
  2. 用中间包来替换原有的日志框架。(狸猫换太子包)
  3. 我们导入SLF4J其他的实现包。

Spring Boot日志关系

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

总结:

  1. Spring Boot底层也是使用的SLF4J+Logback的方式进行日志记录。
  2. Spring Boot也把其他的日志替换成了SLF4J
  3. 如果我们在Spring Boot中引入其他框架,一定要把这个框架的默认日志依赖移除掉。

Spring框架用的是commons-logging:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artfactId>commons-logging</artfactId>
        </exclusion>
      </exclusion>
    </dependency>

Spring Boot能自动适配所有的日志,而且底层使用SLF4J+Logback的方式记录日志,引入其他的框架的时候,只需要把这个框架依赖的日志框架排除掉;

日志使用

默认配置

Spring Boot默认帮我们配置好了日志;
设置日志(在配置文件中设置)

########调整日志的级别-->把cn.fantuan类的所有日志信息调整为trace级别
logging.level.cn.fantuan=trace

########指定日志输出的文件路径,在当前磁盘根路径下创建spring文件夹和里面的log文件夹;使用日志文件名为spring.log,他为默认日志文件名
#logging.file.path=/spring/log

########指定日志输出的文件名,没指定文件路径,则默认为当前项目路径
logging.file.name=D:/springboot.log

########在控制台输出的日志格式:%d{yyyy-MM-dd HH:mm:ss.SSS}:时间、[%thread]:线程ID、%-5level:左对齐显示日志级别、%logger{50}:全类名50个字符、%msg%n:日志信息+换行
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

########指定在文件中输出日志文件的格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} === [%thread] === %-5level === %logger{50} === %msg%n

    //记录器
    Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    void contextLoads() {
        //日志的级别:由低到高 trace < debug < info < warn < error
        //可以调整输出日志级别:日志就只会在这个级别以后的高级别生效

        //跟踪轨迹
        logger.trace("这是trace日志……");
        //调试信息
        logger.debug("这是debug日志……");

        //没有指定级别的就用的root级别,而root级别规定的是info
        //Spring Boot默认给我们使用的是info级别的,即就只会显示info级别及以后的级别信息
        //自己定义的一些信息
        logger.info("这是info日志……");
        //警告信息
        logger.warn("这是warn日志……");
        //错误信息
        logger.error("这是error日志……");
    }
}
指定配置

给类路径下放上每个日志框架自己的配置文件,Spring Boot就使用自己的默认配置文件。详细参考官网配置

切换日志框架

可以按照SLF4J日志适配图进行相关的切换。
SLF4J+Log4J的方式:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!--modelVersion 描述这个POM文件是遵从哪个版本的项目描述符-->
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.fantuan</groupId>
    <artifactId>spring-boot-02-logging</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-02-logging</name>
    <description>Demo project for Spring Boot</description>
    <!--导入了一个父级依赖,管理了一些版本号-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!--定义了java版本号-->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--Spring Boot中的starter-web模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--排除掉logback-classic-->
            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
                <!--排除掉log4j-to-slf4j-->
                <exclusion>
                    <artifactId>log4j-to-slf4j</artifactId>
                    <groupId>org.apache.logging.log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--导入slf4j-log4j12中间层-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <!--Spring Boot中的starter-test是用来单元测试的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!--maven插件-->
    <!--这个插件,可以将应用打包成一个可执行的jar包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

官方切换配置

<!--Spring Boot中的starter-web模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--排除掉spring-boot-starter-logging-->
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--引入spring-boot-starter-log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容