SpringBoot入門及深入

螞蟻小哥發表於2021-01-12

一:SpringBoot簡介

  當前網際網路後端開發中,JavaEE佔據了主導地位。對JavaEE開發,首選框架是Spring框架。在傳統的Spring開發中,需要使用大量的與業務無關的XML配置才能使Spring框架執行起來,這點備受許多開發者詬病。隨著Spring4.x釋出,Spring已經完全脫離XML,只使用註解就可以執行專案。為了進一步簡化Spring應用的開發,SpringBoot誕生了。它是由Pivotal團隊提供的全新框架,其設計目的是簡化Spring應用的搭建及開發過程,並迎合時下流行的分散式微服務設計思想,越來越多企業在使用SpringBoot

1:設計初衷

  SpringBoot為我們開發者提供了一種更快速、體驗更好的開發方式,我們可以開箱即用,無需像寫Spring那樣配置各種XML檔案,雖然Spring3.0時引入了基於java的配置,但是編寫這些配置無疑是在浪費大量時間,其實SpringBoot還內建Tomcat

2:核心功能

一:獨立的執行Spring
    SpringBoot 可以以jar包形式獨立執行,執行一個SpringBoot專案只需要通過java -jar xx.jar來執行
二:內建Servlet容器
    Spring Boot可以選擇內嵌Tomcat、jetty或者Undertow,這樣我們無須以war包形式部署專案
三:簡化Maven配置
    SpringBoot提供了一系列的start pom來簡化Maven的依賴載入,例如,當你使用了spring-boot-starter-web
四:自動裝配
    SpringBoot會根據在類路徑中的jar包,類、為jar包裡面的類自動配置Bean,這樣會極大地減少我們要使用的配置。
當然,SpringBoot只考慮大多數的開發場景,並不是所有的場景,若在實際開發中我們需要配置Bean,而SpringBoot
沒有提供支援,則可以自定義自動配置 五:準生產的應用監控 SpringBoot提供基於http ssh telnet對執行時的專案進行監控 六:無程式碼生產和xml配置 SpringBoot不是藉助與程式碼生成來實現的,而是通過條件註解來實現的,這是Spring4.x提供的新特性

Spring Boot只是Spring本身的擴充套件,使開發,測試和部署更加方便

3:本文開發環境需求

  SpringBoot 2.4.1正式發行版要求Java8並且相容Java15;對應的Spring版本是5.3.2;而且要求Maven 3.3+ 但是最好使用3.5.4穩定版本,而Servlet容器的版本為Tomcat9.0(Servlet Version 4.0)、Jetty 9.4(Servlet Version 3.1)、Undertow 2.0(Servlet Version 4.0)  

 二:SpringBoot入門搭建

1:手動搭建案例

  我們以一個簡單的SpringBoot案例來突顯出Spring的繁瑣,我接下來將使用SpringBoot來實現一個簡單的帶Controller的案例

第一步:使用IDEA構建一個普通的Maven專案
第二步:在構建好的maven工程中對pom檔案修改
第三步:編寫啟動引導類
第四步:編寫Controller
第五步:訪問(預設8080埠) 以本案例http://localhost:8080/index/test
SpringBoot入門及深入
<?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
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--
        在編寫SpringBoot的專案時我們得繼承SpringBoot的父POM檔案,
        這一點和我們以前使用Spring匯入的座標不太一樣,細心的會檢視
        繼承的父POM檔案後發現SpringBoot為我們提前匯入了大量的座標,
        這就解決了我們平常匯入座標版本衝突問題
    -->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.4.1</version>
    </parent>

    <groupId>org.example</groupId>
    <artifactId>demo0023</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--
            要編寫SpringMVC相關程式碼我們還得匯入web的starter依賴
            SpringBoot為了我們匯入的方便,把一系列的關於SpringMVC的座標打包結合到了
            這個我下面匯入的座標裡面
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
pom.xml裡面新增相應座標
SpringBoot入門及深入
package cn.xw;

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

/**
 * 啟動引導類
 */
//加上此註解代表當前類就是SpringBoot啟動類,否則就是普通類
@SpringBootApplication
public class SpringBoot5Application {
    //SpringBoot程式入口
    public static void main(String[] args) {

        //main函式裡面的args引數是一個String陣列,所以在main函式執行的
        //同時可以接收引數,接收過來的引數交給了SpringBoot,用於後期執行配置,後面介紹
        //第一個引數通過反射是告訴SpringBoot哪個是啟動引導類
        //還有這個方法有個返回值,返回IOC容器
        SpringApplication.run(SpringBoot5Application.class, args);
    }
    /**
     * 注意:此類只會掃描載入當前包及其子包裡面的全部類,然會把它們載入IOC容器中
     */
}
啟動引導類編寫
SpringBoot入門及深入
package cn.xw.controller;

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

@RestController //結合@ResponseBody 和 @Controller 兩註解
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/test")
    public String testMethod() {
        System.out.println("訪問到此方法");
        return "Hello !!";
    }
}
Controller編寫

2:使用Spring Initializr快速搭建

SpringBoot入門及深入
<?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>
    <!--SpringBoot父POM座標-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/>
    </parent>
    <groupId>cn.xw</groupId>
    <artifactId>springboot_test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_test</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--WEB開發Starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--SpringBoot的開發者工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--SpringBoot測試Starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--SpringBoot的Maven外掛-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
自動建立的Maven座標說明

三:SpringBoot基本分析

1:座標中starters分析及依賴管理

  starter是依賴關係的整理和封裝。是一套依賴座標的整合,可以讓匯入應用開發的依賴座標更方便。利用依賴傳遞的特性幫我們把一些列指定功能的座標打包成了一個starter,我們只需要匯入starter即可,無需匯入大量座標;每個Starter包含了當前功能下的許多必備依賴座標這些依賴座標是專案開發,上線和執行必須的。同時這些依賴也支援依賴傳遞。如下Starter:

<!--匯入WEB開發Starter-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
SpringBoot入門及深入
<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.4.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.4.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.4.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.2</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.2</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
spring-boot-starter-web內部封裝的一些列座標

封裝成各個Starter的好處就是讓我們更加專注於業務開發,無需關心依賴匯入,依賴衝突,及依賴的版本

問:為什麼匯入的一些Starter不需要寫版本呢?

  不指定版本是因為maven有依賴傳遞的特性,可推測starter在父級定義了並鎖定了版本;spring-boot-dependencies.xml 檔案可以給大家一個答案;繼承關係為 spring-boot-starter-parent.xml ==> spring-boot-dependencies.xml 這裡面鎖定了我們常用的座標及Stater

