Spring Boot源碼剖析之Spring Boot應(yīng)用回顧

Spring Boot應(yīng)用回顧

約定由于配置

約定優(yōu)于配置:按約定編程狡门,是一種軟件設(shè)計規(guī)范视哑。

image

什么是Spring Boot

Spring boot官網(wǎng)

image

使用Spring Boot可以簡單的創(chuàng)建一個基于Spring 應(yīng)用的獨立的產(chǎn)品級的應(yīng)用家厌。
Spring Boot 的目的是簡化Spring應(yīng)用的開發(fā)壁却,盡可能的減少配置揖闸,盡快的讓你的Spring應(yīng)用跑起來蝌矛。

  • Spring Boot 是Pivotal團(tuán)隊研發(fā)
  • SpringBoot是基于Spring 4.0設(shè)計的会傲。
  • Spring Boot集成了大量的框架混卵,使得依賴包的版本沖突和引用不穩(wěn)定性得到了很好的解決。

Spring Boot 就是一種快速使用Spring的方式恶阴,并且可以省去繁瑣的配置诈胜。

Spring Boot主要特性

  • Spring Boot Starter(起步依賴):將常用依賴分組整合,將其合并到一個依賴中冯事,這樣就可以一次性添加到Maven或Gradle構(gòu)建中焦匈。
image.png
  • JavaConfig方式配置
    Spring發(fā)展史:


    image

Spring Boot是基于Spring4.0設(shè)計的,當(dāng)時的Spring4.0已經(jīng)支持了JavaConfig方式桅咆。

  • 自動配置:利用Spring對條件化配置的支持括授,合理地推測應(yīng)用所需的bean并自動化配置他們。


    image.png
  • SpringBoot內(nèi)置Servlet容器岩饼,部署簡單。

Spring Boot案例實現(xiàn)

目標(biāo):使用Spring initializr創(chuàng)建springboot工程薛夜,編寫Controller籍茧,并成功請求Controller,返回響應(yīng)梯澜。
1)創(chuàng)建Spring Boot工程:


image

填寫項目基本信息


image

選擇依賴
image

創(chuàng)建完成之后的目錄結(jié)構(gòu):
image

2)創(chuàng)建 Controller

package com.xdf.springbootdemo.controller;

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

/**
 * @author xdf
 * @version 1.0
 * @date Create in 9:32 2021/6/23
 * @description 測試Controller
 * @modifiedBy
 */

@RestController
public class DemoController {

    @RequestMapping("/demo")
    public String demo() {
        return "demo";
    }
}

注意:controller必須放在SpringBootDemoApplication啟動類下面的包中寞冯,也就是說controller的包路徑必須必啟動了深渴析。
因為SpringBoot包掃描的根目錄是啟動類所在包。

3)啟動測試
通過SpringBootDemoApplication啟動類中的main方法啟動應(yīng)用吮龄。
訪問http://localhost:8080/demo觀察結(jié)果:

image

思考:

  1. starter是什么俭茧?我們?nèi)绾稳ナ褂眠@些starter?
  2. 為什么包掃描只會掃描核心啟動類所在的包及其子包
  3. 在springBoot啟動的過程中漓帚,是如何完成自動裝配的母债?
  4. 內(nèi)嵌Tomcat是如何被創(chuàng)建及啟動的?
  5. 使用了web場景對應(yīng)的starter尝抖,springmvc是如何自動裝配毡们?

Spring Boot熱部署

在修改代碼后需要驗證時,需要重啟項目昧辽。Spring開發(fā)團(tuán)隊提供了一個插件:spring-boot-devtools衙熔,解決啟動緩慢問題。(開發(fā)階段提高效率搅荞,不建議線上使用)

熱部署演示

引入依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

配置idea自動編譯:


image

ctrl+alt+shift+/調(diào)出窗口:


image

選擇registry红氯,在新彈出的窗口中找到并勾選下面的選項:

image

重啟項目,調(diào)用請求http://localhost:8080/demo查看
image

修改Controller:

@RestController
public class DemoController {

    @RequestMapping("/demo")
    public String demo() {
        return "熱部署 demo";
    }
}

稍等一會咕痛,再次調(diào)用http://localhost:8080/demo

image

到此就實現(xiàn)了應(yīng)用熱部署演示痢甘。

熱部署原理分析

Spring官網(wǎng)對自動部署的介紹:


image

自動部署插件會監(jiān)聽classpath下面的文件,一旦文件有變化暇检,就會重啟产阱。重啟的唯一方式就是更新classpath。

