【前置內容】Spring 學習筆記全系列傳送門:
【前置內容】SpingMVC 學習筆記全系列傳送門:
1、SpringBoot 簡介
1.1 SpringBoot 快速入門
1.1.1 開發步驟
-
建立新模組,選擇Spring初始化,並配置模組相關基礎資訊
-
選擇當前模組需要使用的技術集
-
開發控制器類
-
執行自動生成的Application類
1.1.1.1 建立新模組
-
選擇
Spring Initializr
,用來建立SpringBoot
工程 -
打包方式這裡需要設定為
Jar
-
選中
Web
,然後勾選Spring Web
-
Java 版本選 Java8
-
pom.xml 檔案預覽
需要注意:
- 父包 spring-boot-starter-parent 的版本手動更改為了 2.6.3,jdk版本1.8 與 spring boot 3.0.0 版本不匹配,會報錯
- <java.version> 修改為了1.8
<?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.6.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>priv.dandelion</groupId> <artifactId>springboot_01_quickstart</artifactId> <version>0.0.1-SNAPSHOT</version> <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> </plugin> </plugins> </build> </project>
1.1.1.2 建立 Controller
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping("/{id}")
public String getById(@PathVariable Integer id) {
System.out.println("id = " + id);
return "hello boot!";
}
}
1.1.1.3 啟動伺服器
直接執行引導類即可
1.1.2 開發內容對比
-
座標
Spring
程式中的座標需要自己編寫,而且座標非常多SpringBoot
程式中的座標是我們在建立工程時進行勾選自動生成的
-
web3.0配置類
Spring
程式需要自己編寫這個配置類。這個配置類大家之前編寫過,肯定感覺很複雜SpringBoot
程式不需要我們自己書寫
-
配置類
注意:基於Idea的
Spring Initializr
快速構建SpringBoot
工程時需要聯網。Spring/SpringMVC
程式的配置類需要自己書寫。而SpringBoot
程式則不需要書寫。
1.1.3 官網構建工程
SpringBoot官網:https://spring.io/projects/spring-boot
-
點選下方的 Quickstart 中的 Spring Initializr,開始快速建立專案,如下圖所示
1.1.4 SpringBoot 工程快速啟動
1.1.4.1 問題引入
- SpringBoot 程式伺服器執行在本機
- 當進行前後端聯調時,按理說前端需要連線後端開發的機器,比較麻煩
- 是否有更好的方式?
-
後端可以將
SpringBoot
工程打成jar
包- 該
jar
包執行不依賴於Tomcat
和Idea
也可以正常執行 - 這個
jar
包在執行過程中連線和我們自己程式相同的Mysql
資料庫即可
- 該
1.1.4.2 打包
-
首先必須在
pom.xml
中配置如下外掛<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
-
使用
Maven
的package
指令打包就會在target
目錄下生成對應的Jar
包 -
注意:
-
在執行
package
指令之前,最好先執行一次clean
指令,防止出現問題 -
如果配置檔案中包含中文,最好在設定中設定編碼為 UTF-8 並重新檢查配置檔案中的中文,避免出現亂碼問題導致配置檔案無法使用,具體操作如下
-
1.1.4.3 啟動
-
進入 jar 包所在目錄,使用 cmd 輸入命令
java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar
1.2 SpringBoot 概述
原始
Spring
環境搭建和開發存在以下問題:
- 配置繁瑣
- 依賴設定繁瑣
SpringBoot
程式優點恰巧就是針對Spring
的缺點
- 自動配置。這個是用來解決
Spring
程式配置繁瑣的問題- 起步依賴。這個是用來解決
Spring
程式依賴設定繁瑣的問題- 輔助功能(內建伺服器,...)。在啟動
SpringBoot
程式時既沒有使用本地的tomcat
也沒有使用tomcat
外掛,而是使用SpringBoot
內建的伺服器。
1.2.1 起步依賴 —— 核心:Maven 繼承
以後需要使用技術,只需要引入該技術對應的起步依賴即可
-
使用
Spring Initializr
方式建立的Maven
工程的的pom.xml
配置檔案中自動生成了很多包含starter
的依賴,這些以來就是啟動依賴,如下<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.8</version> </parent> <!-- ... --> <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>
1.2.1.1 探索父工程(原始碼不表)
-
進入父工程 spring-boot-starter-parent 中,其也有一個父工程
-
進入 spring-boot-starter-parent 的父工程 spring-boot-dependencies 中,其中包含:
<properties...>
標籤中定義了各個技術軟體依賴的版本,避免了我們在使用不同軟體技術時考慮版本的相容問題。在properties
中可以找到各種技術的版本。<dependencyManagement...>
標籤是進行依賴版本鎖定,但是並沒有匯入對應的依賴;如果我們工程需要那個依賴只需要引入依賴的groupid
和artifactId
不需要定義version
。<build...>
標籤中對外掛的版本進行了鎖定
1.2.1.2 探索依賴
-
本工程中新增了如下依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
-
可以看到 spring-boot-starter-web 引入瞭如下依賴
- 引入了
spring-web
和spring-webmvc
的依賴,這就是為什麼我們的工程中沒有依賴這兩個包還能正常使用springMVC
中的註解的原因。 - 而依賴
spring-boot-starter-tomcat
,從名字基本能確認內部依賴了tomcat
,所以我們的工程才能正常啟動。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.7.8</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.7.8</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.7.8</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.25</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.25</version> <scope>compile</scope> </dependency> </dependencies>
- 引入了
1.2.1.3 小結
-
starter
SpringBoot
中常見專案名稱,定義了當前專案使用的所有專案座標,以達到減少依賴配置的目的
-
parent
- 所有
SpringBoot
專案要繼承的專案,定義了若干個座標版本號(依賴管理,而非依賴),以達到減少依賴衝突的目的
- 所有
-
實際開發
-
使用任意座標時,僅書寫GAV中的G和A,V由SpringBoot提供
G:groupid
A:artifactId
V:version
-
如發生座標錯誤,再指定version(要小心版本衝突)
-
1.2.2 程式啟動
-
引導類
@SpringBootApplication public class Springboot01QuickstartApplication { public static void main(String[] args) { SpringApplication.run(Springboot01QuickstartApplication.class, args); } }
-
注意
SpringBoot
在建立專案時,採用 jar 的打包方式SpringBoot
的引導類是專案的入口,執行main
方法就可以啟動專案- 因為
pom.xml
中配置了spring-boot-starter-web
依賴,而該依賴中依賴tomcat
,所以執行main
方法就可以使用tomcat
啟動工程。
1.2.3 切換 web 伺服器
-
目前啟動工程使用的是
tomcat
伺服器,spring-boot-starter-web
依賴中依賴了tomcat
-
如果要使用其他伺服器就需要將 tomcat 排除,更換為
jetty
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
2、配置檔案
2.1 配置檔案格式及優先順序
- 當三種配置檔案均存在時,優先順序
application.properties
>application.yml
>application.yaml
SpringBoot
程式的配置檔名必須是application
,只是字尾名不同
-
application.properties
server.port=80
-
application.yml
(常用)server: port: 81
-
application.yaml
server: port: 82
2.2 yaml 格式
2.2.1 概述
-
特點
-
YAML(YAML Ain't Markup Language),一種資料序列化格式。
-
相比於 xml 和 properties 而言重資料,輕格式
-
-
優點
-
容易閱讀
yaml
型別的配置檔案比xml
型別的配置檔案更容易閱讀,結構更加清晰
-
容易與指令碼語言互動
-
以資料為核心,重資料輕格式
yaml
更注重資料,而xml
更注重格式
-
-
副檔名
.yml
(主流).yaml
2.2.2 語法規則
-
規則
-
大小寫敏感
-
屬性層級關係使用多行描述,每行結尾使用冒號結束
-
使用縮排表示層級關係,同層級左側對齊,只允許使用空格(不允許使用Tab鍵),空格的個數並不重要,只要保證同層級的左側對齊即可。
-
屬性值前面新增空格(屬性名與屬性值之間使用冒號+空格作為分隔)
-
# 表示註釋
-
-
示例
# 層級關係 enterprise: name: dandelion age: 16 tel: 12345456767 # 陣列格式 subject: - Java - C++ - 演算法
2.3 yaml 配置檔案資料讀取
2.3.1 環境準備
-
準配配置檔案
application.yaml
lesson: SpringBoot server: port: 80 enterprise: name: dandelion age: 16 tel: 12345456767 subject: - Java - C++ - 演算法
2.3.2 讀取配置資料
2.3.2.1 使用 @Value 註解
直接使用
@Value("${ }")
註解進行注入,用於讀取單個資料,引數為${ }
包裹的資料名稱的字串
-
Controller 示例
@RestController @RequestMapping("/books") public class BookController { // 讀取資料 @Value("${lesson}") private String lesson; // 多級資料 @Value("${server.port}") private Integer port; // 陣列元素 @Value("${enterprise.subject[0]}") private String subject_00; @GetMapping("/{id}") public String getById(@PathVariable Integer id) { System.out.println(lesson); System.out.println(port); System.out.println(subject_00); return "hello boot!"; } }
2.3.2.2 Environment 物件
用於獲取全部資料,使用時對
Environment
型別的屬性進行自動裝配,使用其getProperty()
方法來獲取資料
-
Controller 示例
import org.springframework.core.env.Environment; // import ... @RestController @RequestMapping("/books") public class BookController { // 獲取全部資料,注入到Environment型別中 @Autowired private Environment environment; @GetMapping("/{id}") public String getById(@PathVariable Integer id) { // System.out.println(environment.getProperty("lesson")); System.out.println(environment.getProperty("server.port")); System.out.println(environment.getProperty("enterprise.age")); System.out.println(environment.getProperty("enterprise.subject[1]")); return "hello boot!"; } }
2.3.2.3 自定義物件
該方式用於讀取任意資料,將其封裝為實體類,使用註解繫結獲取資料的範圍,在獲取時,透過自動注入獲取該實體類物件並進行操作
-
定義資料的實體類,和配置檔案中保持一致,並實現其 Getter 和 Setter
- 後續要使用自動裝配,故要新增 @Component 註解,將這個類交給 Spring 管理
- 使用
@ConfigurationProperties(prefix = "enterprise")
註解,prefix
屬性值表示讀取配置檔案的哪一部分資料,此處代表讀取enterprise
中的資料
@Component @ConfigurationProperties(prefix = "enterprise") public class Enterprise { private String name; private int age; private String tel; private String[] subject; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String[] getSubject() { return subject; } public void setSubject(String[] subject) { this.subject = subject; } @Override public String toString() { return "Enterprise{" + "name='" + name + '\'' + ", age=" + age + ", tel='" + tel + '\'' + ", subject=" + Arrays.toString(subject) + '}'; } }
-
Controller 示例
@RestController @RequestMapping("/books") public class BookController { @Autowired private Enterprise enterprise; @GetMapping("/{id}") public String getById(@PathVariable Integer id) { System.out.println(enterprise); return "hello boot!"; } }
2.4 多環境配置
2.4.1 yaml 檔案
-
簡單書寫
- 使用
spring.profiles
設定環境的名稱 - 使用
---
將不同的環境進行分隔 - 使用
spring.profiles.active
設定啟動專案時使用的環境 - 公用的配置可以寫在第一部分中
#設定啟用的環境 spring: profiles: active: test --- #開發環境 spring: profiles: dev server: port: 80 --- #測試環境 spring: profiles: test server: port: 81 --- #生產環境 spring: profiles: pro server: port: 82
- 使用
-
標註書寫
簡單書寫部分中,設定環境的名稱的
spring.profiles
的書寫格式並不規範,規範的書寫格式如下#開發環境 spring: config: activate: on-profile: dev server: port: 80
2.4.2 properties 檔案
- 與 yaml 檔案不同,properties 的多環境配置寫在不同的檔案中,並在主配置檔案中指定使用的環境
- 多個環境使用檔名進行區分和定義,
application-環境名.properties
- 公用的配置可以寫
application.properties
中
-
主配置檔案
application.properties
#設定啟用的環境 spring.profiles.active=dev
-
開發環境和測試環境
-
開發環境
application-dev.properties
server.port=80
-
測試環境
application-test.properties
server.port=81
-
2.4.3 命令列啟動引數配置
-
命令列臨時配置
可以在啟動指令後新增引數來臨時覆蓋配置檔案中的內容,引數可以有多個,每一個引數的格式為
-- 空格 使用.連線的配置屬性名稱=屬性值
,如下java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar -- spring.profiles.active=test -- server.port=88
-
配置的優先順序
- 如上,命令中新增引數的優先順序大於原本配置檔案的優先順序
SpringBoot
官網對於優先順序已經進行了說明,參見:- 官方文件:Externalized Configuration
- 中文手冊:外化配置
2.5 配置檔案分類
-
命令列啟動引數配置存在問題
- 由於測試環境和開發環境的很多配置都不相同,所以測試人員在執行我們的工程時需要臨時修改很多配置,可能引數過多,過於複雜
-
解決方案:額外的配置類
-
SpringBoot 配置檔案中 4 級配置檔案位置及其優先順序(優先順序逐級提升):
- 1級:classpath:application.yml 【最低】
- 2級:classpath:config/application.yml
- 3級:file :application.yml
- 4級:file :config/application.yml 【最高】
-
說明
- classpath 指的是專案的 resources 目錄下,file 指的是打好的 jar 包所在的目錄下
- file 中的配置檔案一般用於系統打包後臨時設定通用屬性,classpath 中的配置檔案一般用於開發階段設定通用屬性
- file 中的配置檔案的優先順序高於 classpath 中的配置檔案
- 同一分類的配置中,config 資料夾中的配置檔案的優先順序高於 config資料夾外的配置檔案
-
3、SpringBoot 整合 Junit
3.1 環境準備
-
建立新的模組,不需要依賴
-
Service 實現類(介面不表)
@Service public class BookServiceImpl implements BookService { @Override public void save() { System.out.println("book save!"); } }
3.2 測試類編寫
-
測試類中(
@SpringBootTest
修飾),將BookService
注入如果測試類和引導類的包名不一致,需要為
@SpringBootTest
的 class 屬性手動指定引導類的位元組碼物件,如@SpringBootTest(classes = Springboot02TestApplication.class)
@SpringBootTest class Springboot02TestApplicationTests { @Autowired private BookService bookService; @Test void contextLoads() { bookService.save(); } }
4、SpringBoot 整合 Mybatis
4.1 回顧 Spring 整合 Mybatis
4.2 SpringBoot 整合Mybatis
4.2.1 建立模組
-
依賴
- MyBatis Framework
- MySQL Driver
4.2.2 定義實體類
public class Book {
private Integer id;
private String name;
private String type;
private String description;
// Getter、Setter、toString...
}
4.2.3 定義 dao
資料庫SQL見前置內容,tbl_book 表SQL,此處不再贅述
-
dao (報錯)
public interface BookDao { @Select("select * from tbl_book where id = #{id}") public Book getById(Integer id); }
-
存在問題及解決方案
-
報錯:
No qualifying bean of type 'priv.dandelion.dao.BookDao' available
錯誤資訊顯示在
Spring
容器中沒有BookDao
型別的bean
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'priv.dandelion.dao.BookDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) ~[spring-beans-5.3.25.jar:5.3.25] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) ~[spring-beans-5.3.25.jar:5.3.25] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.25.jar:5.3.25] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.25.jar:5.3.25] ... 74 common frames omitted
-
原因
Mybatis
會掃描介面並建立介面的程式碼物件交給Spring
管理,但是現在並沒有告訴Mybatis
哪個是dao
介面- 注意:Mysql驅動版本大於8.0時,需要在url連線串中配置時區
jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
,或在MySQL資料庫端配置時區解決此問題
-
解決方案:在
BookDao
介面上使用@Mapper
@Mapper public interface BookDao { @Select("select * from tbl_book where id = #{id}") public Book getById(Integer id); }
-
4.2.4 定義測試類
@SpringBootTest
class Springboot03MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
Book book = bookDao.getById(1);
System.out.println(book);
}
}
4.2.5 編寫配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: 123456
4.2.6 使用 Druid 資料來源
-
新增依賴
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency>
-
新增配置,指定使用 Druid 資料來源
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/ssm_db username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource
5、基於 SpringBoot 的 SSM 整合案例
- 本節內容是對上一篇 SSM 整合案例的改進,可參見SpingMVC 學習筆記 - 第二章 -SSM整合案例
- 開發步驟
pom.xml:配置起步依賴,必要的資源座標(druid)
application.yml:設定資料來源、埠等
配置類:現在不需要了
dao:設定@Mapper
測試類
頁面:放置在resources目錄下的static目錄中
5.1 建立工程
-
依賴
- Spring Web
- MyBatis Framework
- MySQL Driver
-
引入Druid
-
新增依賴
<!-- TODO 新增必要的依賴 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency>
-
5.2 後端程式碼整理
-
config 包,對比 SSM 專案全部刪除,現在不需要了
-
entity 包,實體,無變化
-
dao,新增
@Mapper
註解// TODO 新增@Mapper @Mapper public interface BookDao { @Insert("insert into tbl_book values(null,#{type},#{name},#{description})") // @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})") public int save(Book book); @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}") public int update(Book book); @Delete("delete from tbl_book where id = #{id}") public int delete(Integer id); @Select("select * from tbl_book where id = #{id}") public Book getById(Integer id); @Select("select * from tbl_book") public List<Book> getAll(); }
-
service,無變化
-
exception,無變化
-
controller,無變化
-
測試類,使用了 @SpringBootTest 註解,更換了使用的包
// import org.junit.Test; import org.junit.jupiter.api.Test; // import ... //@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(classes = SpringConfig.class) // TODO 將原先使用的註解更改為 @SpringBootTest @SpringBootTest public class BookServiceTest { @Autowired private BookService bookService; // TODO 原先使用的 @Test 註解 現在需要重新導包 @Test public void testGetById() { Book byId = bookService.getById(1); System.out.println(byId); } @Test public void testGetAll() { List<Book> all = bookService.getAll(); System.out.println(all); } }
5.3 配置檔案
#TODO 配置埠和資料來源相關資訊
server:
port: 80
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: 123456
5.4 靜態資源
-
靜態資源存放在 resources 目錄下的 static 目錄下
-
配置主頁
index.html
<!--TODO 配置主頁--> <script> document.location.href="pages/books.html"; </script>
5.5 包結構展示
5.6 其他問題
- 若再未加入前端程式碼時啟動過伺服器,加入前端程式碼後無法正常訪問到頁面時
- 執行 Maven 的 clean 指令,再重新啟動伺服器(重新打包)即可
- SpringBoot 版本問題、MySQL時區問題、專案無法構建、配置檔案打包亂碼等問題,本節筆記中均有提及,可向上查閱