編寫SpringBoot專案繼承spring-boot-starter-parent的好處和特點

①:預設編譯Java 1.8
②:預設編碼UTF-8
③:通過spring-boot-denpendencies的pom管理所有公共Starter依賴的版本
④:spring-boot-denpendencies通過Maven的依賴傳遞和版本鎖定特性來實現版本管理
⑤:隨用隨取,不用繼承父類所有的starter依賴。

POM檔案中的Maven外掛功能

<build>
  <plugins>
        <!-- 作用:將一個SpringBoot的工程打包成為可執行的jar包 -->
      <plugin>
          <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
  </plugins>
</build>

補充:可選擇的啟動器官網介紹,需要則查詢這個手冊

 2:自動配置(AutoConfiguration)分析

  所有我們要配置的專案Pivotal團隊的開發人員,幫我們寫好了,怎麼實現的,主要是通過@Configuration實現 SpringBoot採用約定大於配置設計思想,將所有可能遇到的配置資訊提前配置好,寫在自動配置的jar包中。每個Starter基本都會有對應的自動配置。SpringBoot幫我們將配置資訊寫好,存放在一個jar包中:spring-boot-autoconfigure-2.4.1.jar;jar包裡,存放的都是配置類,讓配置類生效的"規則類"

接下來我來介紹一個我們常見的配置類
一:找到專案的External Libraries
二:查詢Maven:org.springframework.boot:spring-autoconfigue:2.4.1
三:內部有個spring-boot-autoconfigue-2.4.1.jar
四:點選org ==> web ==> servlet ==> ServletWebServerFactoryAutoConfiguration類

@Configuration(proxyBeanMethods = false)  //代表是個配置類 SpringBoot為我們提供的每個配置類都有此註解
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration { ... }

補充:我們回到之前點選META-INF ==> spring.factories 這裡面配置的是SpringBoot的全部配置類
補充:我們回到之前點選META-INF ==> spring-configuration-metadata.json 這裡面配置著各種配置類的資訊引數

問:SpringBoot提供這麼多配置類,難道是程式執行後就全部匯入嗎?

  不會全部匯入,只會根據當前專案的需求選擇性的裝配所需的配置類,這也是SpringBoot的自動裝配一大特性;我們也可以設想一下,一次性裝配全部配置類,那該多慢呀;

問:SpringBoot怎麼知道程式執行後就自動裝配呢?

  我們找到SpringBoot入口函式,點開 @SpringBootApplication 註解會發現裡面有個 @EnableAutoConfiguration 這個註解就是開啟自動配置的

問:開啟自動裝配後,它咋知道要載入指定配置呢?那麼多配置類呢

  我們繼續看上面的 ServletWebServerFactoryAutoConfiguration 配置類

@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
//配置類能否被自動裝配主要看 @ConditionalOnClass註解 
//此註解是否可以載入到一個叫 ServletRequest.class檔案,一旦存在則自動裝配
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
        ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
        ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
        ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration { ... }

  有了自動配置後,那麼基本全部採用預設配置(這也就是為啥說約定大於配置的思想);那麼要修改預設配置也是可以的,我們只需在配置檔案配置指定的引數即可 官方全部可配置屬性  如下常見配置:

# 埠配置
server.port=8888
# 配置context-path專案訪問根路徑
server.servlet.context-path=/demo
# 開啟debug模式,詳細日誌輸出,用於開發的一種設定 預設是false
debug=true
# 配置日誌  logging.level.{指定包下的日誌}=debug
logging.level.cn.xw=debug

 四:SpringBoot的配置檔案

  SpringBoot是約定大於配置的,配置都有預設值。如果想修改預設配置,可以使用application.properties或application.yml或application.yaml自定義配置。SpringBoot預設從Resource目錄載入自定義配置檔案。application.properties是鍵值對型別;application.yml是SpringBoot中一種新的配置檔案方式,在使用自定義配置時名稱一定要為application,因為是提前約定好的,而且三個字尾名的檔案都寫上是有個先後順序,後面可覆蓋前面

<includes>
     <include>**/application*.yml</include>
     <include>**/application*.yaml</include>
     <include>**/application*.properties</include>
</includes>
SpringBoot入門及深入
# properties型別配置檔案 application.properties
server.port=8080
server.address=127.0.0.1

<!--xml型別配置檔案 application.xml-->
<server>
    <port>8080</port>
    <address>127.0.0.1</address>
</server>

# yml/yaml型別配置檔案 application.yml/ymal
server: 
    port: 8080
    address: 127.0.0.1
三種型別檔案的配置方式