所以它的觸發(fā)條件是classpath下面的文件變化块仆,因此需要配合idea的自動編譯功能构蹬。自動編譯后,會將編譯后的class文件更新到classpath下面悔据,觸發(fā)spring-boot-devtools的重啟功能庄敛,完成應(yīng)用更新。

spring-boot-devtools的熱部署功能是怎么實現(xiàn)的科汗?
官方描述:

image

工具是通過兩個classloader來實現(xiàn)的藻烤,一個classloader加載不變的類,一個classloader是加載我們自己寫的class头滔。

image.png

兩個類加載器分別加載機(jī)制驗證:
編寫測試代碼

package com.xdf.springbootdemo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;


/**
 * @author xdf
 * @version 1.0
 * @date Create in 10:12 2021/6/23
 * @description spring boot devtools類加載驗證
 * @modifiedBy
 */
@Component
public class DevtoolTest implements InitializingBean {
    private static final Logger log = LoggerFactory.getLogger(DevtoolTest.class);

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("guava jar classlodaer:${}" , DispatcherServlet.class.getClassLoader());
        log.info("DevtoolsTest classlodaer:${}" , this.getClass().getClassLoader());
    }
}
image

輸出結(jié)果驗證怖亭,發(fā)現(xiàn)DispatchorServlet是AppClassLoader加載的。而我們自己寫的DevtoolsTest類的加載器是RestartClassloader坤检。

如果不引入Devtools兴猩,他們的類加載器都是AppClassloader。

Spring Boot 熱部署排除資源

某些資源在更改后不一定需要觸發(fā)重新啟動早歇。例如倾芝,Thymeleaf模板可以就地編輯讨勤。默認(rèn)情況下,改變資源 /META-INF/maven 晨另, /META-INF/resources 潭千,/resources , /static 借尿, /public 刨晴, 或 /templates 不觸發(fā)重新啟動,但確會觸發(fā)現(xiàn)場重裝垛玻。如果要自定義這些排除項割捅,則可以使用該 spring.devtools.restart.exclude 屬性。例如帚桩,僅排除 /static 亿驾, /public 您將設(shè)置以下屬性:

找到devtools jar包,打開spring.factories文件

image

找到LocalDevToolsAutoConfiguration類


image

點擊進(jìn)去:


image

找到DevToolsProperties類账嚎,點擊進(jìn)入
在這個類中默認(rèn)排除了:
image

如果我們想更改默認(rèn)值
我們現(xiàn)在找到prefix:

image

并且這個類里面有一個內(nèi)部類Restart莫瞬,Restart方法中的exclude是我們需要修改的值。


image

并且這個屬性提供了setter方法:


image

因此郭蕉,我們需要在配置文件中配置的屬性為:
spring.devtools.restart.exclude

因此我們可以在application.propterties中這樣配置:

spring.devtools.restart.exclude=static/**,templates/**

Spring Boot 全局配置文件

全局配置文件概述及優(yōu)先級

Spring Boot使用一個application.properties和application.yml文件作為全局配置文件疼邀。

配置文件的加載目錄:

image

分別對應(yīng):

–file:./config/ 
–file:./ 
–classpath:/config/ 
–classpath:/
image

同時,序號也是配置文件的加載順序召锈。
其中旁振,序號越大的配置文件的屬性優(yōu)先級越低。(后面加載的配置文件不會覆蓋前面配置的配置文件)

不同配置文件的不同屬性涨岁,會相互互補(bǔ)拐袜。

properties和yml文件在相同目錄下,誰的配置優(yōu)先級高梢薪?
springboot在2.4.0之前默認(rèn)properties文件的優(yōu)先級更高蹬铺,在2.4.0之后是yml文件優(yōu)先級更高。
如果在2.4.0z之后的版本還是希望是properties優(yōu)于yml秉撇,可以配置:

spring.config.use-legacy-processing = true

自定義配置文件名:

$ java -jar myproject.jar --spring.config.name=myproject 

指定配置文件:

java -jar run-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties 

和其他配置文件互補(bǔ)甜攀。

application.properties配置文件

Spring boot在啟動的時候會加載application.properties文件。除了框架的配置信息之外琐馆。我們還可以自定義配置屬性注入规阀。

Person:

package com.xdf.springbootdemo.pojo;

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

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author xdf
 * @date Create in 13:45 2021/6/23
 * @description 人
 * @modifiedBy
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {

    private int id;
    /**
     * 名字
     */
    private String name;

    /**
     * 愛好
     */
    private List hobby;

    /**
     * 家庭成員
     */
    private String[] family;

    /**
     *
     */
    private Map map;

    /**
     * 寵物
     */
    private Pet pet;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public List getHobby() {
        return hobby;
    }

    public void setHobby(List hobby) {
        this.hobby = hobby;
    }

    public String[] getFamily() {
        return family;
    }

    public void setFamily(String[] family) {
        this.family = family;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public Pet getPet() {
        return pet;
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", hobby=" + hobby +
                ", family=" + Arrays.toString(family) +
                ", map=" + map +
                ", pet=" + pet +
                '}';
    }
}

