005.Spring Boot

特別說明: 本人平時混跡于 B 站,不咋回復這里的評論,有問題可以到 B 站視頻評論區(qū)留言找我
視頻地址: https://space.bilibili.com/31137138/favlist?fid=326428938
課件說明: 本次提供的課件是 Spring Cloud Netflix 版微服務架構指南,如果有興趣想要學習 Spring Cloud Alibaba 版,可以前往 http://www.qfdmy.com 查看相關課程資源
案例代碼: https://github.com/topsale/hello-spring-cloud-netflix

概述

Spring Boot 可以稱之為 新一代 JavaEE 開發(fā)標準;隨著動態(tài)語言的流行 (Ruby、Groovy、Scala、Node.js),Java 的開發(fā)顯得格外的笨重:繁多的配置、低下的開發(fā)效率、復雜的部署流程以及第三方技術集成難度大。

在上述環(huán)境下,Spring Boot 應運而生。它使用 “習慣優(yōu)于配置” (項目中存在大量的配置,此外還內置了一個習慣性的配置,讓你無需手動進行配置)的理念讓你的項目快速的運行起來。使用 Spring Boot 很容易創(chuàng)建一個獨立運行(運行 Jar,內嵌 Servlet 容器)準生產級別的基于 Spring 框架的項目,使用 Spring Boot 你可以不用或者只需很少的 Spring 配置。

Spring 簡史

Spring 1.x 時代

在 Spring1.x 時代,都是通過 xml 文件配置 bean,隨著項目的不斷擴大,需要將 xml 配置分放到不同的配置文件中,需要頻繁的在 java 類和 xml 配置文件中切換。

Spring 2.x 時代

隨著 JDK 1.5 帶來的注解支持,Spring2.x 可以使用注解對 Bean 進行申明和注入,大大的減少了 xml 配置文件,同時也大大簡化了項目的開發(fā)。

那么,問題來了,究竟是應該使用 xml 還是注解呢?

最佳實踐:

  • 應用的基本配置用 xml,比如:數據源、資源文件等
  • 業(yè)務開發(fā)用注解,比如:Service 中注入 bean 等

Spring 3.x 時代

從 Spring3.x 開始提供了 Java 配置方式,使用 Java 配置方式可以更好的理解你配置的 Bean,現(xiàn)在我們就處于這個時代,并且 Spring4.x 和 Spring boot 都推薦使用 java 配置的方式。

Spring 5.x 時代

Spring5.x 是 Java 界首個支持響應式的 Web 框架,是 Spring 的一個重要版本,距離 Spring4.x 差不多四年。在此期間,大多數增強都是在 Spring Boot 項目中完成的,其最大的亮點就是提供了完整的端到端響應式編程的支持(新增 Spring WebFlux 模塊)。

Spring WebFlux 同時支持使用舊的 Spring MVC 注解聲明 Reactive Controller。和傳統(tǒng)的 MVC Controller 不同,Reactive Controller 操作的是 非阻塞ServerHttpRequestServerHttpResponse,而不再是 Spring MVC 里的 HttpServletRequest 和 HttpServletResponse。

至此也代表著 Java 正式迎來了響應式異步編程的時代。

優(yōu)缺點

優(yōu)點

  • 快速構建項目
  • 對主流開發(fā)框架的無配置集成
  • 項目可獨立運行,無需外部依賴 Servlet 容器
  • 提供運行時的應用監(jiān)控
  • 極大地提高了開發(fā)、部署效率
  • 與云計算的天然集成

缺點

  • 版本迭代速度很快,一些模塊改動很大
  • 由于不用自己做配置,報錯時很難定位

第一個 Spring Boot 應用程序

創(chuàng)建項目

這里我們使用 Intellij IDEA 來新建一個 Spring Boot 項目

Spring 初始化器

Lusifer1527230830.png

填寫項目信息

Lusifer1527231009.png

選擇版本和依賴

Lusifer1527231053.png

保存項目到指定目錄

Lusifer1527231065.png

工程目錄結構

創(chuàng)建完成后的工程目錄結構如下:

│  .gitignore
│  pom.xml
│
│
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─funtl
    │  │          └─hello
    │  │              └─spring
    │  │                  └─boot
    │  │                          HelloSpringBootApplication.java
    │  │
    │  └─resources
    │      │  application.properties
    │      │
    │      ├─static
    │      └─templates
    └─test
        └─java
            └─com
                └─funtl
                    └─hello
                        └─spring
                            └─boot
                                    HelloSpringBootApplicationTests.java
  • .gitignore:Git 過濾配置文件
  • pom.xml:Maven 的依賴管理配置文件
  • HelloSpringBootApplication.java:程序入口
  • resources:資源文件目錄
    • static: 靜態(tài)資源文件目錄
    • templates:模板資源文件目錄
    • application.properties:Spring Boot 的配置文件,實際開發(fā)中會替換成 YAML 語言配置(application.yml)

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 http://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.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.funtl</groupId>
    <artifactId>hello-spring-boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-spring-boot</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-web</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>
                <configuration>
                    <mainClass>com.funtl.hello.spring.boot.HelloSpringBootApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • parent:繼承了 Spring Boot 的 Parent,表示我們是一個 Spring Boot 工程
  • spring-boot-starter-web:包含了 spring-boot-starter 還自動幫我們開啟了 Web 支持

功能演示

我們創(chuàng)建一個 Controller 來演示一下 Spring Boot 的神奇功能

package com.funtl.hello.spring.boot.controller;

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

@RestController
public class HelloController {
    @GetMapping(value = "/")
    public String sayHi() {
        return "Hello Spring Boot.";
    }
}

啟動 HelloSpringBootApplicationmain() 方法,瀏覽器訪問 http://localhost:8080 可以看到:

Hello Spring Boot.

神奇之處

  • 沒有配置 web.xml
  • 沒有配置 application.xml,Spring Boot 幫你配置了
  • 沒有配置 application-mvc.xml,Spring Boot 幫你配置了
  • 沒有配置 Tomcat,Spring Boot 內嵌了 Tomcat 容器

Spring Boot 單元測試

主要是通過 @RunWith@SpringBootTest 注解來開啟單元測試功能

package com.funtl.hello.spring.boot;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.net.URL;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HelloSpringBootApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloSpringBootApplicationTests {

    @LocalServerPort
    private int port;

    private URL base;

    @Autowired
    private TestRestTemplate template;

    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/");
    }

    @Test
    public void contextLoads() {
        ResponseEntity<String> response = template.getForEntity(base.toString(), String.class);
        assertThat(response.getBody(), equalTo("Hello Spring Boot"));
    }

}

運行它會先啟動 Spring Boot 工程,再啟動單元測試

Spring Boot 常用配置

自定義 Banner

在 Spring Boot 啟動的時候會有一個默認的啟動圖案

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

我們在 src/main/resources 目錄下新建一個 banner.txt

通過 http://patorjk.com/software/taag 網站生成字符串,將網站生成的字符復制到 banner.txt 中

再次運行這個程序

${AnsiColor.BRIGHT_RED}
////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//            佛祖保佑       永不宕機     永無BUG                  //
////////////////////////////////////////////////////////////////////

常用屬性設置:

  • ${AnsiColor.BRIGHT_RED}:設置控制臺中輸出內容的顏色
  • ${application.version}:用來獲取 MANIFEST.MF 文件中的版本號
  • ${application.formatted-version}:格式化后的 ${application.version} 版本信息
  • ${spring-boot.version}:Spring Boot 的版本號
  • ${spring-boot.formatted-version}:格式化后的 ${spring-boot.version} 版本信息

配置文件

Spring Boot 項目使用一個全局的配置文件 application.properties 或者是 application.yml,在 resources 目錄下或者類路徑下的 /config 下,一般我們放到 resources 下。

修改 Tomcat 的端口為 9090,并將默認的訪問路徑 "/" 修改為 "boot",可以在 application.properties 中添加:

server.port=9090
server.context-path=/boot

或在 application.yml 中添加:

server:
  port: 9090
  context-path: /boot

測試效果:

Lusifer1509896204.png

更多配置

Starter POM

Spring Boot 為我們提供了簡化企業(yè)級開發(fā)絕大多數場景的 starter pom ,只要使用了應用場景所需要的 starter pom ,相關的技術配置將會消除,就可以得到 Spring Boot 為我們提供的自動配置的 Bean。