1:yml/yaml配置檔案語法及使用

   YML檔案格式是YAML(YAML Aint Markup Language)編寫的檔案格式。可以直觀被電腦識別的格式。容易閱讀,容易與指令碼語言互動。可以支援各種程式語言(C/C++、Ruby、Python、Java、Perl、C#、PHP)。以資料為核心,比XML更簡潔。副檔名為.yml或.yaml  官方網站  線上properties轉yml

1:大小寫敏感
2:資料值前邊必須有空格,作為分隔符
3:使用縮排表示層級關係
4:縮排不允許使用tab,只允許空格
5:縮排的空格數不重要,只要相同層級的元素左對齊即可
6:"#"表示註釋,從這個字元一直到行尾,都會被解析器忽略。
7:陣列和集合使用 "-" 表示陣列每個元素
SpringBoot入門及深入
# 單個值指定
name: 小周
# 單引號忽略轉義字元
message1: 'hello \n world'
# 雙引號識別轉義字元 列印時會換行
message2: "hello \n world"

# 物件方式指定 普通寫法
student:
  name: 張三
  age: 25
  address: 安徽六安
# 物件方式指定 行內寫法
teacher: { name: 李老師, age: 50, address: 上海 }

# 陣列方式 普通寫法
hobby:
  - baseball
  - basketball
  - volleyball
# 陣列方式 行內寫法
likes: [ baseball, basketball, volleyball ]

# 集合方式 map等格式
peoples:
  key1: zhangsan
  key2: anhui
  key3: xiezi
# 集合方式 map等格式 行內寫法
peoples1: { key1 : zhangsan, key2 : anhui , key3 : shanghai}
# 這上面的key~ 是具體的key名稱

######## 其它方式擴充套件
# 配置引用
bookName: 零基礎學Java
person:
  name: xiaowu
  likeBookName: ${bookName}

# 配置隨機數 其中有int 和 long兩種根據情況選擇
# 隨機字串
StringA: ${random.value}
# 隨機數
numberB: ${random.int}
# 隨機產出小於10的數
numberC: ${random.int(10)}
# 隨機產出10~100之間的數 大於10小於100
numberD: ${random.int(10,100)}
# 隨機產出一個uuid字串
uuid: ${random.uuid}
yml基本格式寫法

2:配置檔案與配置類屬性對映

(1):java配置獲取基本的配置檔案資訊.properties型別

SpringBoot入門及深入
三:配置類 jdbcConfig.java
//宣告此類為配置類
@Configuration
//匯入外部配置檔案 因為這個配置類是自定義的,不受SpringBoot幫我們管理
@PropertySource(value="classpath:application.properties")
public class JdbcConfig {

    @Value(value = "${jdbc.datasource.driver-class-name}")
    private String driver;
    @Value("${jdbc.datasource.url}")
    private String url;
    @Value("${jdbc.datasource.username}")
    private String username;
    @Value("${jdbc.datasource.password}")
    private String password;

    @Bean(value = "dataSource")
    public DataSource getDataSource() {
        System.out.println(driver);
        //建立連線池 並加入容器
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

四:Controller 通過訪問執行程式 這裡就先不寫測試類
@RestController //結合@ResponseBody 和 @Controller 兩註解
@RequestMapping("/index")
public class IndexController {

    @Autowired
    private DataSource dataSource;

    @RequestMapping("/test")
    public String testMethod() {
        System.out.println("訪問到此方法"+dataSource);
        return "Hello !!";
    }
}

//列印
訪問到此方法{
    CreateTime:"2021-01-09 15:22:49",
    ActiveCount:0,
    PoolingCount:0,
    CreateCount:0,
    DestroyCount:0,
    CloseCount:0,
    ConnectCount:0,
    Connections:[
    ]
}
基本資料獲取.properties

(2):java配置獲取基本的配置檔案資訊並注入.yml/.yaml型別

1、使用註解@Value對映
  @value註解將配置檔案的值對映到Spring管理的Bean屬性值,只能對映基本資料型別
2、使用註解@ConfigurationProperties對映
  通過註解@ConfigurationProperties(prefix=''配置檔案中的key的字首")可以將配置檔案中的配置自動與實體進行對映。
  使用@ConfigurationProperties方式必須提供Setter方法,使用@Value註解不需要Setter方法
注:使用@ConfigurationProperties要在主函式上開啟@EnableConfigurationProperties
SpringBoot入門及深入
/**
 * @author: xiaofeng
 * @date: Create in $DATE
 * @description: 學生物件
 * @version: v1.0.0
 */
@Component  //一定要保證被對映注入的是個元件
@ConfigurationProperties(prefix = "student")  //可以之間對映物件 
public class Student {
    private Integer id;                     //id
    private String name;                    //姓名
    private String address;                 //住宅
    private List<String> hobbys;            //愛好
    private Map<String, List<Integer>> score;//各科得分
    private Map<String,Teacher> teachers;    //各科老師
    //...省略get/set 這個一定要寫 我為了程式碼少沒複製
}

/**
 * @author: xiaofeng 
 * @date: Create in $DATE
 * @description: 老師物件
 * @version: v1.0.0
 */
public class Teacher {
    private String name;
    private String message;
}

//注:在新增完@ConfigurationProperties後如果沒有spring-boot-configuration-processor編譯器會彈出提示
//提示資訊:Spring Boot Configuration Annotation Processor.....
//pom.xml新增這個配置註解處理器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
//然後去主函式類上面新增@EnableConfigurationProperties 開啟配置註解處理器
POJO實體類
SpringBoot入門及深入
student:
  id: 1001
  name: 張三
  address: 安徽六安
  hobbys:
    - baseball
    - basketball
    - volleyball
  score:
    yuwen:
      - 66
      - 88
    shuxue:
      - 85
      - 99
  #簡寫 score: { "yuwen" : [58,99], "shuxue" : [88,96] }
  # 這裡通過外界傳入值 注意引號別忘了
  teachers:
    yuwenTeacher: { name: "${teacherNameA}", message: "${teacherMessageA}" }
    shuxueTecher: { name: "${teacherNameB}", message: "${teacherMessageB}" }

teacherNameA: 張老師
teacherMessageA: 教語文
teacherNameB: 李老師
teacherMessageB: 教數學
application.yml配置檔案
//通過web的方式載入程式執行
@RestController //結合@ResponseBody 和 @Controller 兩註解 @RequestMapping("/index") public class IndexController { //注入 @Autowired private Student student; @RequestMapping("/test") public String testMethod() { System.out.println(student.toString()); //Student{ // id=1001, // name='張三', // address='安徽六安', // hobbys=[baseball, basketball, volleyball], // score={yuwen=[66, 88], shuxue=[85, 99]}, // teachers={yuwenTeacher=Teacher{name='張老師', message='教語文'}, // shuxueTecher=Teacher{name='李老師', message='教數學'}}} return "Hello !!"; } }

 五:SpringBoot與其它技術整合

 1:SpringBoot整合MyBatis  建表語句

  整合Mybatis完成查詢全部

(1):使用註解方式完成整合

SpringBoot入門及深入
<?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.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.xw</groupId>
    <artifactId>demomybatiss</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demomybatiss</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web啟動器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--spring-boot啟動器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <!--工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--mysql驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--測試 這裡沒用到-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
pom.xml檔案
SpringBoot入門及深入
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123
# 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是為了防止SpringBoot報時區錯誤
# com.mysql.jdbc.Driver 這種的已經過時了,但是不代表就剔除了 可以用
resources下的application.yml配置檔案
SpringBoot入門及深入
///////////POJO
/**
 * @author: xiaofeng
 * @date: Create in $DATE
 * @description: 學生實體類
 * @version: v1.0.0
 */
public class Student implements Serializable {
    private int id;            //id
    private String name;       //姓名
    private String sex;        //性別
    private int age;           //年齡
    private double credit;      //成績/學分
    private double money;      //零花錢
    private String address;    //住址
    private String enrol;      //入學時間
    //private int fid;    //外來鍵 家庭
    //private int tid;    //外來鍵 老師
    //構造器(無參構造器必須有)/set/get/toString  你們補充一下
}

/////////// Mapper
//此註解org.apache.ibatis.annotations.Mapper 是mybatis提供的加入容器
//Mapper 可以說等於 @Component、@Repository、@Server、@Controller
@Mapper
public interface StudentMapper {
    //查詢全部
    @Select("select * from student")
    @Results(id = "studentMapper", value = {
            @Result(id = true, column = "sid", property = "id"),
            @Result(column = "sname", property = "name"),
            @Result(column = "ssex", property = "sex"),
            @Result(column = "sage", property = "age"),
            @Result(column = "scredit", property = "credit"),
            @Result(column = "smoney", property = "money"),
            @Result(column = "saddress", property = "address"),
            @Result(column = "senrol", property = "enrol")
    })
    List<Student> findAll();
}

///////////Service
/**
 * @author: xiaofeng
 * @date: Create in $DATE
 * @description: 學生業務介面
 * @version: v1.0.0
 */
public interface StudentService {
    //查詢全部
    List<Student> findAll();
}
/**
 * @author: xiaofeng
 * @date: Create in $DATE
 * @description: 學生業務實現
 * @version: v1.0.0
 */
@Service    //注入到容器
public class StudentServiceImpl implements StudentService {

    //注入物件  如果是IDEA編譯器這邊會有個紅線錯誤,不影響
    @Autowired
    private StudentMapper studentMapper;

    //查詢全部
    @Override
    public List<Student> findAll() {
        return studentMapper.findAll();
    }
}

//////////Controller
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping("/findAll")
    public List<Student> findAll() {
        System.out.println("訪問成功");
        //這裡通過json把物件寫到瀏覽器,要序列化物件
        return studentService.findAll();
    }
}
POJO、Mapper、Service、Controller檔案

注:使用http://localhost:8080/student/findAll訪問,還有就是Mapper資料夾裡面的程式碼一定要寫在主函式類當前包及其子包下,如果不在則需要在入口類新增@MapperScan或者@MapperScans註解掃描一下,這個是mybatis提供的

(2):使用Mapper.xml對映完成整合

SpringBoot入門及深入
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/demo_school?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123

# spring繼承mybatis環境
# type-aliases-package:pojo別名掃描包
# mapper-locations:載入mybatis對映檔案
mybatis:
  type-aliases-package: cn.xw.pojo
  mapper-locations: classpath:mapper/*Mapper.xml

# 加上 ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 是為了防止SpringBoot報時區錯誤
# com.mysql.jdbc.Driver 這種的已經過時了,但是不代表就剔除了 可以用
更改application.yml
SpringBoot入門及深入
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.xw.mapper.StudentMapper">
    <!--名稱欄位不一樣可以使用這個對映名稱對應-->
    <resultMap id="studentMapper" type="student">
        <id column="sid" property="id"/>
        <result column="sname" property="name"/>
        <result column="ssex" property="sex"/>
        <result column="sage" property="age"/>
        <result column="sscore" property="credit"/>
        <result column="smoney" property="money"/>
        <result column="saddress" property="address"/>
        <result column="senrol" property="enrol"/>
    </resultMap>
    <!--查詢全部學生    要使用上面的resultMap才可以-->
    <select id="findAll" resultMap="studentMapper">
        select * from student;
    </select>
</mapper>
在resources下建立mapper/StudentMapper.xml

刪除之前在Mapper使用註解的SQL語句刪除,只留方法

 2:Spring Boot 整合 Redis

  springBoot整合Redis後,以上個案例的基礎上做個查詢學生快取,如果第一次查詢則快取到redis伺服器裡,然後從redis讀取資料返回到客戶端

 <!--匯入redis啟動器-->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
SpringBoot入門及深入
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    //注入redis模板物件
    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("/findAll")
    public List<Student> findAll() {
        System.out.println("訪問成功");

        //獲取類名
        String className = studentService.getClass().getName();

        //以類名+方法名的方式作為key來查詢redis快取資料
        List<Student> studentList = (List<Student>) redisTemplate.boundValueOps(className + "findAll").get();
        //redis沒有資料 查詢資料庫放入到redis
        if (studentList == null) {
            System.out.println("從資料庫查詢資料放入到redis");
            //查詢資料庫
            studentList = studentService.findAll();
            //把查詢到的資料放入redis中 key為類名加findAll
            redisTemplate.boundValueOps(className + "findAll").set(studentList);
        } else {
            System.out.println("從redis讀取資料快取");
        }
        //這裡通過json把物件寫到瀏覽器,要序列化物件
        return studentList;
    }
}
更改StudentController

3:Spring Boot 整合定時器

     使用SpringBoot完成一個簡易的定時器,每5秒輸出一下當前的時間到控制檯;

  首先在入口函式類上面加@EnableScheduling註解,代表開啟定時器

SpringBoot入門及深入
@Component
public class TimerUtil {
    /**
     * @Scheduled 設定方法執行規則  就是定時任務設定
     * cron: 設定一個String型別的cron表示式  這個屬性和下面6個不要混用
     * fixedDelay       以一個固定的延遲時間,上個任務完成後多久執行下一個任務
     * fixedDelayString 和上面一樣字串形式傳值
     * fixedRate        以一個固定的頻率執行,不管上一個任務執行時間
     * fixedRateString  和上面一樣字串形式傳值
     * initialDelay         當專案初始化後多久觸發事務的執行
     * initialDelayString   和上面一樣字串形式傳值
     */
    //使用cron表示式
    @Scheduled(initialDelay=10000,fixedDelay = 5000)
    public void myTask(){
        System.out.println("當前時間:"+new Date());
    }
}
//注:寫在入口函式類可掃描的範圍包下
編寫定時器類

4:Spring Boot 整合Test單元測試

<!--測試啟動start-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
//@RunWith(SpringRunner.class) 在老版的SpringBoot專案需要這個
//2.2.0.RELEASE以後,springboot測試類不再需要@Runwith的註解
@SpringBootTest //註明為SpringBoot測試類 class DemomybatissApplicationTests { //注入StudentService物件 @Autowired private StudentService studentService; @Test void contextLoads() { System.out.println(studentService.findAll()); } }

5:Spring Boot 傳送HTTP請求

  要在SpringBoot內部傳送HTTP請求就得用到RestTemplate模板,它是Rest的HTTP客戶端模板工具類;對基於HTTP客戶端進行了封裝;還實現了物件與JSON的序列化與反序列化;不限定客戶端型別,目前常用的3種客戶端都支援:HttpClient、OKHttp、JDK原生URLConnection(預設方式)

SpringBoot入門及深入
@SpringBootApplication
@EnableScheduling //開啟定時器註解
public class DemomybatissApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemomybatissApplication.class, args);
    }
    //註冊RestTemplate物件放入IOC容器
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
入口函式類更改
SpringBoot入門及深入
//@RunWith(SpringRunner.class) 在老版的SpringBoot專案需要這個
@SpringBootTest //註明為SpringBoot測試類
class DemomybatissApplicationTests {
    
