Springboot核心技術(shù)學(xué)習(xí)筆記二

  • 第 5 章 SpringBoot 與 Docker
    • 5.1 Docker 簡介
    • 5.2 核心概念
    • 5.3 安裝Docker
      • 安裝linux虛擬機
      • 在linux虛擬機上安裝docker
    • 5.4 Docker常用命令&操作
        1. 鏡像操作
        1. 容器操作
        1. 安裝 MySQL 示例
  • 第 6 章 SpringBoot 與數(shù)據(jù)訪問
    • 6.1 數(shù)據(jù)源初始化與 JDBC
        1. 配置 MySQL
        1. 數(shù)據(jù)源自動配置原理
        1. 數(shù)據(jù)表自動初始化
        1. 使用 JdbcTemplate 查詢數(shù)據(jù)
        1. 數(shù)據(jù)庫自動初始化原理
    • 6.2 使用外部數(shù)據(jù)源
    • 6.3 自定義數(shù)據(jù)源原理
    • 6.4 配置 Druid 數(shù)據(jù)源
    • 6.5 整合 MyBatis
        1. 注解版
        1. Mybatis 常見配置
        1. xml 版
    • 6.6 整合 SpringData JPA
        1. Spring Data 簡介
        1. 整合 SpringData JPA
  • 第 7 章 SpringBoot 啟動配置原理
    • 7.1 啟動流程
        1. 創(chuàng)建SpringApplication對象
        1. 運行run方法
    • 7.2 事件監(jiān)聽機制
  • 第 8 章 SpringBoot 自定義 starter
    • 8.1 starter 原理
    • 8.2 自定義 starter
    1. SpringBoot 與開發(fā)熱部署
  • 進階學(xué)習(xí)
  • 待補充
  • 推薦閱讀
  • 參考文檔

第 5 章 SpringBoot 與 Docker

5.1 Docker 簡介

Docker是一個開源的應(yīng)用容器引擎,輕量級容器技術(shù)。Docker支持將軟件編譯成一個鏡像,然后在鏡像中各種軟件做好配置,將鏡像發(fā)布出去,其他使用者可以直接使用這個鏡像;運行中的這個鏡像稱為容器,容器啟動是非常快速的。
參考 我的 Docker 入門筆記

[圖片上傳失敗...(image-82059e-1606212213489)]

5.2 核心概念

  • 主機(Host):安裝了Docker程序的機器(Docker直接安裝在操作系統(tǒng)之上)
  • 客戶端(Client):連接docker主機進行操作
  • 倉庫(Registry):用來保存各種打包好的軟件鏡像
  • 鏡像(Images):軟件打包好的鏡像;放在docker倉庫中
  • 容器(Container):鏡像啟動后的實例稱為一個容器,容器是獨立運行的一個或一組應(yīng)用

使用Docker的步驟:

  1. 安裝Docker
  2. 去Docker倉庫找到這個軟件對應(yīng)的鏡像
  3. 使用Docker運行這個鏡像,這個鏡像就會生成一個Docker容器
  4. 對容器的啟動停止就是對軟件的啟動停止

5.3 安裝Docker

安裝linux虛擬機

  1. VMWare、VirtualBox(安裝)

  2. 導(dǎo)入虛擬機文件centos7-atguigu.ova

  3. 雙擊啟動linux虛擬機;使用 root/ 123456登陸

  4. 使用客戶端連接linux服務(wù)器進行命令操作

  5. 設(shè)置虛擬機網(wǎng)絡(luò);橋接網(wǎng)絡(luò)===選好網(wǎng)卡====接入網(wǎng)線;

  6. 設(shè)置好網(wǎng)絡(luò)以后使用命令重啟虛擬機的網(wǎng)絡(luò)

    service network restart
    
  7. 查看linux的ip地址

    ip addr
    
  8. 使用客戶端連接linux

在linux虛擬機上安裝docker

參考 Docker 安裝與啟動
步驟:

# 1、檢查內(nèi)核版本,必須是3.10及以上
uname -r
# 2、安裝docker
yum install docker
# 3、輸入y確認安裝
# 4、啟動docker
[root@localhost ~]# systemctl start docker
[root@localhost ~]# docker -v
Docker version 1.12.6, build 3e8e77d/1.12.6
# 5、開機啟動docker
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
# 6、停止docker
systemctl stop docker

5.4 Docker常用命令&操作

1. 鏡像操作

操作 命令 說明
檢索 docker search 關(guān)鍵字 eg:docker search redis 我們經(jīng)常去docker hub上檢索鏡像的詳細信息,如鏡像的TAG。
拉取 docker pull 鏡像名:tag :tag是可選的,tag表示標簽,多為軟件的版本,默認是latest
列表 docker images 查看所有本地鏡像
刪除 docker rmi image-id 刪除指定的本地鏡像

https://hub.docker.com/

2. 容器操作

軟件鏡像(QQ安裝程序)----運行鏡像----產(chǎn)生一個容器(正在運行的軟件,運行的QQ);

步驟:

# 1、搜索鏡像
[root@localhost ~]# docker search tomcat
# 2、拉取鏡像
[root@localhost ~]# docker pull tomcat
# 3、根據(jù)鏡像啟動容器
docker run --name mytomcat -d tomcat:latest
# 4、查看運行中的容器
docker ps  
# 5、 停止運行中的容器
docker stop  容器的id
# 6、查看所有的容器
docker ps -a
# 7、啟動容器
docker start 容器id
# 8、刪除一個容器
docker rm 容器id
# 9、啟動一個做了端口映射的tomcat
[root@localhost ~]# docker run -d -p 8888:8080 tomcat
-d:后臺運行
-p: 將主機的端口映射到容器的一個端口    主機端口:容器內(nèi)部的端口