更多 Starter POM

日志配置

Spring Boot 對各種日志框架都做了支持,我們可以通過配置來修改默認的日志的配置

默認情況下,Spring Boot 使用 Logback 作為日志框架

logging:
  file: ../logs/spring-boot-hello.log
  level.org.springframework.web: DEBUG

關閉特定的自動配置

關閉特定的自動配置使用 @SpringBootApplication 注解的 exclude 參數即可,這里以關閉數據源的自動配置為例

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

Spring Boot 整合 HikariCP

什么是 HikariCP

HiKariCP 是數據庫連接池的一個后起之秀,號稱性能最好,可以完美地 PK 掉其他連接池。是一個高性能的 JDBC 連接池,基于 BoneCP 做了不少的改進和優(yōu)化。超快,快到連 Spring Boot 2 都宣布支持了。

官方 GitHub 地址

什么是 BoneCP

傳說中 BoneCP 在快速這個特點上做到了極致,官方數據是 C3P0 等的 25 倍左右,以下為性能測試報告。

單線程

  • 1,000,000 獲取連接/釋放連接請求
  • 獲取/釋放連接之間沒有延遲
  • 連接池范圍:20-50
  • 增量:5
  • 線程:1
  • 分區(qū):1
images-benchmarks-bonecp-singlethread.jpg

多線程

  • 500 個線程分別獲取釋放 100 個連接
  • 在獲取連接和釋放連接之間引入了 10ms 的延遲 Thread.sleep(),模擬連接完成工作
  • 連接池范圍:50-200
  • 增量:5
  • 線程:5
images-benchmarks-bonecp-multithread-10ms-delay.jpg

Prepared Statement

  • 500 個線程分別獲取釋放 100 個連接
  • 無延遲
  • 連接池范圍:50-200
  • 增量:5
  • 線程:5
Lusifer_20190618071006.png

為什么需要 HikariCP

BoneCP 作者放棄維護,并在 Github 項目主頁推薦大家使用 HikariCP,Hikari(ひかり[shi ga li]) 來自日文,是 的意思。這個產品的口號是 快速、簡單、可靠

優(yōu)化

  • 字節(jié)碼精簡 : 優(yōu)化代碼,直到編譯后的字節(jié)碼最少,這樣,CPU 緩存可以加載更多的程序代碼
  • 優(yōu)化代理和攔截器 : 減少代碼,例如 HikariCP 的 Statement proxy 只有 100 行代碼,只有 BoneCP 的十分之一
  • 自定義數組類型(FastStatementList)代替 ArrayList : 避免每次 get() 調用都要進行 range check,避免調用 remove() 時的從頭到尾的掃描
  • 自定義集合類型(ConcurrentBag): 提高并發(fā)讀寫的效率
  • 其他針對 BoneCP 缺陷的優(yōu)化: 比如對于耗時超過一個 CPU 時間片的方法調用的研究(但沒說具體怎么優(yōu)化)

代碼量

幾個連接池的代碼量對比(代碼量越少,一般意味著執(zhí)行效率越高、發(fā)生 BUG 的可能性越低)

Pool Files Code
Vibur 34 1927
HikariCP 21 2228
Tomcat 31 6345
BoneCP 49 7293
C3P0 120 15550

速度

別人發(fā)推文測試 Hikari 速度

B1IiUUxCAAEgIHY.jpg

穩(wěn)定性

Lusifer_20191205010734.png

可靠性

另外,關于可靠性方面,也是有實驗和數據支持的。對于數據庫連接中斷的情況,通過測試 getConnection(),各種 CP 的不相同處理方法如下(所有 CP 都配置了跟 connectionTimeout 類似的參數為 5 秒鐘)

  • HikariCP(A): 等待 5 秒鐘后,如果連接還是沒有恢復,則拋出一個 SQLExceptions 異常;后續(xù)的 getConnection() 也是一樣處理
  • C3P0(C-): 完全沒有反應,沒有提示,也不會在 CheckoutTimeout 配置的時長超時后有任何通知給調用者;然后等待 2 分鐘后終于醒來了,返回一個 error
  • Tomcat(F): 返回一個 connection,然后調用者如果利用這個無效的 connection 執(zhí)行 SQL 語句 結果可想而知;大約 55 秒之后終于醒來了,這時候的 getConnection() 終于可以返回一個 error,但沒有等待參數配置的 5 秒鐘,而是立即返回 error
  • BoneCP(C): 跟 Tomcat 的處理方法一樣;也是大約 55 秒之后才醒來,有了正常的反應,并且終于會等待 5 秒鐘之后返回 error 了

