# 六角鼠年鐵人賽 Week 10 - Spring Boot - Build first API
==大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai==
### 短歌行 曹操
:::info
對酒當歌,人生幾何!譬如朝露,去日苦多。
慨當以慷,憂思難忘。何以解憂?唯有杜康。
青青子衿,悠悠我心。但爲君故,沉吟至今。
呦呦鹿鳴,食野之苹。我有嘉賓,鼓瑟吹笙。
明明如月,何時可掇?憂從中來,不可斷絕。
越陌度阡,枉用相存。契闊談宴,心念舊恩。
月明星稀,烏鵲南飛。繞樹三匝,何枝可依?
山不厭高,海不厭深。周公吐哺,天下歸心。
:::
上篇介紹過了 Spring Boot 的項目與優缺點,該篇就來手動建造個人的第一個 API 吧!
個人使用的工具為 **Intellij** 2019.03 community 版本,如果沒用過的人可以去下載來使用看看。
> **Intellij** 是 **JetBrain 公司** 專門為 Java 提供開發環境的 IDE,分作 **收費板(Ultimate)** 與 **免費版(Community)**。
>>JetBrain 開發了許多好用的 IDE,其中幾個著名的如:
GoLand(GO語言)、
WebStorm(JavaScripts)、
PyCharm(Python)
等等,都是各領域工程師愛用的 IDE
收費版的功能十分強大,不過因為只是學習,我們只需要下載安裝 Community 版本就好,目前最新的 Version 是 2019.03 版。
[Intellij 官網](https://www.jetbrains.com/idea/)
[Intellij IDE Download Page](https://www.jetbrains.com/idea/download/#section=windows)
## 建置第一個 Spring Boot 專案
我將使用 Gradle 方式進行建置,如果想用 Maven 的話,可自行選用習慣的方式建置。

到如下圖的畫面後,輸入 or 更新 Name、GroupId 兩個欄位
Name: 專案名稱
GroupId: domain Name

如果有遇到下面這張圖的問題,請不要擔心,這只是 Intellij 和 Windows Defender 之間的影響而已,直接選擇 Fix... 處理它

點選 Configure Automatically ,接著應該會跳出一個確認視窗,點選 **是** 即可

## 調整 Gradle 設定
不免得我們還是要處理 Gradle 的設定來幫助我們安置要使用到的 Java 套件包
請打開 build.gradle 檔案
若有遇到如下圖的狀況,請選擇 Ok, apply suggestion! 這是 Gradle 在協助開發者處理 Gradle 相關服務的東西
(詳細可以查看gradle/wrapper/gradle-wrapper.properties 檔案中的設定)

接著我們開始調整 build.gradle 的設定:
1. 首先在 plugins 加入下列兩行,以取得 springboot 的框架套件
```
id 'org.springframework.boot' version '2.2.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
```
若有出現下圖,請開心的點選 Enable Auto-Import,這樣未來 build.gradle 的更動 Intellij IDE 都會自動地幫你完成處理

2. 在 dependencies 中替換成以下內容,明確說明我們將使用的是 springboot starter web 的套件作開發,加上測試用的 JUnit 套件
```
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
```
3. 加入下面的內容,我們會去使用 JUnit Platform 幫助
```
test {
useJUnitPlatform()
}
```
4. 加入下面的指令,這樣等等我們就可以直接透過 Gradle 作測試執行,而不需要包成 Jar 檔
mainClassName 的內容視個人專案情況修正,主要是執行 Starter Class
```
apply plugin: 'application'
mainClassName = 'kai.com.springbootApplicationStarter'
```
:::spoiler **完整 build.gradle 內容**
```
plugins {
id 'java'
id 'org.springframework.boot' version '2.2.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
}
group 'kai.com'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
apply plugin: 'application'
mainClassName = 'kai.com.springbootApplicationStarter'
```
:::
## 創建 Spring Boot Starter
Spring boot 會從標記 @SpringBootApplication 這個 annotation 的 Class 開始執行,每個Spring boot 專案都需要設定一個 Starter Class。
==為求方便,Kai 自己稱呼其為 Starter,此不代表絕對名稱==
```java=
package kai.com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class springbootApplicationStarter {
public static void main(String [] args){
SpringApplication.run(springbootApplicationStarter.class,args);
}
}
```
> 關於 @SpringBootApplication 其實際上包含了 @Configuration、@EnableAutoConfiguration、@ComponentScan 三個設定的功能。
>
> 在 Spring boot 的專案中,只需要設定 @SpringBootApplication 即可。
## 創建 API Controller
在這裡,我建立了兩個 Restful API,一個 GET 一個 POST,他們分別有不同取得參數的方式,在回傳部分,我會使用相同的 POJO Class 處理好,這樣方便我們檢視兩種方法的使用差異。
> @RestController 預設會回傳 application/json 格式的資料,如有需要可以調整
```java=
package kai.com.controller;
import kai.com.bean.chatBean;
import org.springframework.web.bind.annotation.*;
@RestController
public class chatController {
@GetMapping("/chat")
public chatBean chatting(@RequestParam(value = "username", defaultValue = "Unknowns") String username,
@RequestParam(value = "content", defaultValue = "") String content) {
String status = "Get By GET.";
return new chatBean(username,content,status);
}
@PostMapping("/chat")
public chatBean chatting2(@RequestBody chatBean cb) {
String status = "Get By POST.";
cb.setStatus(status);
return cb;
}
}
```
## 創建 POJO Bean
我們會創建一個用來存放資訊的 POJO 的 Bean Class,簡單的設計一個 username 和 content 以及告知的 status 就好。
我會在 call API 時候,將 username 和 content 預先放入 request 中,等程式取得這個 request 的時候,再塞入 status 值並返回這個 Bean,以便在取得回應時看到完整的 Bean 資訊。
```java=
package kai.com.bean;
public class chatBean {
private String username;
private String content;
private String status;
public chatBean(String username, String content, String status){
this.username = username;
this.content = content;
this.status = status;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
```
## 測試
打開最右邊的 Gradle 功能列表,進入 Tasks > application,點擊兩下 bootRun,Gradle 會開始進行 Project Compile,並在完成後直接執行。

Kai 這邊使用 **SoapUI** 進行 call API 的測試,若是習慣其他如 Post Man 軟體的開發者也可以用自己習慣的軟體進行測試。
By GET 成功!

By POST 成功!

## Build Jar
完成開發與測試後就可以開始 Build Jar 了,雖然測試不是使用 JUnit... 這部分 Kai 想保留到後續專門介紹 JUnit 的時候再說。
打開 Gradle 功能列表,進入 Tasks > build,點擊兩下 build 執行建置。

當建置完成後,便可在左方的專案列表中看到 build 資料夾與底下已建置好的 jar 檔和其他文檔。

**springboot-first-api-1.0-SNAPSHOT.jar** 便是可以直接執行的 Jar 檔,且不需要放置在任何 Apache 底下即可獨立運行。
## 結語
:::danger
以上內容就已經完成了一支簡單易懂的 Restful API 了。
下一篇將介紹 Lombok 套件
[六角鼠年鐵人賽 Week 11 - Spring Boot - Lombok 省時省力好幫手](/uWHqezBxQ9CPqr5iUOfNFQ?both)
:::
首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA)
###### tags: `Spring Boot`,`w3HexSchool`