    //注入RestTemplate物件
    @Autowired
    private RestTemplate restTemplate;

    @Test
    void contextLoads() {
        //String.class代表以字串形式接收結果
        String forObject = restTemplate.getForObject("http://baidu.com", String.class);
        System.out.println(forObject);
        //列印
        //<html>
        //<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
        //</html>
    }
}
編寫RestTemplate傳送Http請求測試類

6:擴充套件

  SpringBoot除了上面幾個整合外還整合 MongoDB、ElasticSearch、Memcached、郵件服務:普通郵件、模板郵件、驗證碼、帶Html的郵件、RabbitMQ訊息中介軟體、Freemarker或者Thymeleaf等等

 六:SpringBoot打包部署

   啟動方式有兩種,一種是打成jar直接執行,另一種是打包成war包放到Tomcat服務下,啟動Tomcat

1:打成Jar包部署執行

  注:pom檔案裡的<packaging>jar</packaging>必須為jar,預設就是jar

/**
 * 第一步:使用IDEA工具把寫的程式碼通過maven的package打包
 * 第二步:找到打包後的target資料夾裡面,把xxx.jar包扔給測試
 * 第三步:自己測試的話使用cmd執行下面命令,前提得檢查自己的pom.xml檔案中是否有springboot的maven外掛
 * java -jar  xxxx.jar
 * 補充:在執行的時候傳遞引數 通過main函式的args接收
 * java -jar  xxxx.jar --server.port=8888
 * 補充:在執行的時候配置jvm引數,使佔用更少的記憶體
 * java -Xmx80m -Xms20m -jar xxxx.jar
 */

 2:打成War包部署執行

  注:pom檔案裡的<packaging>war</packaging>必須為jar,預設就是war

