Spring 打造一個 RESTful Web Service
就是 Spring 官方網站 guides 導讀。
既然學習 Spring 那就要去一下 Spring 的官方網站看一下人家的教程。 這篇就是其中的一篇 Building a RESTful Web Service。
我們這次將建立一個在 http://localhost:8080/greeting 接受 HTTP Get 方法的服務,接到請求後會回傳一個 JSON 格式的歡迎訊息。
{
"id": 1,
"content": "Hello, World!"
}
我們也可以選擇是否要在網址內傳入 name 參數,像是這樣。
http://localhost:8080/greeting?name=User
若是有收到 name 參數,便會覆蓋掉預設值 World 字串。
{
"id": 1,
"content": "Hello, User!"
}
我們可以從頭開始一步一步地慢慢完成專案,或者我們可以跳過一些我們已經相當熟悉了的設定,不管是哪種方法,我們都是可以完成專案的。
使用 Spring CLI 初始化專案
ok!到這邊我們開始就跟 Spring.io 他們的官方教程有一點點不一樣了,官方教程是用一個叫做 Spring Initializr 的工具來初始化專案,但我們這邊用 Spring CLI 來建立專案! ( 別誤會呀!Spring Initializr 是很好用的工具 我的入門工具也是它。 但是我現在喜歡用 Spring CLI 而已,事實上 Spring CLI 也是打要求過去 https://start.spring.io 的 )
我們建立專案只要簡單這行:
# 相依性只要簡單地 web 就好了!
$ spring init -d web my-app.zip
解壓縮 zip 檔案之後我們的專案就建立起來了。
先來看看我們的專案設定檔。
<?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>
<!-- ... 略過 ... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ... 略過 ... -->
</dependencies>
<!-- ... 略過 ... -->
</project>
這邊只要看到這個相依性就好了,我們只有一個額外的相依性, 就是剛剛使用 Spring CLI 的 -d 參數加入的 web 所加入相依性。
建立資源表示類別 ( Resource Representation Class )
這個翻譯的比較蹩腳,簡單說就是我們剛才不是說要建立這樣的回傳格式。
{
"id": 1,
"content": "Hello, World!"
}
那在 Java 裡面就要建立一個有這兩個成員的類別出來。
package com.example.myapp;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
這是一個非常乾淨的 POJO 類別,就是兩個唯獨的成員 id, content 而已。
Spring 預設是以 Jackson JSON 來解析類別為 JSON 字串, 以本例來說就會用 Jackson 將 Greeting 物件轉為 JSON 字串,所以我們不用特別做序列化的動作。
建立 Greeting 頁面控制器 ( Controller )
控制器雖然是滿常見的翻譯,但我自己還是覺得挺蹩腳的,還是講 Controller。
package com.example.myapp.web;
import com.example.myapp.Greeting;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class GreetingController {
private static final String template = "Hello, %s";
private final AtomicLong counter = new AtomicLong();
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
重點有以下幾個:
- @RestController - 就是 @Controller 加 @ResponseBody
- @Controller - 會告訴 Spring 自己這個類別是一個控制器,當 Spring 知道他是控制器之後,便會把收到的要求轉發到這個控制器
- @ResponseBody - 顧名思義 表示會將回傳的內容直接透過 HTTP 打回去。若是只有 @Controller 通常會將回傳值解析為跳轉路徑,不直接回傳。
- @GetMapping - 就是處理 HTTP Get 方法 @GetMapping("/greeting") 就是處理使用 HTTP Get 方法 對 /greeting 的請求
這樣就設定完了。可以直接把專案跑起來了,執行 DemoApplication 的 main() 方法。
再來訪問 http://localhost:8080/greeting http://localhost:8080/greeting?name=User 就可以看到不同的結果了。