# 10、為了演示簡單關(guān)閉了linux的防火墻
service firewalld status ;查看防火墻狀態(tài)
service firewalld stop:關(guān)閉防火墻
# 11、查看容器的日志
docker logs container-name/container-id

更多命令參考 Docker 官方文檔

3. 安裝 MySQL 示例

拉取 MySQL鏡像:

docker pull mysql:5.6

$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
mysql                 5.6                 8de95e6026c3        4 weeks ago         302MB

啟動 MySQL:

啟動 MySQL的命令比較特殊,以后遇到不熟悉的鏡像可以查看官方文檔,如 啟動MySQL 可以查看 MySQL 鏡像文檔,可以看到啟動命令中需要設(shè)置 MySQL 的初始密碼:

Start a mysql server instance
Starting a MySQL instance is simple:

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
[root@localhost ~]# docker run --name mysql01 -d mysql:5.6
42f09819908bb72dd99ae19e792e0a5d03c48638421fa64cce5f8ba0f40f5846

# 查看容器,發(fā)現(xiàn)mysql并沒有啟動成功
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                           PORTS               NAMES
42f09819908b        mysql               "docker-entrypoint.sh"   34 seconds ago      Exited (1) 33 seconds ago                            mysql01
538bde63e500        tomcat              "catalina.sh run"        About an hour ago   Exited (143) About an hour ago                       compassionate_
goldstine
c4f1ac60b3fc        tomcat              "catalina.sh run"        About an hour ago   Exited (143) About an hour ago                       lonely_fermi
81ec743a5271        tomcat              "catalina.sh run"        About an hour ago   Exited (143) About an hour ago                       sick_ramanujan


# 查看錯誤日志
[root@localhost ~]# docker logs 42f09819908b
error: database is uninitialized and password option is not specified 
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD;這個三個參數(shù)必須指定一個

# 正確的啟動,設(shè)置MySQL密碼
[root@localhost ~]# docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
b874c56bec49fb43024b3805ab51e9097da779f2f572c22c695305dedd684c5f
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b874c56bec49        mysql               "docker-entrypoint.sh"   4 seconds ago       Up 3 seconds        3306/tcp            mysql01

# 做端口映射
[root@localhost ~]# docker run -p 3306:3306 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
ad10e4bc5c6a0f61cbad43898de71d366117d120e39db651844c0e73863b9434

# 可以看到容器的端口映射 0.0.0.0:3306->3306/tcp
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
ad10e4bc5c6a        mysql               "docker-entrypoint.sh"   4 seconds ago       Up 2 seconds        0.0.0.0:3306->3306/tcp   mysql02

操作 MySQL 命令行:

啟動 MySQL 成功后,可以進入 MySQL 命令行操作 MySQL

# 啟動MySQL
> docker run --name mysql02 -p 3316:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
6a356cfef74fd3c0c81b298bb04913ed1faa2c676cd30b4c57efa220d691d6b2

# 查看mysql容器信息
> docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
6a356cfef74f        mysql:5.6           "docker-entrypoint.s…"   5 seconds ago       Up 4 seconds        0.0.0.0:3316->3306/tcp   mysql02

# 進入mysql命令行,可以看到Mysql的版本號等信息
> docker exec -it mysql02 bash
root@6a356cfef74f:/# mysql -uroot -p123456
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.48 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
# 顯示所有數(shù)據(jù)庫
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

安裝完成后,可以使用 Navicat 連接 Docker 中的 MySQL,連接端口為容器映射到主機的端口,但是發(fā)生錯誤:

Client does not support authentication protocol

經(jīng)過查找資料,發(fā)現(xiàn)是 Navicat 不支持 MySQL 8.0 的原因,于是我關(guān)閉了 MySQL:8.0 容器,重新拉取啟動了 MySQL:5.6,使用 Navicat 連接成功。

高級操作:

# 把主機的/conf/mysql文件夾掛載到 mysqldocker容器的/etc/mysql/conf.d文件夾里面
# 改mysql的配置文件就只需要把mysql配置文件放在自定義的文件夾下(/conf/mysql)
docker run --name mysql03 -v /conf/mysql:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 指定mysql的一些配置參數(shù)
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

第 6 章 SpringBoot 與數(shù)據(jù)訪問

對于數(shù)據(jù)訪問層,無論是 SQL 還是 NOSQL,Spring Boot 默認采用整合 Spring Data 的方式進行統(tǒng)一處理,添加大量自動配置,屏蔽了很多設(shè)置。引入各種 xxxTemplate,xxxRepository 來簡化我們對數(shù)據(jù)訪問層的操作。對我們來說只需要進行簡單的設(shè)置即可。我們將在數(shù)據(jù)訪問章節(jié)測試使用SQL相關(guān)、NOSQL在緩存、消息、檢索等章節(jié)測試。
– JDBC
– MyBatis
– JPA

6.1 數(shù)據(jù)源初始化與 JDBC

1. 配置 MySQL

  1. 引入 Mysql 驅(qū)動 和 jdbc-starter:

默認MySQL 驅(qū)動是 8.0

    <!--    jdbc    -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <!--    mysql 驅(qū)動,這里默認是8.0.20版本,測試兼容 MySQL5.6    -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

Mysql驅(qū)動scope設(shè)置為runtime?

  1. application.yml中配置數(shù)據(jù)源,新版驅(qū)動變?yōu)榱?com.mysql.cj.jdbc.Driver
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3316/sp-jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
  1. 單元測試 JDBC 配置
    @Autowired
    private DataSource dataSource;

    @Test
    void testJdbc() throws SQLException {
        System.out.println("數(shù)據(jù)源:" + dataSource.getClass());
        Connection connection = dataSource.getConnection();
        System.out.println("Connection: " + connection);
    }