建立一個類如:ServletInitializer.java,繼承 SpringBootServletInitializer ,覆蓋 configure(),
把啟動類 Application 註冊進去。外部 Web 應用伺服器構建 Web Application Context 的時候,
會把啟動類新增進去。

//如下程式碼建立的類 除了類名和註冊的啟動類不一樣,其它是固定寫法
//WEB-INF/web.xml
public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        //DemoApplication是自己當前專案的主函式
        return builder.sources(DemoApplication.class);
    }
}

七:SpringBoot熱部署

  我們在之前每次寫完程式碼之後都要重新部署執行,這樣特別浪費時間,其實SpringBoot是支援熱部署的,但是我們得有相對應的引數配置,匯入座標

檢查當前的pom.xml必須有此配置才可以,然後正常啟動執行即可
<!--
工具 用於設定熱部署,optional必須為true--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>

當我們的程式碼寫文執行後,後期更改了程式碼無需重寫部署,只需要按CTRL+F9(Build Project),這是快速構建專案,或點選有上角的錘子;

如果還覺得麻煩,那就設定,一旦更改程式碼,IDEA失去焦點就自動構建程式碼,我們要設定一下IDEA配置

 八:SpringBoot配置檔案深入

1:多環境配置檔案

  我們在開發Spring Boot應用時,通常同一套程式會被安裝到不同環境,比如:開發dev、測試test、生產pro等。其中資料庫地址、伺服器埠等等配置都不同,如果每次打包時,都要修改配置檔案,那麼非常麻煩。profile功能就是來進行動態配置切換的。

(1):單檔案的多環境配置

SpringBoot入門及深入
# 在只有application.yml一個檔案下配置多個配置環境就需要使用 " --- " 分隔界限
# 為了規範 Dev為開發  Test為測試  Pro為生產
# 配置完以後在這裡選擇要使用的配置環境
spring:
  profiles:
    # 開啟哪個環境下的配置檔案
    active: oo
    # 引用包含哪個配置檔案
    include: global

# 開發環境配置  Dev
---
server.port: 8881
# 設定當前的配置界限為 dev開發環境
spring.profiles: dev

# 測試環境配置  Test
---
server.port: 8882
spring.profiles: test

# 生產上線環境配置  Pro
---
server.port: 80
spring.profiles: pro

# 全域性的配置供include包含使用
---
server.servlet.context-path: /littleBird
spring.profiles: global
單個application.yml配置檔案完成多環境配置  不推薦

(2):多檔案的多環境配置 

SpringBoot入門及深入
⭐:application.yml 主配置檔案(必須有)
# 為了規範 Dev為開發  Test為測試  Pro為生產
# 配置完以後在這裡選擇要使用的配置環境
spring:
  profiles:
    # 開啟哪個環境下的配置檔案
    active: dev
    # 引入包含共有配置 
    include: common

⭐:application-dev.yml/properties 開發環境配置
# 開發環境
server.port: 8881

⭐:application-test.yml/properties 測試環境配置
# 測試環境
server.port: 8882

⭐:application-pro.yml/properties 生產環境配置
# 上線環境
server.port: 80

⭐:application-common.yml/properties 公共環境配置
# 公共配置 供其包含匯入
server.servlet.context-path: /littleBird
多檔案配置多環境 推薦

(3):profile啟用方式

   在上面我介紹了使用配置檔案來指定配置環境:spring.profiles.active=xx;可是這個是有侷限性的,除了這種方式啟用還要另外2種

配置檔案:  再配置檔案中配置:spring.profiles.active=dev
虛擬機器引數:在VM options 指定:-Dspring.profiles.active=dev
命令列引數:java –jar xxx.jar --spring.profiles.active=dev
優先順序:命令列引數 > 虛擬機器引數 > 配置檔案

2:鬆散繫結

  不論配置檔案中的屬性值是短橫線、駝峰式還是下換線分隔配置方式,在注入配置時都可以通過短橫線方式取出值使用範圍:properties檔案、YAML檔案、系統屬性

SpringBoot入門及深入
⭐命名各種方式的名稱 application.yml檔案下定義方式
# 短橫線分隔
parameter1: 
  spring-boot: 
    student-name: zhangsan 
# 駝峰式
parameter2:
  springBoot:
    studentName: lisi 
# 下劃線分隔
parameter3:
  spring_boot:
    student_name: wangwu

⭐命名各種方式的名稱 application.properties檔案下定義方式
# 短橫線分隔
parameter1.spring-boot.student-name=zhangsan
# 駝峰式
parameter2.springBoot.studentName=lisi
# 下劃線分隔
parameter3.spring_boot.student_name: wangwu

⭐取出方式:使用短橫線分隔可以取出上面的任意一直格式
注:在@Value獲取上面的3種方式命名的配置只能使用短橫線分隔通配
否則配置檔案寫啥名,獲取就寫啥名,一一對應
@Value(value="${parameter1.spring-boot.student-name}")
@Value(value="${parameter2.spring-boot.student-name}")
@Value(value="${parameter3.spring-boot.student-name}")
鬆散繫結配置檔案介紹

