1. 程式人生 > 程式設計 >超詳細從0開始搭建 Spring Boot 專案

超詳細從0開始搭建 Spring Boot 專案

這個專案,我是打算作為種子專案的,作為種子專案,必須的“開箱即用”,必須要包含大部分 web 開發的相關功能,後期所有的 Spring Boot 專案都是將這個專案拿來,簡單修改一下配置,就可以快速開發了。

1.0.0 建立專案

我使用的ide 是 idea

建立專案

選擇 Spring initializr ,如果點Next一直在轉圈,可能是 start.spring.io/ 在國外,訪問比較慢。可以科學上網或者,使用自定義的 start.spring.io/

主要改以下組織名稱、專案名稱和專案描述就好了

我建立專案的時候, Spring Boot 最新穩定版是 2.1.9 。要用就用最新的!!! 依賴先都不勾選,後期一項一項加

專案資料夾名稱以及存放位置

新增maven映象

新增maven映象加快依賴下載速度

<repositories>
    <repository>
        <name>華為maven倉庫</name>
        <id>huawei</id>
        <url>https://mirrors.huaweicloud.com/repository/maven/</url>
    </repository>
</repositories>

<pluginRepositories>
    <pluginRepository>
        <name>華為maven外掛倉庫</name>
        <id>huawei_plugin</id>
        <url>https://mirrors.huaweicloud.com/repository/maven/</url>
    </pluginRepository>
</pluginRepositories>
複製程式碼

pom 檔案

整體 .pom 檔案內容如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.wqlm</groupId>
    <artifactId>boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>boot</name>
    <description>Spring Boot Demo</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </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> <repositories> <repository> <name>華為maven倉庫</name> <id>huawei</id> <url>https://mirrors.huaweicloud.com/repository/maven/</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <name>華為maven外掛倉庫</name> <id>huawei_plugin</id> <url>https://mirrors.huaweicloud.com/repository/maven/</url> </pluginRepository> </pluginRepositories> </project> 複製程式碼

依賴結構圖

番外

觀察仔細的人應該發現了,spring-boot-starterspring-boot-starter-test 都沒有指定版本,那它們是怎麼確定版本的?

參考 為什麼 maven 依賴可以不指定版本

1.1.0 新增 web 模組

在 pom 檔案中新增 web 模組

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
複製程式碼

由於 spring-boot-starter-web 包含 spring-boot-starter

建議刪掉如下 spring-boot-starter 依賴,以保證依賴的乾淨整潔

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
複製程式碼

作用

引入 spring-boot-starter-web 後,我們可以

  • 編寫 web 應用
  • 不需要配置容器即可執行 web 應用
  • 對請求引數進行校驗
  • 將業務結果物件轉換成 josn 返回

依賴結構圖

從圖中我們可以看到 spring-boot-starter-web 引入了幾個關鍵的依賴

  • spring-boot-starter
  • spring-boot-starter-tomcat:spring boot 不需要 tomcat 也能啟動就是因為它
  • spring-webmvc
  • spring-web
  • spring-boot-starter-json: 有了它,就可以使用 @ResponseBody 返回 json 資料
    • jackson :spring boot 預設的 json 解析工具
  • hibernate-validator:提供引數校驗的註解,如 @Range、@Length
    • javax.validation:提供引數校驗的註解,如 @NotBlank、@NotNull、@Pattern

關於引數校驗請參考 引數校驗 Hibernate-Validator

1.2.0 整合 mysql

Spring Boot 整合 mysql 需要 JDBC 驅動mysql 驅動

引入依賴

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

<!--mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
複製程式碼

版本號可以不用填,spring boot 配置了預設的版本號。例如 spring boot 2.1.9.RELEASE 對於的 mysql-connector-java 版本為 8.0.17

配置 mysql

根據 mysql-connector-java 版本不同,配置的內容也有些許差異

# mysql-connector-java 6.0.x 以下版本配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/boot?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

複製程式碼
# mysql-connector-java 6.0.x 及以上版本配置
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/boot?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
複製程式碼

如下圖,spring boot 2.1.9.RELEASE 對應的 mysql-connector-java 版本為 8.0.17

建立示例資料庫和表

-- 建立 boot 資料庫
CREATE DATABASE
IF
	NOT EXISTS boot DEFAULT CHARSET utf8 COLLATE utf8_bin;