經(jīng)過測試,說明配置 MySQL 成功,SpringBoot 2.x 默認使用 Hikari 數(shù)據(jù)源

數(shù)據(jù)源:class com.zaxxer.hikari.HikariDataSource
Connection: HikariProxyConnection@356519935 wrapping com.mysql.cj.jdbc.ConnectionImpl@18d910b3

什么是數(shù)據(jù)源?

數(shù)據(jù)源是對數(shù)據(jù)庫操作的抽象,封裝了目標源的位置信息,驗證信息和建立與關(guān)閉連接的操作。不同數(shù)據(jù)庫可以實現(xiàn)接口提供不同策略。常見數(shù)據(jù)源包括:DriverManagerDataSource(不提供連接池),C3P0,Dbcp2,Hikari等

數(shù)據(jù)源更多的屬性配置參考:DataSourceProperties

  • @ConfigurationProperties 從配置文件根據(jù)prefix讀取屬性綁定
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
    private String username;
    private String password;
    private String url;
    private String driverClassName;
    private Class<? extends DataSource> type;

}

2. 數(shù)據(jù)源自動配置原理

數(shù)據(jù)源自動配置原理: DataSourceConfiguration

  • SpringBoot 2.x 默認數(shù)據(jù)源為 hikari
  • 可以使用spring.datasource.type修改數(shù)據(jù)源類型
  • @Configuration 底層是 @Component,標注這個類會被掃描
  • @ConfigurationProperties 從配置文件根據(jù)prefix讀取屬性綁定
  • @Bean 將方法返回的對象加入到 Spring 容器,該方法只會被調(diào)用一次
  • @ConditionalOnProperty 表示配置中name=havingValue時則生效,matchIfMissing 表示沒有這項配置時也生效
DataSourceConfiguration:
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(HikariDataSource.class)
    @ConditionalOnMissingBean(DataSource.class)
    @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
            matchIfMissing = true)
    static class Hikari {

        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.hikari")
        HikariDataSource dataSource(DataSourceProperties properties) {
            HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
            if (StringUtils.hasText(properties.getName())) {
                dataSource.setPoolName(properties.getName());
            }
            return dataSource;
        }
    }

3. 數(shù)據(jù)表自動初始化

  1. 創(chuàng)建建表 SQL schema-*.sql,插入數(shù)據(jù) SQL data-*.sql,放在 /resource 目錄下
  2. 配置中加入spring.datasource.initialization-mode=always表示啟動自動建表的操作 (SpringBoot 2.x)
  3. 啟動項目就可以自動運行建表,插入數(shù)據(jù)了

注意:每次項目啟動都會執(zhí)行 SQL,即重新創(chuàng)建表和插入數(shù)據(jù)

默認建表 SQL名稱為schema-*.sql,插入數(shù)據(jù) SQL 名稱為:data-*.sql。也可以在配置application.yml 中指定建表 SQL 文件:spring.datasource.schema: - classpath:department.sql

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3316/sp-jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 2.x 開啟自動初始化數(shù)據(jù)庫
    initialization-mode: always
    # 指定自動執(zhí)行的建表SQL,List需要用 - 表示
    schema:
      - classpath:department.sql   # - 后面有空格,classpath:后無空格
      - classpath:employee.sql
    data: 
      - classpath:init-dept.sql    # 插入數(shù)據(jù)SQL

4. 使用 JdbcTemplate 查詢數(shù)據(jù)

JdbcTemplateConfiguration 會創(chuàng)建 JdbcTemplate Bean 并加入到容器,使用 @Autowired 自動裝配即可查詢數(shù)據(jù)

@RestController
public class HelloController {

    // SpringBoot自動配置了 JdbcTemplate組件,并加入到容器
    @Autowired
    JdbcTemplate jdbcTemplate;

    @GetMapping("/query")
    public Map<String, Object> getDept() {
        List<Map<String, Object>> depts = jdbcTemplate.queryForList("SELECT * FROM department");

        return depts.get(0);
    }
}

5. 數(shù)據(jù)庫自動初始化原理

數(shù)據(jù)庫自動初始化原理: DataSourceInitializerInvoker,DataSourceInitializer
- 數(shù)據(jù)源初始化完成(被創(chuàng)建)時,幫我們運行 schema-.sql 建表
- 監(jiān)聽建表完成事件,完成后執(zhí)行 data-
.sql 插入數(shù)據(jù)

DataSourceInitializerInvoker:
class DataSourceInitializerInvoker implements ApplicationListener<DataSourceSchemaCreatedEvent>, InitializingBean {

    // 數(shù)據(jù)源 DataSource Bean初始化完成后調(diào)用
    @Override
    public void afterPropertiesSet() {
        DataSourceInitializer initializer = getDataSourceInitializer();
        if (initializer != null) {
            // 獲取建表 schema-*.sql 并執(zhí)行,見下文
            boolean schemaCreated = this.dataSourceInitializer.createSchema();
            if (schemaCreated) {

                // 表已經(jīng)創(chuàng)建完成,觸發(fā)DataSourceSchemaCreatedEvent事件
                initialize(initializer);
            }
        }
    }

    // 監(jiān)聽 DataSourceSchemaCreatedEvent事件,執(zhí)行插入數(shù)據(jù)SQL
    @Override
    public void onApplicationEvent(DataSourceSchemaCreatedEvent event) {
 
        DataSourceInitializer initializer = getDataSourceInitializer();
        if (!this.initialized && initializer != null) {

            // 獲取data-*.sql 并執(zhí)行,見下文
            initializer.initSchema();
            this.initialized = true;
        }
    }

上面執(zhí)行建表SQL 與 插入數(shù)據(jù) SQL 方法內(nèi)容如下:

DataSourceInitializer:

    // 執(zhí)行建表SQL schema-*.sql
    boolean createSchema() {
        // 獲取需要執(zhí)行的建表schema-*.sql
        List<Resource> scripts = getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");
        if (!scripts.isEmpty()) {
            if (!isEnabled()) {
                logger.debug("Initialization disabled (not running DDL scripts)");
                return false;
            }
            String username = this.properties.getSchemaUsername();
            String password = this.properties.getSchemaPassword();
            // 運行sql
            runScripts(scripts, username, password);
        }
        return !scripts.isEmpty();
    }

    // 執(zhí)行插入數(shù)據(jù)SQL data-*.sql
    void initSchema() {
        // 獲取插入數(shù)據(jù)SQL data-*.sql
        List<Resource> scripts = getScripts("spring.datasource.data", this.properties.getData(), "data");
        if (!scripts.isEmpty()) {
            if (!isEnabled()) {
                logger.debug("Initialization disabled (not running data scripts)");
                return;
            }
            String username = this.properties.getDataUsername();
            String password = this.properties.getDataPassword();
            // 運行SQL
            runScripts(scripts, username, password);
        }
    }

6.2 使用外部數(shù)據(jù)源

前面提到可以使用spring.datasource.type來指定數(shù)據(jù)源,SpringBoot 支持的數(shù)據(jù)源包括

  • Hikari
  • Tomcat
  • Dbcp2

自定義數(shù)據(jù)源 Druid 步驟:

  1. 引入 Druid 依賴

     <!-- 引入自定義數(shù)據(jù)源 druid-->
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid</artifactId>
         <version>1.1.8</version>
     </dependency>
    
  2. 配置自定義數(shù)據(jù)源 application.yml

    spring:
    datasource:
        # 自定義數(shù)據(jù)源
        type: com.alibaba.druid.pool.DruidDataSource
    
  3. 測試數(shù)據(jù)源 Druid 配置

        @Test
        void testJdbc() throws SQLException {
            System.out.println("數(shù)據(jù)源:" + dataSource.getClass());
            Connection connection = dataSource.getConnection();
            System.out.println("Connection: " + connection);
        }
    

    輸出:

    數(shù)據(jù)源:class com.alibaba.druid.pool.DruidDataSource
    Connection: com.mysql.cj.jdbc.ConnectionImpl@5c080ef3
    

6.3 自定義數(shù)據(jù)源原理

SpringBoot 中自定義數(shù)據(jù)源自動配置功能,是通過配置屬性 spring.datasource.type獲取數(shù)據(jù)源的全類名,然后通過反射創(chuàng)建該類的實例對象,然后綁定數(shù)據(jù)源的相關(guān)屬性配置,最后返回實例對象,加入到 Spring 容器。源碼如下:

DataSourceConfiguration:

    @Configuration(proxyBeanMethods = false)
    // 如果容器中不存在DataSource Bean,才執(zhí)行該方法將自定義數(shù)據(jù)源Bean加入容器
    @ConditionalOnMissingBean(DataSource.class)
    @ConditionalOnProperty(name = "spring.datasource.type")
    static class Generic {

        // 將創(chuàng)建的數(shù)據(jù)源加入到容器,使用時使用 @AutoWired
        @Bean
        DataSource dataSource(DataSourceProperties properties) {
            // 使用 DataSourceBuilder 創(chuàng)建數(shù)據(jù)源,build下下文
            return properties.initializeDataSourceBuilder().build();
        }

    }

DataSourceBuilder:

    public T build() {
        // 獲取 spring.datasource.type 指定的數(shù)據(jù)源類名稱
        Class<? extends DataSource> type = getType();
        // 根據(jù)數(shù)據(jù)源類名稱,反射創(chuàng)建數(shù)據(jù)源示例
        DataSource result = BeanUtils.instantiateClass(type);
        maybeGetDriverClassName();
        // 綁定數(shù)據(jù)源的屬性配置,如url, username, password
        bind(result);
        return (T) result;
    }

這種方式無法配置自定義數(shù)據(jù)源的特有屬性,所以一般使用 《6.4 配置 Druid 數(shù)據(jù)源》 自定義配置類的方式引入外部數(shù)據(jù)源

6.4 配置 Druid 數(shù)據(jù)源

上一節(jié)中使用了外部數(shù)據(jù)源 Druid,但是不支持配置 Druid 的相關(guān)屬性,所以我們來自定義 Druid 配置類來創(chuàng)建數(shù)據(jù)源Bean DataSource 加入到 Spring 容器。

  1. 配置 Druid 相關(guān)屬性
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3316/sp-jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 2.x 開啟自動初始化數(shù)據(jù)庫
    initialization-mode: always
    # 自定義數(shù)據(jù)源
    type: com.alibaba.druid.pool.DruidDataSource
    # 自動執(zhí)行的建表SQL,默認為schema-*.sql data-*.sql
#    schema:
#      - classpath:department.sql   # - 后面有空格,classpath:后無空格
#      - classpath:employee.sql

    #  druid 數(shù)據(jù)源其他配置
    # 初始化連接個數(shù)
    initialSize: 5
    minIdle: 5
    # 連接池的最大數(shù)據(jù)庫連接數(shù)。設(shè)為0表示無限制
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #   配置監(jiān)控統(tǒng)計攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計,'wall'用于防火墻
    filters: stat,wall
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  1. 將 Druid 數(shù)據(jù)源加入 Spring 容器

將上面配置的 Druid 數(shù)據(jù)源的屬性與 DruidDataSource 進行綁定,并將其加入到 Spring 容器