3:配置路徑及其載入順序

4:外部配置載入順序  官方文件

  外部載入順序就是說在程式執行時載入外部的配置資訊的順序,如我們常用的命令列下指定額外資訊 java -jar  xxx.jar --server.port=8888

SpringBoot入門及深入
# 這個是2.1.11版本的springboot之前的資訊,中文的看的清楚,以具體版本為準
1:開啟 DevTools 時, ~/.spring-boot-devtools.properties
2:測試類上的 @TestPropertySource 註解
3:@SpringBootTest#properties 屬性
4:==命令?引數(--server.port=9000 )==
5:SPRING_APPLICATION_JSON 中的屬性
6:ServletConfig 初始化引數
7:ServletContext 初始化引數
8:java:comp/env 中的 JNDI 屬性
9:System.getProperties()
10:作業系統環境變數
11:random.* 涉及到的 RandomValuePropertySource
12:jar 包外部的 application-{profile}.properties 或 .yml
13:jar 包內部的 application-{profile}.properties 或 .yml
14:jar 包外部的 application.properties 或 .yml
15:jar 包內部的 application.properties 或 .yml
16:@Configuration 類上的 @PropertySource
17:SpringApplication.setDefaultProperties() 設定的預設屬性
中文介紹

 5:修改配置檔案位置及預設名稱

  我們知道配置檔案只能以application.yml/properties來定義,但是名稱不一樣是可以指定具體檔名,也可以把配置檔案放入其它位置並指定都是可以的;指定的方式我以cmd下指定引數 java -jar xxx.jar  --xxx  -xxx 方式指定,或在IDEA裡面指定-xxx引數

# 自定義配置檔名稱
--spring.config.name=myApplication
# 指定配置檔案儲存位置 或 指定配置檔案儲存位置及配置檔名稱
--spring.config.location=classpath:/myconfig/myApplication.yml
注:多個配置引數以空格隔開 --xxx -xxx

 九:SpringBoot監聽器

  我們知道JavaEE包括13門規範,其中Servlet規範包括三個技術點:Servlet、Listener、Filter;而本章介紹的是監聽器,監聽器就是監聽某個物件的狀態變化;SpringBoot中的監聽器有很多種:如下

①:CommandLineRunner 應用程式啟動完成後
②:ApplicationRunner 應用程式啟動完成後

③:ApplicationContextInitializer 程式執行初始化前
④:SpringApplicationRunListener 多功能監聽器

1:對開發者有益的監聽器

SpringBoot入門及深入
@Component  //實現CommandLineRunner介面的監聽器必須要加入IOC容器
public class MyCommandLineRunner implements CommandLineRunner {
    //注 引數args是主函式入口的args傳來的
    @Override
    public void run(String... args) throws Exception {
        System.out.println("應用程式啟動完成後 列印:CommandLineRunner");
    }
}
CommandLineRunner 監聽器使用
SpringBoot入門及深入
@Component  //實現ApplicationRunner介面的監聽器必須要加入IOC容器
public class MyApplicationRunner implements ApplicationRunner {

    //注 引數args是主函式入口的args傳來的
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("應用程式啟動完成後 列印:ApplicationRunner");
    }
}
ApplicationRunner 監聽器使用

2:對框架開發者有意義的監聽器 功能多

SpringBoot入門及深入
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("程式執行初始化前 列印:ApplicationContextInitializer");
    }
}
ApplicationContextInitializer 監聽器使用
SpringBoot入門及深入
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
    //注意:此構造方法必須要寫 不寫就給你報個錯誤
    public MySpringApplicationRunListener(SpringApplication application, String[] args) {}
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        System.out.println("應用程式開始啟動==>starting");
    }
    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        System.out.println("環境準備完成==>environmentPrepared");
    }
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("Spring容器準備完成==>contextPrepared");
    }
    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("Spring容器載入完成==>contextLoaded");
    }
    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println("應用程式啟動完成==>started");
    }
    //注:running成功與failed異常只會存在一個
    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println("應用程式開始執行==>running");
    }
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("應用程式執行時丟擲異常==>failed");
    }
}
SpringApplicationRunListener 監聽器使用
SpringBoot入門及深入
# 說明 在resources目錄下建立META-INF資料夾 並在裡面建立一個spring.factories
# 主要目的是解耦:將監聽器的配置權交給第三方廠商、外掛開發者
# 框架提供介面,實現類由你自己來寫,釋放原生API能力,增加可定製性
# META-INF/spring.factories檔案中配置介面的實現類名稱

# 配置ApplicationContextInitializer監聽器的配置
# 左邊監聽器的全路徑名稱=右邊實現此監聽器的全路徑名
org.springframework.context.ApplicationContextInitializer=cn.xw.lintener.MyApplicationContextInitializer
# 配置SpringApplicationRunListener監聽器的配置
# 左邊監聽器的全路徑名稱=右邊實現此監聽器的全路徑名
org.springframework.boot.SpringApplicationRunListener=cn.xw.lintener.MySpringApplicationRunListener
使用ApplicationContextInitializer/SpringApplicationRunListener監聽器必看 配置一些資訊才可使用

 十:自動配置實現分析

  我們在匯入spring-boot-starter-web啟動器無需其它配置就可以之間用,還有我們匯入spring-boot-starter-data-redis啟動器後可以直接使用@Autowired直接注入RedisTemplate物件,很奇怪吧,這就是SpringBoot自動配置特性,在下幾節我慢慢引入

 1:@Import註解進階

  當我們需要匯入某個類到spring容器中去,但spring恰好無法掃描到這個類,而我們又無法修改這個類(jar包形式)。我們就可以通過@import(xxx.class)是將這個類匯入到spring容器中

(1):直接匯入

//配置類  springConfig
@Configuration
@Import(value={DateConfig.class})  //直接匯入
public class SpringConfig { }

//普通類,裡面有個@Bean注入方法  DateConfig
//被任何一個配置類引用,當前自己類也變為子配置類
public class DateConfig {
    //建立時間物件放入容器
    @Bean
    public Date createDate() { return new Date(); }
}

(2):通過配置類匯入

@Configuration
public class SpringConfig {
    //建立時間物件放入容器
    @Bean
    public Date createDate() { return new Date(); }
}

@SpringBootApplication
@Import(value={SpringConfig.class}) //匯入配置類
public class LintenerDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
        //列印時間物件
        System.out.println(run.getBean(Date.class));
    }
}

(3):通過ImportSelector介面實現類匯入  高階方式