整合 HikariCP

POM

<!-- 主要增加 HikariCP 依賴 -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>${hikaricp.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <exclusions>
        <!-- 排除 tomcat-jdbc 以使用 HikariCP -->
        <exclusion>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- MySQL 驅動 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>

application.yml

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.141.130:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
    hikari:
      minimum-idle: 5
      idle-timeout: 600000
      maximum-pool-size: 10
      auto-commit: true
      pool-name: MyHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1

注意: 具體使用方法在 測試 MyBatis 操作數據庫 時進行介紹,此處僅為準備環(huán)節(jié)

Spring Boot 整合 TkMyBatis

tk.mybatis 是在 MyBatis 框架的基礎上提供了很多工具,讓開發(fā)更加高效

POM

pom.xml 文件中引入 mapper-spring-boot-starter 依賴,該依賴會自動引入 MyBaits 相關依賴

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>

application.yml

mybatis:
    # 實體類的存放路徑
    type-aliases-package: com.funtl.hello.spring.boot.domain
    mapper-locations: classpath:mapper/*.xml

創(chuàng)建通用父級接口

主要作用是讓 DAO 層的接口繼承該接口,以達到使用 tk.mybatis 的目的

package tk.mybatis.mapper;

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

/**
 * 自己的 Mapper
 * 特別注意,該接口不能被掃描到,否則會出錯
 * <p>Title: MyMapper</p>
 * <p>Description: </p>
 *
 * @author Lusifer
 * @version 1.0.0
 * @date 2018/5/29 0:57
 */
public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
}

Spring Boot 整合 PageHelper

PageHelper 是 Mybatis 的分頁插件,支持多數據庫、多數據源??梢院喕瘮祿斓姆猪摬樵儾僮鳎线^程也極其簡單,只需引入依賴即可

POM

pom.xml 文件中引入 pagehelper-spring-boot-starter 依賴

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.12</version>
</dependency>

代碼生成插件

我們無需手動編寫 實體類、DAO、XML 配置文件,只需要使用 MyBatis 提供的一個 Maven 插件就可以自動生成所需的各種文件便能夠滿足基本的業(yè)務需求,如果業(yè)務比較復雜只需要修改相關文件即可

配置插件

pom.xml 文件中增加 mybatis-generator-maven-plugin 插件

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
                <overwrite>true</overwrite>
                <verbose>true</verbose>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>${mysql.version}</version>
                </dependency>
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>4.1.5</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

注意: configurationFile 自動生成所需的配置文件路徑

自動生成的配置

src/main/resources/generator/ 目錄下創(chuàng)建 generatorConfig.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!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="jdbc.properties"/>

    <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        
        <!-- 配置 tk.mybatis 插件 -->
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="com.funtl.utils.MyMapper"/>
        </plugin>

        <!-- 配置數據庫連接 -->
        <jdbcConnection
                driverClass="${jdbc.driverClass}"
                connectionURL="${jdbc.connectionURL}"
                userId="${jdbc.username}"
                password="${jdbc.password}">
        </jdbcConnection>

        <!-- 配置實體類存放路徑 -->
        <javaModelGenerator targetPackage="com.funtl.hello.spring.boot.domain" targetProject="src/main/java"/>

        <!-- 配置 XML 存放路徑 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>

        <!-- 配置 DAO 存放路徑 -->
        <javaClientGenerator
                targetPackage="com.funtl.hello.spring.boot.mapper"
                targetProject="src/main/java"
                type="XMLMAPPER"/>

        <!-- 配置需要指定生成的數據庫和表,% 代表所有表 -->
        <table catalog="myshop" tableName="%">
            <!-- 默認為 false,如果設置為 true,在生成的 SQL 中,table 名字不會加上 catalog 或 schema -->
            <property name="ignoreQualifiersAtRuntime" value="true"/>
            
            <!-- mysql 配置 -->
            <generatedKey column="id" sqlStatement="Mysql" identity="true"/>
        </table>
    </context>