  • @ConfigurationProperties 將配置文件中的相關(guān)屬性綁定到 DruidDataSource 對象
  • @Bean 將方法返回的 DataSource 對象加入到 Spring 容器,使用 @Autowired 自動裝配
  • 不會與默認的數(shù)據(jù)源 Hikari 沖突,因為 Hikari 數(shù)據(jù)源加入容器的條件是容器中沒有 DataSource Bean
  • Hikari Bean 上的注解 @ConditionalOnMissingBean(DataSource.class) 表示沒有 DataSource Bean 時才加入容器
    `
@Configuration
public class DruidConfig {

    /**
     * 讀取配置文件中的 spring.datasource 屬性綁定到DruidDataSource,返回一個 DataSource 數(shù)據(jù)源對象
     * 并將其加入容器,替換了默認的 DataSource Bean(Hikari)
     * {@link org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari.dataSource}
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druid() {
        return new DruidDataSource();
    }
}

  1. 使用 Druid 數(shù)據(jù)源

    測試 Druid 數(shù)據(jù)源的屬性配置,輸出相關(guān)屬性,與配置文件中一致,說明配置成功

        // 這里裝配的數(shù)據(jù)源已經(jīng)從默認的 Hrki 變?yōu)榱?Druid
        @Autowired
        private DataSource dataSource;
    
        @Test
        void testDruid() throws SQLException {
            System.out.println("數(shù)據(jù)源:" + dataSource.getClass());
    
            // 獲取Druid 數(shù)據(jù)源的initialSize屬性,配置文件中為5
            int initialSize = ((DruidDataSource)dataSource).getInitialSize();
            System.out.println("initialSize: " + initialSize);
    
            // 獲取Druid 數(shù)據(jù)源的maxActive屬性,配置文件中為20
            int maxActive = ((DruidDataSource)dataSource).getMaxActive();
            System.out.println("maxActive: " + maxActive);
        }
    
  2. 配置 Druid Web 監(jiān)控

    @Configuration
    public class DruidConfig {
    
        /**
         * 讀取配置文件中的 spring.datasource 屬性綁定到DruidDataSource,返回一個 DataSource 數(shù)據(jù)源對象
         * 并將其加入容器,替換了默認的 DataSource Bean(Hikari)
         * {@link org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari.dataSource}
         */
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource druid() {
            return new DruidDataSource();
        }
    
        // 配置Druid的監(jiān)控
        // 1. 注冊一個Druid管理后臺的Servlet
        @Bean
        public ServletRegistrationBean statViewServlet() {
            // 注冊Servlet到容器,處理/druid/*下的所有請求
            // 這里的 urlMappings 類似Controller,訪問時前面需要加上項目路徑 context-path
            ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
    
            Map<String, String> initParams = new HashMap<>();
            initParams.put("loginUsername", "admin");
            initParams.put("loginPassword", "admin");
            initParams.put("allow", "");     // 允許所有人訪問
            initParams.put("deny", "192.168.1.1");    // 拒絕這個IP訪問
    
            bean.setInitParameters(initParams);
            return bean;
        }
    
        // 2. 注冊一個 Web監(jiān)控的filter
        @Bean
        public FilterRegistrationBean webStatFilter() {
            FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
            bean.setFilter(new WebStatFilter());
    
            Map<String, String> initParams = new HashMap<>();
            initParams.put("exclusions", "*.js, *.css, /druid/*");
            bean.setInitParameters(initParams);
    
            bean.setUrlPatterns(Arrays.asList("/*"));
            return bean;
        }
    }
    

訪問localhost:8080/context-path/druid ,就可以查看 Druid 的 Web 監(jiān)控,可以查看數(shù)據(jù)源的配置,調(diào)用過的SQL,訪問過URI等監(jiān)控信息。

Druid 監(jiān)控控制臺

6.5 整合 MyBatis

1. 注解版

整合 Mybatis 的前提預(yù)備步驟:

  1. 已經(jīng)配置好了 MySQL驅(qū)動 和數(shù)據(jù)源
  2. 數(shù)據(jù)庫建表
  3. 創(chuàng)建了和表對應(yīng)的實體類
  4. 可以使用 JDBC 單元測試一下前三步是否準備完成

做好預(yù)備步驟后,接下來整合 SprintBoot 與 Mybatis:

  1. 引入 MyBatis-starter
        <!-- 引入 mybatis-starter,不是Spring官方出點  -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
    

[圖片上傳失敗...(image-2717e4-1606212213489)]

  1. 創(chuàng)建注解版Mapper,實現(xiàn)增刪改查 SQL
// 指定這是一個操作數(shù)據(jù)庫的mapper,將接口掃描裝配到容器中,接口名不需要與表名一致
@Mapper
public interface DepartmentMapper {

    // 注解版,直接寫sql語句,不需要xml
    @Select("select * from department where id=#{id}")
    public Department getDeptById(Integer id);

    @Delete("delete from department where id=#{id}")
    public int deleteDeptById(Integer id);

    // 標注使用自增主鍵,并且將生成的主鍵綁定到入?yún)?dept.id 屬性上
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("insert into department(departmentName) values(#{departmentName})")
    public int insertDept(Department dept);

    @Update("update dapartment set departmentName=#{departmentName} where id=#{id}")
    public int updateDept(Department dept);
}

  1. 使用 Mapper
@RestController
public class DeptController {

    @Autowired
    private DepartmentMapper departmentMapper;

    @GetMapping("/dept/{id}")
    public Department getDepartment(@PathVariable("id") Integer id) {
        return departmentMapper.getDeptById(id);
    }

    @GetMapping("/dept")
    public Department getDepartment(Department dept) {
        int i = departmentMapper.insertDept(dept);
        
        // 這里返回的dept已經(jīng)設(shè)置了自動生成的id
        return dept;
    }
}

2. Mybatis 常見配置

  1. 獲取自增主鍵:插入數(shù)據(jù)后,通常需要將數(shù)據(jù)返回,而自增主鍵一般在數(shù)據(jù)庫中生成。我們可以使用 @Options 注解,Mybatis 會自己將主鍵綁定到插入對象的屬性上,useGeneratedKeys 表示使用了自增逐漸,keyProperty 指定主鍵需要綁定的對象屬性

     @Options(useGeneratedKeys = true, keyProperty = "id")
    
  2. 掃描配置:在SpringBoot 主類上加@MappserScan 指定掃描的包,不需要每個Mapper接口上標注Mapper注解

    // 掃描指定包下的 mapper,不需要每個Mapper類上標注Mapper注解
     @MapperScan(value = "com.atguigu.springboot.mapper")
     @SpringBootApplication
     public class SpringBoot06DataMybatisApplication {
    

    @Mapper 注解針對的是一個個的接口,相當于是一個個 Mapper.xml 文件,可以將 SQL 寫到接口中,Mybatis 會生成代理類來執(zhí)行SQL,代理類會加入到Spring 容器。@ComponentScan 掃描的是所有 @Component注解,而 @MapperScan 掃描的是指定包下的所有接口。

  3. 松散綁定:查詢到的結(jié)果需要自動綁定到對象上返回,但是默認是不支持松散綁定的,如數(shù)據(jù)庫dept_name字段無法綁定到對象的 deptName屬性上,需要開啟松散綁定。

    mybatis:
     configuration:
         map-underscore-to-camel-case: true
    

    Mybatis 自動配置類為 MybatisAutoConfiguration,根據(jù)@EnableConfigurationProperties 指定的配置類找到 MybatisProperties,其屬性 configuration 擁有屬性 mapUnderscoreToCamelCase,正是用來設(shè)置松散綁定的。

  4. 自定義配置:設(shè)置 Mybatis 屬性,除了配置文件,還可以使用自定義 Mybatis 配置類,下面就使用自定義 Mybatis 配置類設(shè)置松散綁定:

    @org.springframework.context.annotation.Configuration
    public class MybatisConfig {
    
        // 這里的ConfigurationCustomizer是mybatis的自定義配置
        @Bean
        public ConfigurationCustomizer configurationCustomizer() {
            return new ConfigurationCustomizer() {
                @Override
                public void customize(Configuration configuration) {
                    // 設(shè)置松散綁定
                    configuration.setMapUnderscoreToCamelCase(true);
                }
            };
        }
    }
    
  5. 開啟 SQL 打印:

    mybatis
       configuration:
           log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 
    
    <settings>
       <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    
  6. 關(guān)閉緩存:Mybatis 中一級緩存默認開啟,查詢操作會優(yōu)先從緩存中查詢,增刪改操作會使緩存失效。
    但是在調(diào)試過程中,如果手動修改了數(shù)據(jù)庫數(shù)據(jù),Mybatis 仍會使用一級緩存中的數(shù)據(jù),導(dǎo)致需要重啟項目才能生效,所以開發(fā)過程中,建議關(guān)閉一級緩存

    <settings>
        <setting name="cacheEnabled" value="false"/>
    </settings>
    

3. xml 版

  1. 指定 Mybatis 的全局配置文件與所有 Mapper 文件的路徑
mybatis:
  config-location: classpath:mybatis/mybatis-config.xml     # mybatis全局配置文件
  mapper-locations: classpath:mybatis/mapper/*.xml          # 需要掃描的mapper文件
  1. 創(chuàng)建 Mybatis的全局配置文件

根據(jù) Mybatis 官方文檔 創(chuàng)建全局配置文件 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 設(shè)置松散綁定,下劃線轉(zhuǎn)駝峰 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>
  1. 創(chuàng)建Mapper 接口類與 xml 配置文件
public interface EmployeeMapper {
    // 查詢
    public Employee getEmpById(Integer id);

    // 插入
    public void insertEmp(Employee employee);
}
<?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接口類綁定 -->
<mapper namespace="com.atguigu.springboot.mapper.EmployeeMapper">

    <!-- id對應(yīng)Mapper方法名,resultType是返回類型 -->
    <select id="getEmpById" resultType="com.atguigu.springboot.bean.Employee">
        select * from employee where id=#{id}
    </select>

    <!--  自增ID綁定  -->
    <insert id="insertEmp"  useGeneratedKeys="true" keyProperty="id" >
        insert into employee(lastName, email, gender, d_id) values(
            #{lastName},
            #{email},
            #{gender},
            #{dId}
        )
    </insert>
</mapper>

// 補充:對于Mybatis的xml寫法還是不熟,如果以后用到了可以專門學(xué)一下MyBatis實戰(zhàn)教程 - 10小時

6.6 整合 SpringData JPA

1. Spring Data 簡介

Spring Data 是為了簡化數(shù)據(jù)訪問,提供統(tǒng)一 API 對數(shù)據(jù)訪問層進行操作,包括關(guān)系型數(shù)據(jù)庫,非關(guān)系型數(shù)據(jù)庫,Map-Reduce框架,云數(shù)據(jù)服務(wù)等,讓我們在使用多種數(shù)據(jù)訪問技術(shù)時,都使用 Spring 提供的統(tǒng)一標準,包括 增刪改查,排序,分頁等操作。

Spring Data 包含多個子項目:

  • Spring Data Commons
  • Spring Data JPA
  • Spring Data MongoDB
  • Spring Data Redis
  • Spring Data Elasticsearch

2. 整合 SpringData JPA

// 補充:這里只是復(fù)制了筆記,等學(xué)懂了JPA,再來補充理解

  1. 編寫一個實體類(bean)和數(shù)據(jù)表進行映射,并且配置好映射關(guān)系;
//使用JPA注解配置映射關(guān)系
@Entity //告訴JPA這是一個實體類(和數(shù)據(jù)表映射的類)
@Table(name = "tbl_user") //@Table來指定和哪個數(shù)據(jù)表對應(yīng);如果省略默認表名就是user;
public class User {

    @Id //這是一個主鍵
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增主鍵
    private Integer id;

    @Column(name = "last_name",length = 50) //這是和數(shù)據(jù)表對應(yīng)的一個列
    private String lastName;
    @Column //省略默認列名就是屬性名
    private String email;
  1. 編寫一個Dao接口來操作實體類對應(yīng)的數(shù)據(jù)表(Repository)
//繼承JpaRepository來完成對數(shù)據(jù)庫的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}

  1. 基本的配置JpaProperties
spring:  
 jpa:
    hibernate:
#     更新或者創(chuàng)建數(shù)據(jù)表結(jié)構(gòu)
      ddl-auto: update
#    控制臺顯示SQL
    show-sql: true

第 7 章 SpringBoot 啟動配置原理

// 補充:這一章其實并沒有聽懂,只是復(fù)制了筆記,后面進行補充吧

下面的啟動配置原理源碼解析使用的是 SpringBoot 1.5.10 版本,

幾個重要的事件回調(diào)機制

配置在META-INF/spring.factories

ApplicationContextInitializer

SpringApplicationRunListener

只需要放在ioc容器中

ApplicationRunner

CommandLineRunner

7.1 啟動流程

1. 創(chuàng)建SpringApplication對象

進入 SpringBoot 主類的主方法,是調(diào)用 run()方法,其中創(chuàng)建了 SpringApplication 對象,該類的構(gòu)造方法調(diào)用了initialize(),如下所示:

initialize(sources);
private void initialize(Object[] sources) {
    //保存主配置類,即啟動類
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判斷當前是否一個web應(yīng)用,通過查看是否存在javax.servlet.Servlet類
    this.webEnvironment = deduceWebEnvironment();
    //從類路徑下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起來
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    //從類路徑下找到ETA-INF/spring.factories配置的所有ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //從多個配置類中找到有main方法的主配置類
    this.mainApplicationClass = deduceMainApplicationClass();
}

2. 運行run方法

SpringApplication 初始化完成后,調(diào)用其run()方法:

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
    
   //獲取SpringApplicationRunListeners;從類路徑下META-INF/spring.factories
   SpringApplicationRunListeners listeners = getRunListeners(args);
    //回調(diào)所有的獲取SpringApplicationRunListener.starting()方法
   listeners.starting();
   try {
       //封裝命令行參數(shù)
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //準備環(huán)境
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
            //創(chuàng)建環(huán)境完成后回調(diào)SpringApplicationRunListener.environmentPrepared();表示環(huán)境準備完成

      // 控制臺輸出Spring Logo 
      Banner printedBanner = printBanner(environment);
       
       //創(chuàng)建ApplicationContext;決定創(chuàng)建web的ioc還是普通的ioc
      context = createApplicationContext();
       
      analyzers = new FailureAnalyzers(context);
       //準備上下文環(huán)境;將environment保存到ioc中;而且applyInitializers();
       //applyInitializers():回調(diào)之前保存的所有的ApplicationContextInitializer的initialize方法
       //回調(diào)所有的SpringApplicationRunListener的contextPrepared();
       //
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
       //prepareContext運行完成以后回調(diào)所有的SpringApplicationRunListener的contextLoaded();
       
       // 這個方法進入到了Spring中,創(chuàng)建所有 bean 對象,
       // 刷新容器;ioc容器初始化(如果是web應(yīng)用還會創(chuàng)建嵌入式的Tomcat);Spring注解版
       // 掃描,創(chuàng)建,加載所有組件的地方;(配置類,組件,自動配置)
      refreshContext(context);

       //從ioc容器中獲取所有的ApplicationRunner和CommandLineRunner進行回調(diào)
       //ApplicationRunner先回調(diào),CommandLineRunner再回調(diào)
      afterRefresh(context, applicationArguments);
       //所有的SpringApplicationRunListener回調(diào)finished方法
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
       //整個SpringBoot應(yīng)用啟動完成以后返回啟動的ioc容器;
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}
AbstractApplicationContext: spring 容器啟動初始化Bean工廠

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // 對所有Bean進行初始化后保存到beanFactory,Bean是單例
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
            catch (BeansException ex) { }
            finally {  }
        }
    }

7.2 事件監(jiān)聽機制

// 補充

第 8 章 SpringBoot 自定義 starter

8.1 starter 原理

starter:

1、這個場景需要使用到的依賴是什么?

2、如何編寫自動配置類
@Configuration          //指定這個類是一個配置類
@ConditionalOnXXX       //在指定條件成立的情況下自動配置類生效
@AutoConfigureAfter     //指定自動配置類的順序
@Bean                   //給容器中添加組件

@ConfigurationPropertie           // 指定相關(guān)xxxProperties類來綁定相關(guān)的配置
@EnableConfigurationProperties    // 讓指定的xxxProperties生效加入到容器中


參考 DataSourceAutoConfiguration,WebMvcAutoConfiguration 等自動配置類

而自動配置類要能加載,將需要啟動就加載的自動配置類,配置在META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

8.2 自定義 starter

// 補充:很簡單,但是心靜不下來,后面再補充,23分鐘的視頻 p71

9. SpringBoot 與開發(fā)熱部署

在實際開發(fā)中我們修改一個文件后想看到效果必須重啟應(yīng)用,這導(dǎo)致大量時間
被浪費,我們希望不重啟應(yīng)用的情況下,程序可以自動部署(熱部署)。有以下四
種方式可以實現(xiàn)熱部署:

  1. 模板引擎

    • 在 Spring Boot 中開發(fā)情況下禁用模板引擎的緩存 spring.thymeleaf.cache=false
    • 頁面模板改變ctrl+F9可以重新編譯當前頁面并生效
  2. Spring Loaded

    • Spring官方提供的熱部署程序,實現(xiàn)修改類文件的熱部署
    • 下載Spring Loaded(項目地址https://github.com/spring?projects/spring-loaded)
    • 添加運行時參數(shù) -javaagent:C:/springloaded-1.2.5.RELEASE.jar -noverify
  3. Spring Boot Devtools

    1. 引入依賴
      <!--    引入熱部署依賴    -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
      </dependency>
      
    2. ctrl + f9 重新構(gòu)建一次項目即可生效
  4. JRebel (推薦)

Spring Boot Devtools 熱部署的本質(zhì)還是重啟,效率很低。IDEA 中自帶插件 HotSwap,例如在修改 Controller 層的代碼后ctrl + f9能夠立即生效,但是修改 Controller 引用的其他模塊代碼,并不會立即生效,而 JRebel 能夠?qū)崿F(xiàn)動態(tài)類加載,所以推薦使用 JRebel 進行熱加載。

進階學(xué)習(xí)

  1. SpringBoot 整合教程 - 尚硅谷

    7小時,主要講了 SpringBoot 與常用技術(shù)的整合,包括 Redis,RabbitMQ,ElasticSearch,定時任務(wù),SpringSecurity,Zookeeper/dubbo,SpringCloud等,等熟悉了這些技術(shù)后再學(xué)習(xí)與 SpringBoot 整合

  2. Spring注解驅(qū)動教程 - 尚硅谷

    11 小時,學(xué)習(xí)當前這門課,許多源碼部分都涉及到了 Spring 原生注解,很多實際開發(fā)用不到的注解,在看源碼時很有用,需要查缺補漏

  3. SpringCloud 教程 - 尚硅谷

    25 小時,分布式微服務(wù)必備,必須具有 SpringBoot 基礎(chǔ)

  4. 圖解+仿寫深入解析SpringBoot源碼課 - 慕課網(wǎng)

    13小時,當前筆記中許多 SpringBoot 源碼和原理的地方?jīng)]有完全搞清楚,借助這門課搞清

  5. Spring Boot企業(yè)微信點餐系統(tǒng) - 慕課網(wǎng)

    學(xué)了SpringBoot,需要使用項目鞏固一下,否則很容易忘記,也無法檢測學(xué)習(xí)成果。這門課并不算全面,缺少密碼加密,購物車,圖片上傳等功能,參考從0開始Java電商網(wǎng)站開發(fā)

  6. SSM 教程

待補充

  1. 補充筆記中寫了// 補充的部分,這些部分大多都是重難點。包括自動配置原理,@Conditional,SpringMVC自動配置原理,嵌入式 Servlet 容器自動配置原理,SpringBoot啟動配置原理,監(jiān)聽事件機制,自定義 starter
  2. 分析SpringMVC工作流程,根據(jù)LoginController debug和3y mvc筆記,核心控制器,映射器,適配器,視圖解析器等等,非常簡單(反射調(diào)用方法,傳參)
    SpringMVC - 運行流程圖及原理分析
    https://blog.csdn.net/j080624/article/details/58041191
    https://blog.csdn.net/j080624/article/details/57411870

[圖片上傳失敗...(image-fbd23b-1606212213489)]

[圖片上傳失敗...(image-e93db3-1606212213489)]

Spring MVC工作流程圖
  1. Bean 的生命周期,Spring IOC 的初始化,參考文章Bean的生命周期 - Guide 推薦

    https://blog.csdn.net/fageweiketang/article/details/80994433
    https://mp.weixin.qq.com/s/IKrWnD_O4_L7tbhmTFG_pg
    https://mp.weixin.qq.com/s/0tWgaYxavixiDCppvOfd-w

在講解該控制器之前,首先我們要明白SpringMVC控制器一個與Struts2不同的地方:SpringMVC的控制器是單例的,Struts2的控制器是多例的!

也就是說:Struts2收集變量是定義成員變量來進行接收,而SpringMVC作為單例的,是不可能使用成員變量來進行接收的【因為會有多個用戶訪問,就會出現(xiàn)數(shù)據(jù)不合理性】!

那么SpringMVC作為單例的,他只能通過方法的參數(shù)來進行接收對應(yīng)的參數(shù)!只有方法才能保證不同的用戶對應(yīng)不同的數(shù)據(jù)!

  1. 看一下過濾器和監(jiān)聽器,搞明白CharacterEncodingFilter,HiddenHttpMethodFilter,ContextLoaderListener的原理

推薦閱讀

  1. @RequestParam注解詳解
  2. 15個經(jīng)典的Spring面試題 - Guide
  3. Spring 面試題及解析 - 程序員諸葛
  4. Spring Boot熱部署 - 慕課網(wǎng)
  5. Spring MVC中的Controller是Serlvet嗎?
  6. 關(guān)于 @EnableConfigurationProperties 注解
  7. Spring Boot啟動流程源碼詳解
  8. Spring/SpringBoot常用注解總結(jié) - Guide
  9. 15個經(jīng)典的Spring面試常見問題解析 - Guide
  10. Spring Boot 熱部署入門 - 芋道源碼

參考文檔

  1. SpringBoot 核心技術(shù) - 尚硅谷

  2. Spring 注解驅(qū)動教程 - 尚硅谷

  3. Spring 和 SpringBoot 比較

  4. SpringBoot 2.3.1 官方文檔

  5. SpringBoot 66個常用Demo - Github

  6. SpringBoot 整合示例

  7. Srping 易混淆注解對比 - Hollis

  8. thymeleaf3.0 官方文檔

  9. Docker MySQL 鏡像 官方文檔

  10. Docker 入門筆記

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容