SpringBoot入門及深入
//普通類 裡面有個@Bean注入物件
public class DateConfig {
    //建立時間物件放入容器
    @Bean
    public Date createDate() { return new Date(); }
}

//建立一個類實現ImportSelector
public class MyImportSelector implements ImportSelector {
    //這個方法是返回配置類的全類名,匯入多少都行,最後通過@Import匯入
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //返回一個陣列
        return new String[]{"cn.xw.config.DateConfig"};
    }
}

@SpringBootApplication
@Import(value={MyImportSelector.class}) //匯入配置類
public class LintenerDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
        //列印時間物件
        System.out.println(run.getBean(Date.class));
    }
}
使用ImportSelector介面

 2:@Configuration註解進階

  相對這個註解大家肯定不陌生,只要是Spring註解配置類都有這玩意;其實只要新增@Configuration註解的類裡面可以衍生出各種條件註解供我們使用,前提只能在註解類下使用,它就是@Conditional條件註解,這個條件註解又衍生出各種詳細的條件註解

注:@EnableAutoConfiguration 其本質是 @Import 和 @Configuration的組合

一:class類條件
    @ConditionalOnClass == 存在指定類條件
    @ConditionalOnMissingClass == 不存在指定類條件
二:屬性條件
    @ConditionalOnProperty == 屬性條件,還可以為屬性設定預設值
三:Bean條件
    @ConditionalOnBean == 存在Bean條件
    @ConditionalOnMissingBean == 不存在Bean條件
    @ConditionalOnSingleCondidate == 只有一個Bean條件
四:資源條件
    @ConditionalResource == 資源條件
五:Web應用條件
    @ConditionalOnWebApplication == web應用程式條件
    @ConditionalOnNotWebApplication == 不是web應用程式條件
六:其他條件
    @ConditionalOneExpression == EL表示式條件
    @ConditionalOnJava == 在特定的Java版本條件

   @Configuration還有一些載入順序的方式

1:@AutoConfigureBefore==在那些自動配置之前執行
2:@AutoConfigureAfter==在那些自動配置之後執行
3:@AutoConfigureOrder==自動配置順序

 (1):@ConditionalOnClass  與 @ConditionalOnProperty 介紹

@ConditionalOnClass註解屬性介紹
    Class<?>[] value():以類的class形式的陣列
    String[] name():以類的全路徑名的字串陣列

@ConditionalOnProperty註解屬性介紹
    value 和 name:陣列,獲取對應property名稱的值,它們只能存在其中一個
    prefix:配置屬性名稱的字首,比如spring.http.encoding
    havingValue:可與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才載入配置
    matchIfMissing:缺少該配置屬性時是否可以載入。如果為true,沒有該配置屬性時也會正常載入;反之則不會生效
SpringBoot入門及深入
//學生類
public class Student {
    private String name;
    private String identity;
    //省略了get/set,
}

//老師類
public class Teacher {
    private String name;
    private String identity;
    //省略了get/set,
}


//需求,當建立Teacher加入容器時得判斷當前是否存在Student這個類
@Configuration
@ConditionalOnClass(name = "cn.xw.pojo.Student")
public class SpringConfig {
    
    //可以通過spring.myconfig.enable=true開啟 或者false 關閉容器註冊
    @Bean(value = "teacher")
    @ConditionalOnProperty(prefix = "spring.myconfig", name = "enable", havingValue ="true", matchIfMissing = true)
    public Teacher createTeacher() {
        Teacher teacher = new Teacher();
        teacher.setName("張老師");
        teacher.setIdentity("老師");
        return teacher;
    }
}

@SpringBootApplication
//匯入配置類
@Import(value={SpringConfig.class})
public class LintenerDemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(LintenerDemoApplication.class, args);
        //列印時間物件
        System.out.println(run.getBean(Teacher.class).getName());
    }
}

//application.properties
# 關閉容器註冊
spring.myconfig.enable=false
案例講解註解
SpringBoot入門及深入
//註解類
@Configuration(proxyBeanMethods = false)
//條件註解 確儲存在RedisOperations類
@ConditionalOnClass(RedisOperations.class)
//@Import 和  @ConfigurationProperties結合  RedisProperties類就是我們配置額外變數的spring.redis
@EnableConfigurationProperties(RedisProperties.class)
//匯入配置類
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

    @Bean
    //判斷不存在redisTemplate的Bean條件
    @ConditionalOnMissingBean(name = "redisTemplate")
    //判斷只有一個RedisConnectionFactory的Bean條件
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    //下面差不多
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}
RedisTemplate自動注入分析

 十一:自定義auto-Configuration及starter

   我們平常匯入是第三方mybatis-spring-boot-starter啟動器都是由第三方提供給,特點就是以mybatis開頭,那下面我們自定義starter也得是自定義名稱開頭,我們要自定義auto-Configuraction並使用必備的四個角色功能主體框架、自動配置模組、starter模組、開發者引用

1:定製自動配置必要內容
    autoconfiguration模組,包含自動配置程式碼。自定義 *-spring-boot-autoconfigure。
    starter模組。自定義 *-spring-boot-starter
2:自動配置命名方式
    官方的Starters
        spring-boot-starter-*  如:spring-boot-starter-web
    非官方的starters
        *-spring-boot-starter  如:mybatis-spring-boot-starter
3:SpringBoot起步依賴,Starter Dependencies

   接下來我要建立一個第三方模組,功能主體模組是一個圖形列印模組,根據配置檔案的不同列印出不同的圖案,還要就是一個自動配置模組和starter模組咯,最後由我來在普通的springboot應用中呼叫這個自定義的自動配置

(1):功能主體模組

SpringBoot入門及深入
⭐主體功能模組maven座標
<?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 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.tx</groupId>
    <artifactId>graphic-printing</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--設定maven使用什麼版本的jdk解析編譯-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
</project>
⭐主體功能模組具體類方法
//圖形列印物件
public class GraphicPrintingUtil {
    private Integer width = 4;
    private Integer height = 3;
    //別忘了新增get/set方法,後面會引數注入

    //列印圖形 方法
    public void graphicPrinting() {
        System.out.println(">圖形開始列印<");
        for (int i = 1; i <= height; i++) {
            for (int j = 1; j <= width; j++) {
                System.out.print(" * ");
            }
            System.out.println();
        }
    }
}
功能主體程式碼 模組名:graphic-printing

(2):自動配置模組

