Building your first Spring Boot web application

介紹如何建立用 Spring boot 建立 web application,內容從定義 Controller 和 Request Mapping 開始,接著會有如何取得輸入的參數,最後把做完的結果傳到樣版進行呈現

前置作業

如果你還沒有建立過 Spring boot 的專案,請先參考這篇文章 開始在 Mac 上開發 Spring boot 先試著把環境設定好,確定程式能夠執行才能往下做。

進入 Spring Initializr 產生一個測試專案,請選取 Spring WebThymeleaf 或開啟一個有載入 Spring WebThymeleaf 的 Spring boot 專案。

靜態資源

專案對應的靜態資源會放在 src/main/resources/static 目錄下面,所以像是 js, css, images 或是要直接被下載的檔案都可以直接放在這邊。

試著在 src/main/resources/static 建立一個 index.html 的檔案內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Hello Spring Boot</title>
</head>
<body>

<h2>Hello Spring Boot</h2>

<p>這是一個靜態檔案</p>

</body>
</html>

然後就可以透過 http://127.0.0.1:8080/ 看到下面這個畫面了。

使用 Controller

Annotated Controllers

Request Mapping

Handler Methods

Handler Methods 是 Route 的進入點,這邊分成兩個部分來介紹,分別是用來處理輸入的 Method Arguments 和用來處理輸出的 Return Values

Method Arguments

Return Values

  • @ResponseBody 在有標示這個 Annotation 的範圍裡,會直接把回傳的內容透過 HttpMessageConverter 做轉換
  • HttpEntity<T>, ResponseEntity<T> 回傳一個標準的 Http Response,其中包含 Header 和 Body,詳細內容可以參考 ResponseEntity
  • String 在沒有指定 @ResponseBody 的情況,回傳的這個 String 會被當成樣版名稱,透過 ViewResolver 來解析,若需要使用樣版變數,可在 Method Arguments 上可以指定要注入 Model,然後把樣版變數放入這個物件

Example

下面這是一個 Controller,底下的 Route 因為 Controller 有標示 @RequestMapping("first"),所以全部的 Path 都會是 /first/xxxx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package com.example.demo.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Controller
@RequestMapping("first")
public class FirstController {
/*
curl -X GET http://127.0.0.1:8080/first/route1
*/
@GetMapping("route1")
public ResponseEntity route1() {
return ResponseEntity.ok("Hi");
}

/*
curl -X GET http://127.0.0.1:8080/first/route2
*/
@RequestMapping("route2")
public ResponseEntity route2(HttpServletRequest request) {
Map<String, String> headers = Collections
.list(request.getHeaderNames())
.stream()
.collect(Collectors.toMap(h -> h, request::getHeader));

Map<String, Object> ret = new HashMap<>();
ret.put("header", headers);
ret.put("param", request.getParameterMap());
return ResponseEntity.ok(ret);
}

/*
curl -X GET http://127.0.0.1:8080/first/route3
*/
@GetMapping("route3")
@ResponseBody
public Map<String, Object> route3(HttpServletRequest request) {
return new HashMap<>() {{ this.put("A", "AAA"); }};
}

/*
curl -X GET http://127.0.0.1:8080/first/route4
*/
@GetMapping("route4")
public String route4(Model model) {
model.addAttribute("name", "Austin");
model.addAttribute("message", "This is test message!");
return "hello_template";
}

/*
curl -X POST http://127.0.0.1:8080/first/route5?name=Austin \
-F 'message=Hello Route5!'
*/
@PostMapping("route5")
public String route5(Model model, @RequestParam String name, @RequestParam String message) {
model.addAttribute("name", name);
model.addAttribute("message", message);

return "hello_template";
}

/*
curl -X POST http://127.0.0.1:8080/first/route6/Austin \
-H 'Content-Type: text/plain' \
-d 'Hello Route6!'
*/
@PostMapping("route6/{name}")
public String route6(Model model, @PathVariable String name, @RequestBody String body) {
model.addAttribute("name", name);
model.addAttribute("message", body);

return "hello_template";
}

/*
curl -X POST http://127.0.0.1:8080/first/route7 \
-H 'Content-Type: application/json' \
-d '{"name": "Austin", "message":"Hello Route7!"}'
*/
@PostMapping("route7")
public String route7(Model model, @RequestBody Map<String, String> body) {
model.addAttribute("name", body.get("message"));
model.addAttribute("message", body.get("message"));
System.out.println(body);
return "hello_template";
}
}