Pet:

package com.xdf.springbootdemo.pojo;

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

/**
 * @author xdf
 * @version 1.0
 * @date Create in 13:45 2021/6/23
 * @description 寵物
 * @modifiedBy
 */

@Component
@ConfigurationProperties(prefix = "pet")
public class Pet {
    private String type;
    private String name;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Pet{" +
                "type='" + type + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

application.properties

person.id=1
person.name=tom
person.hobby=吃飯,睡覺瘦麸,打豆豆
person.family=爸爸
person.map.ley1=v1
person.map.ley2=v2
person.pet.type=dog
person.pet.name=大黃

為了idea能給自定義屬性注入提示姥敛,需要引入maven依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

application.yml配置文件

  • yml與xml比,少了結(jié)構(gòu)性代碼瞎暑,數(shù)據(jù)更直接
  • 相比properties文件更簡潔
  • 擴(kuò)展名為yml或yaml
  • yml文件使用“key:(空格)”格式配置屬性彤敛,使用縮進(jìn)控制層級關(guān)系。

1)普通類型配置

person:
  id: 1
  name: tom

2)list/數(shù)組類型配置

person:
  hobby:
    - 吃飯
    - 睡覺
    - 打豆豆

person:
  hobby:
    吃飯
    睡覺
    打豆豆

person:
  hobby: [吃飯,睡覺,打豆豆]
  1. map/對象類型配置
person:
  map:
    k1: v1
    k2: v2

person:
  map: {k1: v1, k2: v2}

屬性注入

使用Spring Boot全局配置文件時:
如果配置的是Spring Boot的已有屬性了赌,Spring Boot會自動掃描讀取這些配置并覆蓋默認(rèn)配置墨榄。
如果是自定義屬性,必須在程序中注入這些信息才能生效勿她。

屬性注入常用注解

  • @Configration:聲明一個類作為配置類
  • @Bean:將方法返回值作為bean放入IoC容器
  • @Value:屬性注入
  • @ConfigurationProperties:批量屬性注入
  • @PropertySource:指定外部屬性文件袄秩。

@Value屬性值注入

數(shù)據(jù)庫數(shù)據(jù)源配置示例:
引入maven依賴

<dependency>
    <groupId>com.github.drtrang</groupId>
    <artifactId>druid-spring-boot2-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.24</version>
</dependency>

自定義配置屬性:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring
jdbc.username=root
jdbc.password=123456

自定義配置類:

package com.xdf.springbootdemo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author xdf
 * @version 1.0
 * @date Create in 14:34 2021/6/23
 * @description jdbc配置類
 * @modifiedBy
 */
@Configuration
public class JdbcConfig {

    /**
     * jdbc驅(qū)動
     */
    @Value("${jdbc.driverClassName}")
    private String driverClassName;
    /**
     * 數(shù)據(jù)庫url
     */
    @Value("${jdbc.url}")
    private String url;

    /**
     * 用戶名
     */
    @Value("${jdbc.username}")
    private String username;

    /**
     * 密碼
     */
    @Value("${jdbc.password}")
    private String password;


    @Bean
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();

        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "JdbcConfig{" +
                "driverClassName='" + driverClassName + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

通過@Configuration注解讓Spring掃描配置類,使用@value注入屬性值逢并。使用@Bean注解之剧,將dataSoure方法的返回值放到IoC容器。

@ConfigurationProperties批量注入

使用批量注入方式重新配置數(shù)據(jù)源:
maven依賴注入:

<dependency>
    <groupId>com.github.drtrang</groupId>
    <artifactId>druid-spring-boot2-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.24</version>
</dependency>

自定義配置屬性:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring
jdbc.username=root
jdbc.password=123456

自定義配置類:

package com.xdf.springbootdemo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author xdf
 * @version 1.0
 * @date Create in 14:57 2021/6/23
 * @description 批量注入方式配置jdbc數(shù)據(jù)源
 * @modifiedBy
 */
@Configuration
@ConfigurationProperties(prefix = "jdbc")
public class BatchJdbcConfig {