SpringBoot入門及深入
⭐自動配置模組maven座標
<?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 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--匯入Springboot父座標-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.4.1</version>
    </parent>
    <!--當前本專案的一些資訊-->
    <groupId>cn.tx</groupId>
    <artifactId>graphic-spring-boot-autoconfigure</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--座標-->
    <dependencies>
        <!--匯入SpringBoot的自動配置座標 因為程式碼中要寫配置註解-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!--匯入我們之前建立的主體模組graphic-printing-->
        <dependency>
            <groupId>cn.tx</groupId>
            <artifactId>graphic-printing</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
⭐自動配置模組具體類方法
## GraphicConfiguration類
@Configuration  //註解類
@Import(value = {GraphicProperties.class})  //匯入配置類
@ConditionalOnClass(GraphicPrintingUtil.class)//判斷當前專案是否存在GraphicPrintingUtil類
public class GraphicConfiguration {
    @Bean
    @ConditionalOnProperty(prefix = "graphic.printing", name = "enable", havingValue = "true", matchIfMissing = true)
    //@ConfigurationProperties(prefix = "graphic.config") 可以使用此註解直接注入 注入時值可有可無
    public GraphicPrintingUtil createGraphicPrintingUtil(GraphicProperties g) {
        //建立圖形列印物件,主體模組上的物件
        GraphicPrintingUtil printingUtil = new GraphicPrintingUtil();
        //設定寬高
        printingUtil.setHeight(g.getHeight());
        printingUtil.setWidth(g.getWidth());
        return printingUtil;
    }
}

##  GraphicProperties 配置類
//這裡報紅不管他,後面使用者匯入<artifactId>spring-boot-configuration-processor</artifactId>
@ConfigurationProperties(prefix = "graphic.config")
public class GraphicProperties {
    private Integer width;
    private Integer height;
    //別忘了寫get/set
}
自動配置程式碼 模組名:graphic-spring-boot-autoconfigure
SpringBoot入門及深入
# 註冊自定義自動配置
# 前面是固定的,後面是自定義配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.tx.config.GraphicConfiguration
在resources下建立META-INF資料夾,並在下面建立spring.factories配置

(3):stater模組

SpringBoot入門及深入
<?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 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--自己專案座標-->
    <groupId>cn.tx</groupId>
    <artifactId>graphic-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--主體功能模組-->
        <dependency>
            <groupId>cn.tx</groupId>
            <artifactId>graphic-printing</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--自動配置類autoconfigure-->
        <dependency>
            <groupId>cn.tx</groupId>
            <artifactId>graphic-spring-boot-autoconfigure</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
stater模組 模組名:graphic-spring-boot-starter

  注:此模組啥都不用,只要pom.xml檔案即可

(3):開發者引用

SpringBoot入門及深入
注:此模組和正常SpringBoot一樣,可以使用腳手架構建
⭐使用者maven座標
<?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>
    <!--springboot父座標-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/>
    </parent>
    <!--本專案的座標資訊-->
    <groupId>cn.xw</groupId>
    <artifactId>test001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test001</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--匯入我們自定義的stater啟動器-->
        <dependency>
            <groupId>cn.tx</groupId>
            <artifactId>graphic-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--一定要匯入,是為了注入配置檔案裡面的數值-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <!--maven外掛-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
⭐使用者具體類方法
@SpringBootApplication
public class Test001Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Test001Application.class, args);
        //ConfigurableApplicationContext是ClassPathXmlApplicationContext子類
        run.getBean(GraphicPrintingUtil.class).graphicPrinting();
    }
}
⭐配置檔案application.properties
graphic.printing.enable=true
graphic.config.width=10
graphic.config.height=15
開發者模組 模組名:test001

 十二:切換內建web應用伺服器

SpringBoot的web環境中預設使用tomcat作為內建伺服器,其實還提供了另外2種內建伺服器供我們選擇,我們可以很方便的進行切換。
1:Tomcat:這個是使用最廣泛但效能不太好的web應用伺服器  預設
2:Jetty:Jetty 是一個開源的servlet容器,它為基於Java的web容器,例如JSP和servlet提供執行環境。
3:Undertow: 是紅帽公司開發的一款基於 NIO 的高效能 Web 嵌入式伺服器

  Tomcat方式:Tomcat started on port(s): 8080 (http) with context path ''
  Jetty方式:Jetty started on port(s) 8080 (http/1.1) with context path '/'
  Undertow方式:Undertow started on port(s) 8080 (http)

SpringBoot入門及深入
<!--匯入web的starter啟動器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--一定要排除tomcat的starter   因為預設就是tomcat-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--匯入jetty容器依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
切換為Jetty
SpringBoot入門及深入
 <!--匯入web的starter啟動器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--一定要排除tomcat的starter   因為預設就是tomcat-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--匯入undertow容器依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
切換Undertow

 十三:SpringBoot生產級監控

  SpringBoot自帶監控功能Actuator,可以幫助實現對程式內部執行情況監控,比如監控狀況、Bean載入情況、配置屬性、日誌資訊等

 1:專案整合Actuator監控服務

  其實匯入健康服務特別簡單,任何一個SpringBoot只需要加入一個監控啟動器則可開啟監控服務,然後專案正常執行即可

<!--監控服務Actuator啟動器-->
<
dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

  儲存SpringBoot匯入監控座標後啟動程式,在程式執行的情況下訪問 http://localhost:8080/actuator 則可監控程式

 

 補充:預設只可以監控這幾項,其實可以監測很多模組

SpringBoot入門及深入
 路徑                描述                                預設開啟
/beans            顯示容器的全部的Bean,以及它們的關係        N
/env            獲取全部環境屬性                           N
/env/{name}        根據名稱獲取特定的環境屬性值                N
/health            顯示健康檢查資訊                           Y
/info            顯示設定好的應用資訊                       Y
/mappings        顯示所有的@RequestMapping資訊               N
/metrics        顯示應用的度量資訊                           N
/scheduledtasks    顯示任務排程資訊                           N
/httptrace        顯示Http Trace資訊                          N
/caches            顯示應用中的快取                           N
/conditions        顯示配置條件的匹配情況                        N
/configprops    顯示@ConfigurationProperties的資訊           N
/loggers        顯示並更新日誌配置                            N
/shutdown        關閉應用程式                               N
/threaddump        執行ThreadDump                              N
/headdump        返回HeadDump檔案,格式為HPROF               N
/prometheus        返回可供Prometheus抓取的資訊               N
監控應用endpoint

常用application.properties配置

# 暴露所有的監控點
management.endpoints.web.exposure.include=*
# 定義Actuator訪問路徑
management.endpoints.web.base-path=/act
# 開啟endpoint 關閉服務功能  訪問關閉路徑只能傳送post請求才可關閉
management.endpoint.shutdown.enabled=true

.

相關文章