Spring Boot(一)Spring Boot核心技術(shù)

目錄
一、Spring Boot入門
? 1 Spring Boot簡介
? 2 微服務(wù)
? 3 入門案例
? 4 Spring Boot簡化部署
? 5 入門案例解析
? 6 使用Spring Initializer快速創(chuàng)建Spring Boot項目(以idea為例)
? 7 springboot內(nèi)嵌tomcat啟動方式和非內(nèi)嵌tomcat啟動方式
二、Spring Boot配置
? 1 簡介
? 2 yaml文件
? 3 配置文件注入
? 4 配置文件占位符
? 5 Profile
? 6 配置文件加載位置
? 7 外部配置加載順序
? \color{red}{8 自動配置原理}
三、日志
? 1 市面上的日志框架
? 2 SLF4j使用
? 3 SpringBoot日志關(guān)系
? 4 日志使用
? 5 切換日志框架
?
更多知識可參考:http://www.itdecent.cn/p/7dbaac902074


一、Spring Boot入門

1 Spring Boot簡介
  • 簡化Spring應(yīng)用開發(fā)的一個框架
  • 整個Spring技術(shù)棧的一個大整合
  • 將J2EE開發(fā)的一站式解決方案
2 微服務(wù)

Martin Fowler和James Lewis的《Microservices》是第一篇詳細介紹微服務(wù)的文章。
Microservices全文
spring微服務(wù)官網(wǎng)

3 入門案例

在此之前,你需要掌握Spring框架和Maven的使用.

  • 創(chuàng)建maven項目,導(dǎo)入依賴
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  • 編寫主程序,啟動Spring Boot應(yīng)用
/**
 * SpringBootApplication用來標注一個主程序,說明這是一個Spring Boot應(yīng)用
 */
@SpringBootApplication
public class FirstSpringBootApplication {
    public static void main(String[] args) {
        //spring應(yīng)用啟動
        SpringApplication.run(FirstSpringBootApplication.class, args);
    }
}
  • 編寫controller,service
@RestController
public class FirstController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello world";
    }
}
4 Spring Boot簡化部署
  • 在pom.xml中導(dǎo)入插件,這個插件可以將應(yīng)用打包成一個jar包
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • 打包過程
    在idea的右側(cè)欄找到maven,找到并點擊package.

    此時就會在控制臺輸出打包的信息

    在控制臺給出的路徑中找到生成的jar包,使用命令行運行命令java -jar springboot-1.0-SNAPSHOT.jar,運行成功會出現(xiàn)如下界面

    此時再訪問http://localhost:8080/hello,結(jié)果和在idea中運行結(jié)果一致,則部署成功.
5 入門案例解析
1) pom.xml文件
  • spring-boot-starter-parent,父項目是spring-boot-dependencies,它用來管理SpringBoot項目里的依賴版本
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>

在以后的項目開發(fā)過程中,出現(xiàn)在spring-boot-dependencies的依賴就不需要寫版本號了

  • spring-boot-starter-web,是Spring Boot場景啟動器,它幫我們導(dǎo)入了web模塊正常運行所依賴的組件.
    Spring Boot將所有的功能場景都抽取出來,做成一個starter(啟動器),只需要在項目引入這些starter,相關(guān)場景的所有依賴都會導(dǎo)入進來
2) 主程序類

?? @SpringBootApplication,標注在某個類上,說明這個類是Spring Boot的主配置類,Spring Boot就應(yīng)該運行在這個類的main()方法來啟動應(yīng)用.我們進入這個注解可以看到

@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}
)}
)