    /**
     * 驅(qū)動類名
     */
    private String driverClassName;

    /**
     * jdbc url
     */
    private String url;

    /**
     * 用戶名
     */
    private String username;

    /**
     * 密碼
     */
    private String password;


    /**
     * 將數(shù)據(jù)源bean放到ioc容器
     * @return dataSource
     */
    @Bean
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        return druidDataSource;
    }

    /**
     * 批量方式必須實現(xiàn)setter方法
     */




    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 方便打印觀察
     * @return
     */
    @Override
    public String toString() {
        return "BatchJdbcConfig{" +
                "driverClassName='" + driverClassName + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

三方配置

引入的三方j(luò)ar包中的類是無法修改的砍聊,沒辦法在原本的類上面去做屬性注入背稼。但是我們也有辦法做屬性注入。下面看個例子:

三方類(假設(shè)不能修改):

package com.xdf.springbootdemo.pojo;

/**
 * @author xdf
 * @version 1.0
 * @date Create in 15:20 2021/6/23
 * @description 模擬三方j(luò)ar包中的類
 * @modifiedBy
 */
public class AnotherComponent {

    private String name;

    private String address;


    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "AnotherComponent{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

我們需要對name和address進(jìn)行屬性注入玻蝌。
編寫配置類:

/**
 * @author xdf
 * @version 1.0
 * @date Create in 15:22 2021/6/23
 * @description 三方j(luò)ar包中的類的屬性注入
 * @modifiedBy
 */
@Configuration
public class AnotherConfig {

    @Bean
    @ConfigurationProperties(prefix = "another")
    public AnotherComponent anotherComponent() {
        return new AnotherComponent();
    }
}

三方類通過@Bean放入Ioc容器蟹肘。
在@Bean方法上面使用@ConfigurationProperties注解標(biāo)記

屬性配置:

another.name=anothername
another.address=address

例如:

@Data 
@Component 
@ConfigurationProperties("acme.my-person.person") 
public class OwnerProperties { 
    private String firstName; 
}
acme: 
  my-person: 
    person: 
      first-name: 泰森

松散綁定

Spring Boot 支持使用一些寬松的規(guī)則將屬性綁定到@ConfigurationProperties bean。


image.png

@ConfigurationProperties VS @Value

image.png

Spring Boot 日志框架

日志框架介紹

日志框架設(shè)計思想


image.png

市面上常見的日志框架:
JCL俯树、SLF4J帘腹、Jboss-logging、log4j许饿、log4j2阳欲、logback等。
其中細(xì)分為:


image.png
  • Jboss-logging 是應(yīng)用在特殊場景的日志抽象層框架陋率,我們一般不用
  • JCL是Commons包中提供的日志框架球化,spring默認(rèn)在用,但不維護(hù)了
  • SLF4J是log4j翘贮、logback的抽象層赊窥,三個抽象層中,前兩個不用狸页,一般就用SLF4J
  • jul是jdk提供的日志框架锨能,功能不夠強(qiáng)大
  • log4j存在性能問題,作者開發(fā)了升級版logback
  • logback跟log4j都遵循SLF4J的抽象層框架規(guī)范芍耘,性能比log4j強(qiáng)大址遇,推薦使用
  • log4j2是Apache開發(fā)的另外一個日志框架,但是應(yīng)用得比較少斋竞,不推薦

Spring boot采用的是SLF4J+logback方案倔约。

SLF4J的使用

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

下圖是SLF4J的官方提供的示例圖。SEF4J框架作為其他日志實現(xiàn)框架的門面直接應(yīng)用到應(yīng)用程序中坝初。


image

如果不引入日志實現(xiàn)框架浸剩,日志無法輸出钾军。logbank,slf4j-simple绢要,slf4j-nop是遵循slf4j規(guī)范的日志實現(xiàn)框架吏恭,只要引入jar包就能使用。
而log4j重罪、jdk日志框架樱哼,在開發(fā)的時候還沒有slf4j規(guī)范,因此需要適配層slf4j-log412剿配、slf4j-jdk14來進(jìn)行適配搅幅。

注意:由于每一個日志的實現(xiàn)框架都有自己的配置文件,所以在使用 SLF4j 之后呼胚,配置文件還是要使用實現(xiàn)日志框架的配置文件茄唐。

統(tǒng)一日志框架的使用

不同的三方框架使用不同的日志框架,在應(yīng)用中進(jìn)行整合的時候砸讳,怎么使用統(tǒng)一的日志框架琢融?


image

如果引入的三方框架也引入了日志實現(xiàn)類,那么

  • 在引入三方框架的時候要排除三方框架引入的日志實現(xiàn)框架簿寂。
  • 引入一個轉(zhuǎn)換層(jcl-over-slf4j漾抬、log4j-over-slf4j、jul-to-slf4j)
  • 引入我們選擇的日志實現(xiàn)框架

Spring Boot中的日志關(guān)系

1)排除其他日志框架
在Spring Boot的spring-boot-dependencies中常遂,將三方框架的其他日志實現(xiàn)框架進(jìn)行了排除纳令。

image

2)統(tǒng)一框架引入替換包
Spring boot 在spring-boot-starter-logging中引入了自己選擇的日志實現(xiàn)框架
image

image

引入日志框架轉(zhuǎn)換層
image

日志相關(guān)Maven依賴關(guān)系:
image

Spring Boot 的日志使用

Spring Boot日志級別測試:

@Test
void testLog() {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    logger.trace("trace 日志");
    logger.debug("debug 日志");
    logger.info("info 日志");
    logger.warn("warn 日志");
    logger.error("error 日志");
}

打印


image

Spring Boot默認(rèn)日志級別是info級別

Spring Boot的日志格式是

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 
# %d{yyyy-MM-dd HH:mm:ss.SSS} 時間 
# %thread 線程名稱 
# %-5level 日志級別從左顯示5個字符寬度 
# %logger{50} 類名 
# %msg%n 日志信息加換行

至于為什么 Spring Boot 的默認(rèn)日志輸出格式是這樣?
我們可以在 Spring Boot 的源碼里找到答案克胳。


image

自定義日志輸出

可以直接在配置文件編寫日志相關(guān)配置

# 日志配置 
# 指定具體包(com.xdf)的日志級別 
logging.level.com.xdf=debug 
# 控制臺和日志文件輸出格式 
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 
# 日志輸出路徑平绩,默認(rèn)文件spring.log 
logging.file.path=spring.log 
#logging.file.name=log.log 

關(guān)于日志的輸出路徑,可以使用 logging.file 或者 logging.path 進(jìn)行定義漠另,兩者存在關(guān)系如下表捏雌。


image.png

替換日志框架

因為 Log4j 日志框架已經(jīng)年久失修,原作者都覺得寫的不好笆搓,所以下面演示替換日志框架為 Log4j2 的 方式性湿。根據(jù)官網(wǎng)我們 Log4j2 與 logging 需要二選一,因此修改 pom如下

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
    <exclusions> 
        <exclusion> 
            <artifactId>spring-boot-starter-logging</artifactId> 
            <groupId>org.springframework.boot</groupId> 
        </exclusion> 
    </exclusions> 
</dependency> 
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-log4j2</artifactId> 
</dependency>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末满败,一起剝皮案震驚了整個濱河市肤频,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌算墨,老刑警劉巖宵荒,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡报咳,警方通過查閱死者的電腦和手機(jī)侠讯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來少孝,“玉大人继低,你說我怎么就攤上這事∩宰撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵柴底,是天一觀的道長婿脸。 經(jīng)常有香客問我,道長柄驻,這世上最難降的妖魔是什么狐树? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮鸿脓,結(jié)果婚禮上抑钟,老公的妹妹穿的比我還像新娘。我一直安慰自己野哭,他們只是感情好在塔,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拨黔,像睡著了一般蛔溃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篱蝇,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天贺待,我揣著相機(jī)與錄音,去河邊找鬼零截。 笑死麸塞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涧衙。 我是一名探鬼主播哪工,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绍撞!你這毒婦竟也來了正勒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤傻铣,失蹤者是張志新(化名)和其女友劉穎章贞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡鸭限,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年蜕径,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片败京。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡兜喻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赡麦,到底是詐尸還是另有隱情朴皆,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布泛粹,位于F島的核電站遂铡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏晶姊。R本人自食惡果不足惜扒接,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望们衙。 院中可真熱鬧钾怔,春花似錦、人聲如沸蒙挑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脆荷。三九已至凝垛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜓谋,已是汗流浹背梦皮。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留桃焕,地道東北人剑肯。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像观堂,于是被迫代替她去往敵國和親让网。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355