</generatorConfiguration>

配置數據源

src/main/resources 目錄下創(chuàng)建 jdbc.properties 數據源配置:

jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://192.168.141.130:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=123456

插件自動生成

mvn mybatis-generator:generate

# 輸出如下
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" -Dvisualvm.id=757855494303000 -Dmaven.multiModuleProjectDirectory=D:\Workspace\Study\other\hello-spring-boot "-Dmaven.home=C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\plugins\maven\lib\maven3" "-Dclassworlds.conf=C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\plugins\maven\lib\maven3\bin\m2.conf" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=64651:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\plugins\maven\lib\maven3\boot\plexus-classworlds-2.5.2.jar" org.codehaus.classworlds.Launcher -Didea.version2019.1.3 --update-snapshots -s D:\apache-maven-3.6.1\conf\settings.xml org.mybatis.generator:mybatis-generator-maven-plugin:1.3.7:generate
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building hello-spring-boot 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- mybatis-generator-maven-plugin:1.3.7:generate (default-cli) @ hello-spring-boot ---
[INFO] Connecting to the Database
[INFO] Introspecting table myshop..%
[INFO] Generating Record class for table myshop..tb_item_param_item
[INFO] Generating Mapper Interface for table myshop..tb_item_param_item
[INFO] Generating SQL Map for table myshop..tb_item_param_item
[INFO] Generating Record class for table myshop..tb_item_cat
[INFO] Generating Mapper Interface for table myshop..tb_item_cat
[INFO] Generating SQL Map for table myshop..tb_item_cat
[INFO] Generating Record class for table myshop..tb_order
[INFO] Generating Mapper Interface for table myshop..tb_order
[INFO] Generating SQL Map for table myshop..tb_order
[INFO] Generating Record class for table myshop..tb_content
[INFO] Generating Mapper Interface for table myshop..tb_content
[INFO] Generating SQL Map for table myshop..tb_content
[INFO] Generating Record class for table myshop..tb_order_item
[INFO] Generating Mapper Interface for table myshop..tb_order_item
[INFO] Generating SQL Map for table myshop..tb_order_item
[INFO] Generating Record class for table myshop..tb_item
[INFO] Generating Mapper Interface for table myshop..tb_item
[INFO] Generating SQL Map for table myshop..tb_item
[INFO] Generating Record class for table myshop..tb_item_desc
[INFO] Generating Mapper Interface for table myshop..tb_item_desc
[INFO] Generating SQL Map for table myshop..tb_item_desc
[INFO] Generating Record class for table myshop..tb_item_param
[INFO] Generating Mapper Interface for table myshop..tb_item_param
[INFO] Generating SQL Map for table myshop..tb_item_param
[INFO] Generating Record class for table myshop..tb_order_shipping
[INFO] Generating Mapper Interface for table myshop..tb_order_shipping
[INFO] Generating SQL Map for table myshop..tb_order_shipping
[INFO] Generating Record class for table myshop..tb_user
[INFO] Generating Mapper Interface for table myshop..tb_user
[INFO] Generating SQL Map for table myshop..tb_user
[INFO] Generating Record class for table myshop..tb_content_category
[INFO] Generating Mapper Interface for table myshop..tb_content_category
[INFO] Generating SQL Map for table myshop..tb_content_category
[INFO] Saving file TbItemParamItemMapper.xml
[INFO] Saving file TbItemCatMapper.xml
[INFO] Saving file TbOrderMapper.xml
[INFO] Saving file TbContentMapper.xml
[INFO] Saving file TbOrderItemMapper.xml
[INFO] Saving file TbItemMapper.xml
[INFO] Saving file TbItemDescMapper.xml
[INFO] Saving file TbItemParamMapper.xml
[INFO] Saving file TbOrderShippingMapper.xml
[INFO] Saving file TbUserMapper.xml
[INFO] Saving file TbContentCategoryMapper.xml
[INFO] Saving file TbItemParamItem.java
[INFO] Saving file TbItemParamItemMapper.java
[INFO] Saving file TbItemCat.java
[INFO] Saving file TbItemCatMapper.java
[INFO] Saving file TbOrder.java
[INFO] Saving file TbOrderMapper.java
[INFO] Saving file TbContent.java
[INFO] Saving file TbContentMapper.java
[INFO] Saving file TbOrderItem.java
[INFO] Saving file TbOrderItemMapper.java
[INFO] Saving file TbItem.java
[INFO] Saving file TbItemMapper.java
[INFO] Saving file TbItemDesc.java
[INFO] Saving file TbItemDescMapper.java
[INFO] Saving file TbItemParam.java
[INFO] Saving file TbItemParamMapper.java
[INFO] Saving file TbOrderShipping.java
[INFO] Saving file TbOrderShippingMapper.java
[INFO] Saving file TbUser.java
[INFO] Saving file TbUserMapper.java
[INFO] Saving file TbContentCategory.java
[INFO] Saving file TbContentCategoryMapper.java
[WARNING] Column id, specified as an identity column in table myshop..tb_order, does not exist in the table.
[WARNING] Column id, specified as an identity column in table myshop..tb_item_desc, does not exist in the table.
[WARNING] Column id, specified as an identity column in table myshop..tb_order_shipping, does not exist in the table.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.892 s
[INFO] Finished at: 2019-06-24T03:40:09+08:00
[INFO] Final Memory: 30M/634M
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