??@SpringBootConfiguration,Spring Boot的配置類,標注在某個類上表示這是一個Spring Boot的配置類.而@SpringBootConfiguration注解上又標注了@Configuration,@Configuration表明某個類是一個配置類,配置類和配置文件有相同的作用,是容器中的一個組件(@Component)
?? @EnableAutoConfiguration,SpringBoot開啟自動配置功能.在這個注解上標注了@AutoConfigurationPackage,他是自動配置包,這個注解上又標注了@Import,它是Spring的底層注解.@AutoConfigurationPackage將主配置類(@SpringBootApplication標注的類)所在包及子包里面的的所有組件掃描到Spring容器;在@EnableAutoConfiguration上還標注了@Import({AutoConfigurationImportSelector.class}),它給容器導(dǎo)入組件AutoConfigurationImportSelector,而AutoConfigurationImportSelector是一個導(dǎo)入組件的選擇器,它將所有需要導(dǎo)入的組件以全類名的方式返回,最終會給容器倒入很多自動配置類(xxxAutoConfiguration),這些配置類會給容器導(dǎo)入這個場景所需要的所有組件,并配置好這些組件,它為我們免去了手動編寫配置文件和注入組件的工作.Spring Boot在啟動時從類路徑下的
META-INF/spring-autoconfigure-metadata.properties獲取指定的值,將這些值作為自動配置類導(dǎo)入到容器中,自動配置類就生效了.也就是說,J2EE的整體整合解決方案和自動配置都在spring-boot-autoconfigure-2.1.6.RELEASE.jar里`

6 使用Spring Initializer快速創(chuàng)建Spring Boot項目(以idea為例)
  • 新建Spring Initializer項目


  • 填寫包名和項目名


  • 需要什么功能,就加入相關(guān)的組件


  • finish



    系統(tǒng)生成了項目目錄和主程序


7 springboot內(nèi)嵌tomcat啟動方式和非內(nèi)嵌tomcat啟動方式

springboot內(nèi)嵌tomcat啟動方式和非內(nèi)嵌tomcat啟動方式可參考:
https://www.cnblogs.com/ysq2018China/p/10241201.html

二、Spring Boot配置

1 簡介

1.Spring Boot使用一個全局的配置文件,配置文件名是固定的;

  • application.properties
  • application.yml

2.配置文件作用:修改Spring Boot自動配置的默認值

3.配置文件放在src/main/resources目錄或者類路徑/config下

2 yaml文件
1) YAML(YAML Ain't Markup Language),以數(shù)據(jù)為中心,比json、xml等更適合做配置文件
  • yaml配置示例
server:
  port: 8081
  • xml配置示例
<server>
  <port>8081</port>
</server>
2) YAML語法
* YAML基本語法

– k:(空格)v:表示一對鍵值對(空格必須有);
– 以空格的縮進來控制層級關(guān)系;只要是左對齊的一列數(shù)據(jù),都是同一個層級的
–縮進時不允許使用Tab鍵,只允許使用空格。
–縮進的空格數(shù)目不重要,只要相同層級的元素左側(cè)對齊即可
–大小寫敏感

* YAML 支持的三種數(shù)據(jù)結(jié)構(gòu)

– 對象:鍵值對的集合
– 數(shù)組:一組按次序排列的值
– 字面量:單個的、不可再分的值

* 對象、Map(屬性和值)(鍵值對):

k: v:在下一行來寫對象的屬性和值的關(guān)系;注意縮進;
對象還是k: v的寫法

friends:
        name: zhangsan
        age: 20

行內(nèi)寫法:

friends: {name: zhangsan,age: 18}
* 數(shù)組(List,Set):

用- 值表示數(shù)組中的一個元素

pets:
 - cat
 - dog
 - pig

行內(nèi)寫法

pets: [cat,dog,pig]
* 字面量:普通的值(數(shù)字,字符串,布爾)
  • k: v:字面直接來寫;
  • 字符串默認不用加上單引號或者雙引號;
  • "":雙引號;不會轉(zhuǎn)義字符串里面的特殊字符;特殊字符會作為本身想表示的意思
    name: "zhangsan \n lisi":輸出: zhangsan 換行 lisi
  • '':單引號;會轉(zhuǎn)義特殊字符,特殊字符最終只是一個普通的字符串數(shù)據(jù)
    name: ‘zhangsan \n lisi’:輸出;zhangsan \n lisi
3 配置文件注入
1) yaml方式

在之前創(chuàng)建的spring-boot-quick項目的基礎(chǔ)上加上如下代碼

  • application.yaml配置文件
person:
  name: zhangsan
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: 12}
  lists:
    - lisi
    - zhan
  dog:
    name: 小狗
    age: 2
  • Person對象
/**
 * @author:TiaNa
 * 配置文件中配置的每一個屬性的值,映射到這個組件中
 * 只有這個組件是日期中的組件,才能使用容器提供的功能
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean boss;
    private Date birthday;

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

    get/set方法...
}
  • pom.xml,導(dǎo)入配置文件處理器,以后編寫配置就有提示了
<!--導(dǎo)入配置文件處理器,配置文件進行綁定就會有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
  • 重新運行SpringBootQuickApplication,編寫測試代碼
/**
 * springboot 單元測試
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootQuickApplicationTests {

    @Autowired
    Person person;

    @Test
    public void contextLoads() {
        System.out.println(person);
    }
}
  • 運行單元測試代碼后


2) properties方式

application.properties文件

# 配置person的值
person.name=李四
person.age=18
person.birthday=2018/7/17
person.boss=false
person.dog.name=10
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
3) @value獲取值

上面兩節(jié),不管是yaml方式還是properties方式注入,我們都使用的是@ConfigurationProperties注解獲取值,但其實@value注解也可以實現(xiàn)。

@Component
public class Person {
   /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}從環(huán)境變量、配置文件中獲取值/#{SpEL}"></property>
     * <bean/>
     */
    @Value("${person.last-name}")
    private String lastName;
    @Value("#{11*2}")
    private Integer age;
    @Value("true")
    private Boolean boss;

    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
4) @value和@ConfigurationProperties獲取值比較
序號 @value @ConfigurationProperties
功能 一個一個注入 批量注入配置文件的屬性
松散綁定(松散語法) 不支持 支持
SpEL(Spring表達式) 支持 不支持
JSP303數(shù)據(jù)校驗 不支持 支持
復(fù)雜類型封裝 不支持 支持
  • 松散綁定
    屬性名匹配規(guī)則(Relaxed binding)以下方式@ConfigurationProperties都能用firstName匹配
    – person.firstName:使用標準方式
    – person.first-name:大寫用-
    – person.first_name:大寫用_
    – PERSON_FIRST_NAME: 推薦系統(tǒng)屬性使用這種寫法
  • 配置文件注入值數(shù)據(jù)校驗(JSR303數(shù)據(jù)校驗)
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
   //lastName必須是郵箱格式
    @Email
    private String lastName;

如果說,我們只是在某個業(yè)務(wù)邏輯中需要獲取配置文件中的某個值,使用@value;如果說,我們專門編寫了一個JavaBean來和配置文件進行映射,需要使用@ConfigurationProperties。

5) @PropertySource、@ImportSource和@Bean
  • @PropertySource:加載指定的配置文件;
/**
 * 將配置文件中配置的每一個屬性的值,映射到這個組件中
 * @ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關(guān)的配置進行綁定;
 *      prefix = "person":配置文件中哪個下面的所有屬性進行一一映射
 *
 * 只有這個組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;
 *  @ConfigurationProperties(prefix = "person")默認從全局配置文件中獲取值;
 *
 */
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
//@Validated
public class Person {

    /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}從環(huán)境變量、配置文件中獲取值/#{SpEL}"></property>
     * <bean/>
     */

   //lastName必須是郵箱格式
   // @Email
    //@Value("${person.last-name}")
    private String lastName;
    //@Value("#{11*2}")
    private Integer age;
    //@Value("true")
    private Boolean boss;
  • @ImportResource:導(dǎo)入Spring的配置文件,讓配置文件里面的內(nèi)容生效;Spring Boot里面沒有Spring的配置文件,我們自己編寫的配置文件,也不能自動識別;@ImportResource標注在一個配置類上使Spring的配置文件生效,加載進來;
@ImportResource(locations = {"classpath:beans.xml"})
  • @Bean
/**
 * @Configuration:指明當前類是一個配置類;就是來替代之前的Spring配置文件
 * 在配置文件中用<bean><bean/>標簽添加組件
 */
@Configuration
public class MyAppConfig {

    //將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名
    @Bean
    public HelloService helloService02(){
        System.out.println("配置類@Bean給容器中添加組件了...");
        return new HelloService();
    }
}

SpringBoot推薦給容器中添加組件的方式:推薦使用全注解的方式
1、配置類@Configuration(相當于Spring配置文件)
2、使用@Bean給容器中添加組件

4 配置文件占位符
1) 隨機數(shù)
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
2) 占位符獲取之前配置的值,如果沒有可以是用:指定默認值
person.last-name=張三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
5 Profile
1)多Profile文件

我們在主配置文件編寫的時候,文件名可以是application-{profile}.properties/yml,默認使用application.properties的配置;

2)yml支持多文檔塊方式
server:
  port: 8081
spring:
  profiles:
    active: prod

---
server:
  port: 8083
spring:
  profiles: dev


---

server:
  port: 8084
spring:
  profiles: prod  #指定屬于哪個環(huán)境
3)激活指定profile(三種方式)
  • 在配置文件中指定
spring.profiles.active=dev
  • 命令行,可以直接在測試的時候,配置傳入命令行參數(shù)
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
  • 虛擬機參數(shù)
?   -Dspring.profiles.active=dev
6 配置文件加載位置

springboot 啟動會掃描以下位置的application.properties或者application.yml文件作為Spring boot的默認配置文件:

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

優(yōu)先級由高到底,高優(yōu)先級的配置會覆蓋低優(yōu)先級的配置;
SpringBoot會從這四個位置全部加載主配置文件;互補配置
我們還可以通過spring.config.location來改變默認的配置文件位置
項目打包好以后,我們可以使用命令行參數(shù)的形式,啟動項目的時候來指定配置文件的新位置;指定配置文件和默認加載的這些配置文件共同起作用形成互補配置;

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
7 外部配置加載順序

Spring Boot 支持多種外部配置方式
這些方式優(yōu)先級參考官方文檔:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config
①命令行參數(shù)
所有的配置都可以在命令行上進行指定,多個配置用空格分開; --配置項=值

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

②來自java:comp/env的JNDI屬性
③Java系統(tǒng)屬性(System.getProperties())
④操作系統(tǒng)環(huán)境變量
⑤RandomValuePropertySource配置的random.屬性值
==
由jar包外向jar包內(nèi)進行尋找;==
==
優(yōu)先加載帶profile==
⑥jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
⑦jar包內(nèi)部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
==
再來加載不帶profile*==
⑧jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
⑨jar包內(nèi)部的application.properties或application.yml(不帶spring.profile)配置文件
⑩ @Configuration注解類上的@PropertySource
①①通過SpringApplication.setDefaultProperties指定的默認屬性

8 \color{red}{自動配置原理}(以SprinBoot2.1.8源碼為例)

配置文件能配置的屬性參照

1)SpringBoot啟動時加載主配置類,開啟了自動配置功能@EnableAutoConfiguration
2)@EnableAutoConfiguration作用:利用AutoConfigurationImportSelector給容器中導(dǎo)入組件,可以查看selectImports方法中的內(nèi)容:
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = 
this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
  • 這個方法用來獲取候選的配置
  • SpringFactoriesLoader.loadFactoryNames掃描所有jar包類路徑下META-INF/spring.factories,把掃描到的這些文件內(nèi)容包裝成Properties對象,從properties中獲取到EnableAutoConfiguration.class類(類名)對應(yīng)的值,然后把它們添加進容器中。
  • 最后將類路徑下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.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
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.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
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.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
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.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
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.groovy.template.GroovyTemplateAutoConfiguration,\
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.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.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
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.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都是容器中的組件,都加入到容器中,用它們做自動配置
3)每一個配置類進行自動配置(以HttpEncodingAutoConfiguration為例)
@Configuration      
@EnableConfigurationProperties({HttpProperties.class})    
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }
    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
      filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
      filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }

  • @Configuration表示是一個配置類,和以前編寫的配置文件一樣,可以給容器中加入組件;
  • @EnableConfigurationProperties 啟用指定類的ConfigurationProperties功能,將配置文件對應(yīng)的值和HttpProperties綁定,并將HttpProperties加入到ioc容器中;
  • @ConditionalOnWebApplication,spring底層@Conditional注解,如果滿足某個條件,整個配置類里的配置才能生效; @ConditionalOnWebApplication就是判斷當前應(yīng)用是否是web應(yīng)用,如果是則生效;
  • @ConditionalOnClass判斷當前有沒有CharacterEncodingFilter這個類,springmvc中解決亂碼的過濾器
  • @ConditionalOnProperty判斷是否存在spring.http.encoding.enabled;如果不存在,判斷也是成立的。即使配置文件中不配置默認也生效。
  • HttpEncodingAutoConfiguration只有一個有參構(gòu)造器的情況下,參數(shù)值就會從容器中拿;
  • @Bean給容器中添加組件,這個組件的某些值需要從properties中獲取,而properties已經(jīng)和SpringBoot的配置文件映射了。

根據(jù)當前條件判斷配置類是否生效,一旦生效,配置類就會給容器添加給中組件,這些組件的屬性是從對應(yīng)的properties中獲取的,這些類里的屬性又是和配置文件綁定的

4) 所有配置文件中能配置的屬性xxxProperties類中封裝著,配置文件能配置什么就可以參照某個功能對應(yīng)的屬性類
//從配置文件spring.http中獲取指定的值和屬性進行綁定
@ConfigurationProperties( prefix = "spring.http")  
public class HttpProperties {
    private boolean logRequestDetails;
    private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();
    public HttpProperties() {
    }

5) 用好自動配置類
  • SpringBoot啟動會加載大量的自動配置類
  • 看我們需要的功能是否已由SpringBoot自動配置類寫好,配置類中如果已經(jīng)寫好了組件,我們就不用配置了。
  • 給容器中自動配置類添加組件時,會從properties獲取某些屬性,我們可以在配置文件中指定這些屬性的值。
6) @Conditional注解(補充知識)

作用:必須是@Conditional指定的條件成立,才給容器中添加組件,配置配里面的所有內(nèi)容才生效;

@Conditional擴展注解 作用(判斷是否滿足當前指定條件)
@ConditionalOnJava 系統(tǒng)的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 滿足SpEL表達式指定
@ConditionalOnClass 系統(tǒng)中有指定的類
@ConditionalOnMissingClass 系統(tǒng)中沒有指定的類
@ConditionalOnSingleCandidate 容器中只有一個指定的Bean,或者這個Bean是首選Bean
@ConditionalOnProperty 系統(tǒng)中指定的屬性是否有指定的值
@ConditionalOnResource 類路徑下是否存在指定資源文件
@ConditionalOnWebApplication 當前是web環(huán)境
@ConditionalOnNotWebApplication 當前不是web環(huán)境
@ConditionalOnJndi JNDI存在指定項

自動配置類必須在一定的條件下才能生效;
那我們怎么知道哪些自動配置類生效?可以application.properties里通過debug=true屬性,來讓控制臺打印自動配置報告。打印內(nèi)容如下:

=========================
AUTO-CONFIGURATION REPORT
=========================


Positive matches:(自動配置類啟用的)
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
        
    
Negative matches:(沒有啟動,沒有匹配成功的自動配置類)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

三、日志

1 市面上的日志框架

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

日志門面 (日志的抽象層) 日志實現(xiàn)
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j JUL(java.util.logging) Log4j2 Logback

左邊選一個門面(抽象層)、右邊來選一個實現(xiàn);
SpringBoot選用 SLF4j和logback

2 SLF4j使用
1)如何在系統(tǒng)中使用SLF4j

官網(wǎng): https://www.slf4j.org
以后開發(fā)的時候,日志記錄方法的調(diào)用,不應(yīng)該來直接調(diào)用日志的實現(xiàn)類,而是調(diào)用日志抽象層里面的方法;
給系統(tǒng)里面導(dǎo)入slf4j的jar和 logback的實現(xiàn)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");
 }
}

系統(tǒng)中使用slf4j的方法:可參考https://www.slf4j.org/manual.html


每一個日志的實現(xiàn)框架都有自己的配置文件。使用slf4j以后,配置文件還是做成日志實現(xiàn)框架自己本身的配置文件;

2)遺留問題

A(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx
如上,A系統(tǒng)使用了許多框架,且每個框架日志輸出使用的方式都不同,如何統(tǒng)一日志記錄,所有框架統(tǒng)一使用slf4j進行輸出?
解決辦法:


如何讓系統(tǒng)中所有的日志都統(tǒng)一到slf4j;
1、將系統(tǒng)中其他日志框架先排除出去;
2、用中間包來替換原有的日志框架;
3、我們導(dǎo)入slf4j其他的實現(xiàn)

3 SpringBoot日志關(guān)系
  • SpringBoot使用它來做日志功能:
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
 </dependency>
  • 底層依賴關(guān)系:

    總結(jié):
    ? 1)SpringBoot底層也是使用slf4j+logback的方式進行日志記錄
    ? 2)SpringBoot也把其他的日志都替換成了slf4j;
    ==SpringBoot能自動適配所有的日志,而且底層使用slf4j+logback的方式記錄日志,引入其他框架的時候,只需要把這個框架依賴的日志框架排除掉即可;==
    比如在SpringBoot1.x版本中引入spring時就做了這樣的處理
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
       </exclusions>
</dependency>
2 日志使用
1)默認配置

SpringBoot默認幫我們配置好了日志;

  • 日志級別
    //記錄器
    Logger logger = LoggerFactory.getLogger(getClass());
    @Test
    public void contextLoads() {
        //System.out.println();
        //日志的級別;
        //由低到高   trace<debug<info<warn<error
        //可以調(diào)整輸出的日志級別;日志就只會在這個級別以以后的高級別生效
        logger.trace("這是trace日志...");
        logger.debug("這是debug日志...");
        //SpringBoot默認給我們使用的是info級別的,沒有指定級別的就用SpringBoot默認規(guī)定的級別;root級別
        logger.info("這是info日志...");
        logger.warn("這是warn日志...");
        logger.error("這是error日志...");
    }
  • 日志輸出格式
    日志輸出格式:
        %d表示日期時間,
        %thread表示線程名,
        %-5level:級別從左顯示5個字符寬度
        %logger{50} 表示logger名字最長50個字符,否則按照句點分割。 
        %msg:日志消息,
        %n是換行符
    -->
    %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
  • SpringBoot修改日志的默認配置
logging.level.com.logging=trace

#logging.path=
# 不指定路徑在當前項目下生成springboot.log日志

# 可以指定完整的路徑;
#logging.file=G:/springboot.log

# 在當前磁盤的根路徑下創(chuàng)建spring文件夾和里面的log文件夾;使用 spring.log 作為默認文件
logging.path=/spring/log

#  在控制臺輸出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n

# 指定文件中日志輸出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
logging.file logging.path Example Description
(none) (none) 只在控制臺輸出
指定文件名 (none) my.log 輸出日志到my.log文件
(none) 指定目錄 /var/log 輸出到指定目錄的 spring.log 文件中
2)指定配置

給類路徑下放上每個日志框架自己的配置文件即可;SpringBoot就不使用他默認配置的了

Logging System Customization
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

logback.xml:直接就被日志框架識別了;

logback-spring.xml:日志框架不直接加載日志的配置項,由SpringBoot解析日志配置,可以使用SpringBoot的高級Profile功能

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
    可以指定某段配置只在某個環(huán)境下生效
</springProfile>

如:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志輸出格式:
            %d表示日期時間,
            %thread表示線程名,
            %-5level:級別從左顯示5個字符寬度
            %logger{50} 表示logger名字最長50個字符,否則按照句點分割。 
            %msg:日志消息,
            %n是換行符
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <springProfile name="dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
        </layout>
    </appender>

如果使用logback.xml作為日志配置文件,還要使用profile功能,會有以下錯誤
no applicable action for [springProfile]

5 切換日志框架

可以按照slf4j的日志適配圖,進行相關(guān)的切換;
slf4j+log4j的方式:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <artifactId>logback-classic</artifactId>
      <groupId>ch.qos.logback</groupId>
    </exclusion>
    <exclusion>
      <artifactId>log4j-to-slf4j</artifactId>
      <groupId>org.slf4j</groupId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
</dependency>

切換為log4j2

   <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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容