-- 選擇 boot 資料庫
USE boot;

-- 建立 user 表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE
IF
	EXISTS `user`;
CREATE TABLE `user` (
	`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`user_name` VARCHAR ( 255 ) COLLATE utf8_bin NOT NULL,`pasword` VARCHAR ( 255 ) COLLATE utf8_bin NOT NULL,`salt` VARCHAR ( 255 ) COLLATE utf8_bin NOT NULL,PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8 COLLATE = utf8_bin;
SET FOREIGN_KEY_CHECKS = 1;
複製程式碼

1.3.0 多環境配置

詳細參考spring profile 與 maven profile 多環境管理

spring 多環境配置

配置一個 dev 環境

建立 application-dev.properties 檔案,並將 mysql 相關配置遷移過來

使用 dev 環境

application-dev.properties 指定要使用的環境

spring.profiles.active=dev
複製程式碼

同理你也可以建立 test、prod 環境,但一般公共配置還是會放在 application.properties 中,只有非公共配置才會放在各自的環境中

maven 多環境配置

spring boot 多環境配置有兩個缺點

  1. 每次切換環境要手動修改 spring.profiles.active 的值
  2. 打包的時候,要手動刪除其它環境的配置檔案,不然其它環境的敏感資訊就都打包進去了

而 maven 的 profile 可以解決這兩個問題

第一個問題

"每次切換環境要手動修改spring.profiles.active的值"

這個問題就可以通過配置 profile 解決,在pom的根節點下新增

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <!-- activeByDefault 為 true 表示,預設啟用 id為dev 的profile-->
            <activeByDefault>true</activeByDefault>
        </activation>
        <!-- properties 裡面可以新增自定義節點,如下添加了一個env節點 -->
        <properties>
            <!-- 這個節點的值可以在maven的其他地方引用,可以簡單理解為定義了一個叫env的變數 -->
            <env>dev</env>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <env>test</env>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <env>prod</env>
        </properties>
    </profile>
</profiles>
複製程式碼

如上,定義了三套環境,其中id為dev的是預設環境,三套環境中定義了叫 env的“變數”

如果你用的是idea編輯器,新增好後,maven控制元件視窗應該會多出一個 Profiles,其中預設值就是上面配置的dev

最小化的 profiles 已經配置好了,通過勾選上圖中的Profiles,就可以快速切換 maven的 profile 環境。

現在 maven profile 可以通過 勾選上圖中的Profiles 快速切換環境

Spring Profile 還得通過 手動修改spring.profiles.active的值來切環境

現在的問題是怎樣讓 maven profile的環境與Spring Profile一一對應,達到切換maven profile環境時,Spring Profile環境也被切換了

還記得maven profile 中定義的 env "變數"嗎,現在只需要把

spring.profiles.active=dev
複製程式碼

改成

spring.profiles.active=@env@
複製程式碼

就將maven profile 與 Spring Profile 環境關聯起來了

當maven profile 將 環境切換成 test 時,在pom中定義的id為test的profile環境將被啟用,在該環境下env的值是test,maven外掛會將 @env@ 替換為 test,這樣Spring Profile的環境也隨之發生了改變。從上面可以看出,自定義的"變數"env的值還不能亂寫,要與Spring Profile的環境相對應。

總結

  • 第一步,在pom檔案中配置 profiles
  • 第二步,在application.properties配置檔案中新增 spring.profiles.active=@env@

第二個問題

打包的時候,要手動刪除其它環境的配置檔案,不然其它環境的敏感資訊就都打包進去了

解決這個問題需要在pom根節點下中配置 build 資訊

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <!--先排除application開頭的配置檔案-->
                <exclude>application*.yml</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <!--filtering 需要設定為 true,這樣在include的時候,才會把
            配置檔案中的@env@ 這個maven`變數`替換成當前環境的對應值  -->
            <filtering>true</filtering>
            <includes>
                <!--引入所需環境的配置檔案-->
                <include>application.yml</include>
                <include>application-${env}.yml</include>
            </includes>
        </resource>
    </resources>
</build>
複製程式碼
  • directory:資原始檔所在目錄
  • includes:需要包含的檔案列表
  • excludes:需要排除的檔案列表

如上,配置了兩個 <resource>,第一個先排除了src/main/resources目錄下所有 application 開頭是配置檔案,第二個在第一個的基礎上添加了所需的配置檔案。注意 application-${env}.yml,它是一個動態變化的值,隨著當前環境的改變而改變,假如當前環境是 id叫 dev的 profile,那麼env的值為 dev。

這樣配置後,maven在build時,就會根據配置先排除掉指定的配置檔案,然後根據當前環境新增所需要的配置檔案。

pom 檔案

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.wqlm</groupId>
    <artifactId>boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>boot</name>
    <description>Spring Boot Demo</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <!--maven 多環境-->
    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault> <!-- 為 true 表示,預設啟用該 profile-->
            </activation>

            <properties> <!-- properties 裡面可以新增自定義節點,如下添加了一個env節點 -->
                <env>dev</env> <!-- 這個節點的值可以在maven的其他地方引用,可以簡單理解為定義了一個叫env的變數 -->
            </properties>
        </profile>

        <profile>
            <id>test</id>
            <properties>
                <env>test</env>
            </properties>
        </profile>

        <profile>
            <id>prod</id>
            <properties>
                <env>prod</env>
            </properties>
        </profile>
    </profiles>

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

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

        <!--test-->
        <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>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <!--先排除application開頭的配置檔案-->
                    <exclude>application*.yml</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <!--filtering 需要設定為 true,這樣在include的時候,才會把配置檔案中的@env@ 這個maven`變數`替換成當前環境的對應值-->
                <filtering>true</filtering>
                <includes>
                    <!--引入所需環境的配置檔案-->
                    <include>application.yml</include>
                    <include>application-${env}.yml</include>
                </includes>
            </resource>
        </resources>
    </build>

    <repositories>
        <repository>
            <name>華為maven倉庫</name>
            <id>huawei</id>
            <url>https://mirrors.huaweicloud.com/repository/maven/</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <name>華為maven外掛倉庫</name>
            <id>huawei_plugin</id>
            <url>https://mirrors.huaweicloud.com/repository/maven/</url>
        </pluginRepository>
    </pluginRepositories>
</project>
複製程式碼

1.4.0 多模組配置

稍微大一點的專案一般都會採用多模組的形式管理專案,將一個大型專案升級成多模組專案,一般需要兩大步驟

  1. 拆分現有專案
  2. 進行 maven 多模組配置

關於如何拆分現有專案maven 多模組配置的詳細介紹請參考 Maven 多模組配置、管理

拆分現有專案

我是按照功能拆分專案的,但由於該專案本身不大,所以我簡單的拆分為 user 模組和 common 模組

在boot下建立兩個新的模組

子模組的pom

此時,父模組的pom內容也發生了改變,添加了如下三行

再來建立 common 模組,建立過程同上,我就不演示了,建立好之後,pom如下

整個專案結構如下

下一步進行遷移工作,將原先 src 目錄下面的內容遷移到對於的子模組中

這裡我放到 user 模組中,遷移過程中注意路徑和命名規範,過程就不展示了,遷移之後,結構如下。

多模組配置

多模組配置遵守以下原則

  • 公共、通用配置一定要配置在父pom中
  • 版本號由父 pom 統一管理

如下圖,藍色背景的元素都會被子專案全部繼承

由於目前,只有 user 模組用到了如下依賴項,而 common 模組不需要用到這些依賴,所以,將依賴複製到 user 模組下,後刪掉依賴

build中的配置目前也是隻有 user 模組用到,也複製到 user 模組下,後刪掉

父專案已經配置完成了,接下來配置 user 模組,如下

common 模組用到的時候在配置

多模組管理

多模組環境管理 我們在父 pom 中配置了 maven 多環境,子模組會繼承這些配置。之後,我們只需要在 maven 外掛中切換環境,所有的子模組的 maven 環境都會被切換

多模組構建管理 在 maven 外掛中,通過 boot 專案對所以子模組進行、編譯、測試、打包、清理...

1.5.0 整合 mybatis

整合 mybatis 一般需要5步

  1. 引入依賴
  2. 建立 PO 層,存放我們的資料持久化物件
  3. 建立 DAO 層,存放資料庫的增刪改查方法
  4. 建立 mapper.xml 層,對應增刪改查語句
  5. 在啟動類上配置 @MapperScan
  6. 其他。如配置 MyBatis Generator,用來幫我們生成 PO、DAO、Mapper.xml

新增依賴

在多模組專案中新增依賴要注意一下幾點

  • 不要將依賴直接新增到父 pom 中,這樣所以子模組都會繼承該依賴
  • 多個模組引用了統一個依賴,最好保證依賴的版本一致

maven dependencyManagement 可以非常方便的管理多模組的依賴

關於 maven dependencyManagement 請參考 maven 依賴版本管理

這裡我就不在解釋,直接應用了

  1. properties 定義 mybatis-spring-boot-starter 版本號的變數

    <mybatis-spring-boot-starter.version>2.1.0</mybatis-spring-boot-starter.version>
    複製程式碼

  2. 在父 pom 的根節點下,申明 mybatis 依賴

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot-starter.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    複製程式碼

  3. 在 user 模組的 pom 檔案中引入 mybatis 依賴

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>
    複製程式碼
  4. 由於 mybatis-spring-boot-starter 包含 spring-boot-starter-jdbc ,所以刪除spring-boot-starter-jdbc依賴,保證依賴的整潔

依賴結構圖

建立對應的資料夾

如圖

com.wqlm.boot

  • controller :控制層
  • po : 存放與資料庫中表相對應的java物件
  • dto : 存放資料傳輸物件,比如註冊時,註冊的資訊可以用一個 dto 物件來接收
  • dao : 存放操作資料庫的介面
  • service : 業務層
  • vo : 存放業務返回結果物件
  • qo : 封裝了查詢引數的物件

resources

  • mapper : 存放mapper.xml 檔案

配置 mybatis

mybatis 需要知道有那些類是 mapper!有兩種方式可以告訴 mybatis。

第一種

在啟動類上配置 @MapperScan

# 指定你的 mapper介面所在的 package
@MapperScan("com.wqlm.boot.user.dao")
複製程式碼

第二種 在介面上加 @Mapper 註解,如下

要我選我肯定選第一種配置方式,一勞永逸

除此之外,還要告訴 mybatis ,你的 mapper.xml 檔案在哪

# mybatis
# mapper.xml檔案的位置
mybatis.mapper-locations=classpath*:mapper/*.xml
複製程式碼

由於這裡的配置跟環境無關,所以應該配置在 application.properties

1.5.1 配置 MyBatis Generator

MyBatis Generator 是 MyBatis 提供的一個程式碼生成工具。可以幫我們生成 表對應的持久化物件(po)、操作資料庫的介面(dao)、CRUD sql的xml(mapper)。

使用方法主要分為三步

  1. 引入並配置 MyBatis Generator 外掛
  2. 配置 MyBatis Generator Config 檔案
  3. 使用 MyBatis Generator 外掛

詳細說明請參考 MyBatis Generator 超詳細配置

這裡只給出一種最終配置

引入並配置 MyBatis Generator 外掛

在user專案的pom檔案的根節點下新增如下配置

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <!--mybatis的程式碼生成器的配置檔案-->
                <configurationFile>src/main/resources/mybatis-generator-config.xml</configurationFile>
                <!--允許覆蓋生成的檔案-->
                <overwrite>true</overwrite>
                <!--將當前pom的依賴項新增到生成器的類路徑中-->
                <!--<includeCompileDependencies>true</includeCompileDependencies>-->
            </configuration>
            <dependencies>
                <!--mybatis-generator外掛的依賴包-->
                <!--<dependency>-->
                    <!--<groupId>org.mybatis.generator</groupId>-->
                    <!--<artifactId>mybatis-generator-core</artifactId>-->
                    <!--<version>1.3.7</version>-->
                <!--</dependency>-->
                <!-- mysql的JDBC驅動 -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.17</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
<build>    
複製程式碼

配置 MyBatis Generator Config 檔案

在在user專案的 resources 目錄下,建立mybatis-generator-config.xml,內容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis的程式碼生成器相關配置-->
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!-- 引入配置檔案 -->
    <properties resource="application-dev.properties"/>

    <!-- 一個資料庫一個context,context的子元素必須按照它給出的順序
        property*,plugin*,commentGenerator?,jdbcConnection,javaTypeResolver?,javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,table+
    -->
    <context id="myContext" targetRuntime="MyBatis3" defaultModelType="flat">

        <!-- 這個外掛給生成的Java模型物件增加了equals和hashCode方法 -->
        <!--<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>-->

        <!-- 註釋 -->
        <commentGenerator>
            <!-- 是否不生成註釋 -->
            <property name="suppressAllComments" value="true"/>
            <!-- 不希望生成的註釋中包含時間戳 -->
            <!--<property name="suppressDate" value="true"/>-->
            <!-- 新增 db 表中欄位的註釋,只有suppressAllComments為false時才生效-->
            <!--<property name="addRemarkComments" value="true"/>-->
        </commentGenerator>


        <!-- jdbc連線 -->
        <jdbcConnection driverClass="${spring.datasource.driverClassName}"
                        connectionURL="${spring.datasource.url}"
                        userId="${spring.datasource.username}"
                        password="${spring.datasource.password}">
            <!--高版本的 mysql-connector-java 需要設定 nullCatalogMeansCurrent=true-->
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>

        <!-- 型別轉換 -->
        <javaTypeResolver>
            <!--是否使用bigDecimal,預設falsefalse,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer
                true,把JDBC DECIMAL 和 NUMERIC 型別解析為java.math.BigDecimal-->
            <property name="forceBigDecimals" value="true"/>
            <!--預設false
                false,將所有 JDBC 的時間型別解析為 java.util.Date
                true,將 JDBC 的時間型別按如下規則解析
                    DATE	                -> java.time.LocalDate
                    TIME	                -> java.time.LocalTime
                    TIMESTAMP               -> java.time.LocalDateTime
                    TIME_WITH_TIMEZONE  	-> java.time.OffsetTime
                    TIMESTAMP_WITH_TIMEZONE	-> java.time.OffsetDateTime
                -->
            <!--<property name="useJSR310Types" value="false"/>-->
        </javaTypeResolver>

        <!-- 生成實體類地址 -->
        <javaModelGenerator targetPackage="com.wqlm.boot.user.po" targetProject="src/main/java">
            <!-- 是否讓 schema 作為包的字尾,預設為false -->
            <!--<property name="enableSubPackages" value="false"/>-->
            <!-- 是否針對string型別的欄位在set方法中進行修剪,預設false -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>


        <!-- 生成Mapper.xml檔案 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <!--<property name="enableSubPackages" value="false"/>-->
        </sqlMapGenerator>

        <!-- 生成 XxxMapper.java 介面-->
        <javaClientGenerator targetPackage="com.wqlm.boot.user.dao" targetProject="src/main/java" type="XMLMAPPER">
            <!--<property name="enableSubPackages" value="false"/>-->
        </javaClientGenerator>


        <!-- schema為資料庫名,oracle需要配置,mysql不需要配置。
             tableName為對應的資料庫表名
             domainObjectName 是要生成的實體類名(可以不指定,預設按帕斯卡命名法將表名轉換成類名)
             enableXXXByExample 預設為 true, 為 true 會生成一個對應Example幫助類,幫助你進行條件查詢,不想要可以設為false
             -->
        <table schema="" tableName="user" domainObjectName="User"
               enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
               enableUpdateByExample="false" selectByExampleQueryId="false">
            <!--是否使用實際列名,預設為false-->
            <!--<property name="useActualColumnNames" value="false" />-->
        </table>
    </context>
</generatorConfiguration>
複製程式碼

application-dev.properties 的配置

MyBatis Generator Config 引用的外部配置檔案內容如下

# mysql
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/boot?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
複製程式碼

使用 MyBatis Generator 外掛

配置好後,雙擊 maven 中的 MyBatis Generator 執行

1.5.2 整合 tk.mybatis (通用mapper)

上一節中,MyBatis Generator 為我們生成了一些常用的操作資料庫的方法。其實我們也可以通過 整合 tk.mybatis (通用mapper) 來實現,整合之後,會有更多的通用方法,並且這些通用方法是不用配置mapper.xml 的。

springboot 整合 tk.mybatis (通用mapper) 一般需要3步

  1. 引入依賴
  2. 配置 tk.mybatis 的 MyBatis Generator 外掛
  3. 啟動類上配置要掃描的 dao 路徑
  4. 配置通用 Mapper

tk.mybatis 的 GitHub

引入依賴

老規矩,還是在父 pom 中配置 tk.mybatis 的版本並申明 tk.mybatis 的依賴

<properties>
    <tk.mybatis.mapper-spring-boot-starter.version>2.1.5</tk.mybatis.mapper-spring-boot-starter.version>
</properties>

<!--申明依賴-->
<dependencyManagement>
    <dependencies>
        <!--tk.mybatis 通用mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>${tk.mybatis.mapper-spring-boot-starter.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
複製程式碼

然後在 user 模組的 pom 中引入依賴

<dependencies>
    <!--tk.mybatis 通用mapper-->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
    </dependency>
</dependencies>
複製程式碼

配置 tk.mybatis 的 MyBatis Generator 外掛

tk.mybatis 為 MyBatis Generator 開發了一個外掛,用於改變 MyBatis Generator 的原始生成策略,配置好之後,生成出來的檔案更加精練、註釋更加有意義。

整個配置過程分兩步

  1. 引入外掛依賴
  2. 修改 MyBatis Generator Config

引入外掛依賴

在原來的 MyBatis Generator 外掛的 dependencies 裡面新增如下依賴

<!--4.15 是目前最新的版本-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>4.1.5</version>
</dependency>
複製程式碼

修改 MyBatis Generator Config

主要有一下幾點改動

首先是 targetRuntime 的值改為 MyBatis3SimpledefaultModelType 設定為 flat

如果 targetRuntime="MyBatis3" 的話,生成出來的 mapper.xml 會多出一段無用程式碼,如下

然後新增 tk.mybatis 外掛

<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
    <!--dao 要繼承的介面-->
    <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
    <!--是否區分大小寫,預設false-->
    <property name="caseSensitive" value="true"/>
</plugin>
複製程式碼

其他地方都不需要改動,配置好之後,執行 MyBatis Generator 外掛,生成出來的檔案如下

po

可以看到,相比與 MyBatis Generator 生成的註釋,tk.mybatis 生成的註解跟簡潔易懂。除此之外,它還多了幾個註解

  • @Table(name = "user"):意思是該po對應資料庫的user表
  • @Id:表示該屬性對應user表的主鍵
  • @Column(name = "user_name"):表示該屬性對應user表的 user_name 欄位

dao

相比於 MyBatis Generator 生成的程式碼,少了很多介面,但多繼承了一個類,這個類就是你在 tk.mybatis 外掛裡面配置的類
你可能猜到了,少的那些介面,都在繼承的這個tk.mybatis.mapper.common.Mapper類中有,如下圖,userMapper 繼承了這麼多方法,而且這些方法都是可以直接使用的

mapper.xml

相比於 MyBatis Generator 少了很多程式碼

啟動類上配置要掃描的 dao 路徑

這一步我們在整合 mybatis 時已經配置過了

但是整合 tk.mybatis 後,需要使用 tk.mybatis 包下的 @MapperScan,因此需要修改一下 @MapperScan 的包路徑

import tk.mybatis.spring.annotation.MapperScan;
複製程式碼

配置通用 Mapper

# 通用 mapper
# 主鍵自增回寫方法,預設值MYSQL
mapper.identity=MYSQL
# 設定 insert 和 update 中,字串型別!=""才插入/更新,預設false
#mapper.not-empty=true
複製程式碼

tk.mybatis 至此就全部整合完了

1.5.3 整合 pagehelper 分頁外掛

分頁查詢是web開發中一個很常見的功能,mybatis 雖然也可以實現分頁,但那是基於記憶體的分頁,即把資料一次性全查出來,然後放在記憶體中分多次返回。

而 pagehelper 分頁外掛是物理分頁,是通過 sql 關鍵字來實現的。例如mysql中的limit,oracle中的rownum等。

pagehelper 分頁外掛和 tk.mybatis 是通一個作者寫的pagehelper專案地址

整合 pagehelper 需要兩步

  • 引入 pagehelper 依賴
  • 配置 pagehelper

引入 pagehelper 依賴

老規矩,父pom中定義依賴版本,並申明依賴

<properties>
    <pagehelper-spring-boot-starter.version>1.2.12</pagehelper-spring-boot-starter.version>
</properties>
複製程式碼
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper-spring-boot-starter.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
複製程式碼

子模組中引入依賴

<dependencies>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
    </dependency>
</dependencies>
複製程式碼

配置 pagehelper

# 使用的sql方言
pagehelper.helperDialect=mysql
# 是否啟用合理化,預設false,啟用合理化時,如果 pageNum<1會查詢第一頁,如果pageNum>pages會查詢最後一頁
pagehelper.reasonable=true
# 是否支援通過Mapper介面引數來傳遞分頁引數,預設false
#pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
複製程式碼

更多配置請參考官網

1.6.0 引入 lombok 外掛

lombok 是一個簡化程式碼的外掛,能通過一個註解幫你生成 get、set、tostring、hash... 方法。

整合 lombok 十分簡單

  1. 引入 lombok 依賴
  2. 安裝 ide 對應的 lombok 外掛

lombok 使用方法參考這篇文章 lombok 外掛

引入 lombok 依賴

由於 spring-boot-starter-parent 中已經申明瞭lombok 依賴,我們只需要在子模組中引入就好了

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
複製程式碼

安裝 ide 對應的 lombok 外掛

我用的是 idea ,所以以idea為例

1.7.0 整合 redis

作為最常用的 nosql 資料庫,Spring Boot 對 redis 做了非常好對支援,整合起來也很簡單,只需要4步

  1. 引入依賴
  2. 配置 redis
  3. 自定義 RedisTemplate (推薦)
  4. 自定義 redis 操作類 (推薦)

詳細的整合步驟我單獨提出來寫了篇文章,地址如下

Spring Boot 2.0 整合 redis

1.7.1 整合 spring cache

Spring Cache 是 Spring 為快取場景提供的一套解決方案。通過使用 @CachePut、@CacheEvict、@Cacheable等註解實現對快取的,儲存、查詢、刪除等操作

由於我們已經引入 redis ,所以只需要簡單配置一下,就可以使用 spring cache

詳細的整合步驟我單獨提出來寫了篇文章,地址如下(在 Spring Cache 那一節)

Spring Boot 2.0 整合 redis

當然,不用也可以選擇不去整合

1.8.0 開發使用者模組

不同的系統對應不同的使用者設計,掘金的使用者系統和淘寶的使用者系統肯定是不一樣的,所以,該專案雖然是一個種子專案,但很難給出通用的使用者模組設計。

因此,我轉變思路,並不去追求什麼通用的使用者模組,而是力求在該模組中,將上面整合的技術,全部都應用起來。

這樣,在以後使用到上面的某項技術的時候,也有一個參照。

使用者表

建表語句在 配置 mysql 那一章

新增 controller 、service 、dto

先建立 controller 、service 、dto 目錄

先從註冊介面開始寫

注意校驗引數一定要加 @Valid 註解

其中 @Data 用到了 lombok 外掛

資料庫存的是密碼加鹽後的hash,也就是說就連我們自己也看不到使用者的密碼

1.8.1 自定義全域性狀態碼和業務結果類

雖然向上面這樣直接返回 註冊成功註冊失敗 也沒有什麼問題,但卻不太優雅,因為其他介面返回的可能不是簡單的字串。

我們其實可以自定義一個業務結果類,所以的介面,都返回該業務結果物件,這個業務結果類,除了有業務結果外,還有業務執行狀態、業務訊息等。

除了業務結果類,我還建議建立全域性狀態碼類,就想螞蟻金服的api介面一樣,呼叫失敗會返回一個狀態碼,方便錯誤排查

自定義全域性狀態碼

新建 enums 目錄

建立 ApplicationEnum 全域性狀態碼類,我這裡只寫了幾個,之後可以往裡面加

建立業務結果類

如下,在 vo 目錄下下建立 result 目錄,並在裡面建立業務結果類

為了方便使用,再建立一個 SuccessResult 和一個 FailResult

改造註冊介面

1.8.2 統一異常處理

業務執行過程中會產生的各種異常,對其進行統一處理是所有web專案的通用需求。Spring 提供了 @RestControllerAdvice、@ExceptionHandler 註解來幫助我們處理異常。

具體的異常處理該如何設計沒有統一的標準,下面是我給出的設計,僅供參考。

我的做法是自定義一個異常類,然後在業務出錯時丟擲,最後在自定義異常處理類中處理。

更多內容請參考 基於spring 的統一異常處理

自定義異常類

每一種異常都對於一種ApplicationEnum

自定義異常處理類

如果一個異常能匹配多個 @ExceptionHandler 時,選擇匹配深度最小的Exception(即最匹配的Exception)

使用自定義異常