CRUD 案例

package com.funtl.hello.spring.boot;
import java.util.Date;

import com.funtl.hello.spring.boot.domain.TbUser;
import com.funtl.hello.spring.boot.mapper.TbUserMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@Rollback
public class HelloSpringBootApplicationTests {

    /**
     * 注入 DAO
     */
    @Autowired
    private TbUserMapper tbUserMapper;

    /**
     * 查詢
     */
    @Test
    public void testSelectAll() {
        List<TbUser> tbUsers = tbUserMapper.selectAll();
        tbUsers.forEach(tbUser -> {
            System.out.println(tbUser);
        });
    }

    /**
     * 條件查詢
     */
    @Test
    public void testSelectCondition() {
        Example example = new Example(TbUser.class);
        example.createCriteria().andEqualTo("username", "zhangsan");
        List<TbUser> tbUsers = tbUserMapper.selectByExample(example);
        tbUsers.forEach(tbUser -> {
            System.out.println(tbUser);
        });
    }

    /**
     * 新增
     */
    @Test
    public void testInsert() {
        TbUser tbUser = new TbUser();
        tbUser.setUsername("Lusifer");
        tbUser.setPassword("123456");
        tbUser.setPhone("15888888888");
        tbUser.setEmail("topsale@vip.qq.com");
        tbUser.setCreated(new Date());
        tbUser.setUpdated(new Date());

        tbUserMapper.insert(tbUser);
    }

    /**
     * 更新
     */
    @Test
    public void testUpdate() {
        TbUser tbUser = tbUserMapper.selectByPrimaryKey(37L);
        tbUser.setUsername("Happy");

        tbUserMapper.updateByPrimaryKey(tbUser);
    }

    /**
     * 修改
     */
    @Test
    public void testDelete() {
        tbUserMapper.deleteByPrimaryKey(37L);
    }

    /**
     * 分頁
     */
    @Test
    public void testPage() {
        Example example = new Example(TbUser.class);
        example.createCriteria().andLike("username", "z%");

        PageHelper.startPage(1, 5);
        PageInfo<TbUser> pageInfo = new PageInfo<>(tbUserMapper.selectByExample(example));
        System.out.println(pageInfo.getTotal());
        System.out.println(pageInfo.getPages());
        pageInfo.getList().forEach(tbUser -> {
            System.out.println(tbUser);
        });
    }

}

特別說明: 本人平時混跡于 B 站,不咋回復這里的評論,有問題可以到 B 站視頻評論區(qū)留言找我
視頻地址: https://space.bilibili.com/31137138/favlist?fid=326428938
課件說明: 本次提供的課件是 Spring Cloud Netflix 版微服務架構指南,如果有興趣想要學習 Spring Cloud Alibaba 版,可以前往 http://www.qfdmy.com 查看相關課程資源
案例代碼: https://github.com/topsale/hello-spring-cloud-netflix

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容