# Spring Boot
學習資源: https://spring.io/
快速建立專案: https://start.spring.io/
## 建立 Spring Boot 開發環境
```java=
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
// @RestController 註解告訴Spring這段代碼描述了一個端點,該端點可以在web上運用。
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// hello() 我們添加的方法採用一個 value = name。 然後將此參數與單字結合。
// GetMapping("/hello") 告訴 Spring 使用我們的hello發送請求到 http://localhost:8080/hello
// @RequestParam 告訴 Spring 再請求中期望一個名稱值,但如果不存在,它將默認使用單字 World。
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
// %s 為 string
return String.format("Hello %s!", name);
}
}
```
使用以下指令來嘗試跑跑看Web
```
mvnw spring-boot:run
```
成功跑起來!!

## Springboot helloworld
demoApplication.java
```java=
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// Spring 應用啟動起來
SpringApplication.run(DemoApplication.class,args);
}
}
```
HelloController.java
```java=
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HellController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
```
成功執行的畫面

## 主程序類, 主入口類 (自動架構)
學習網站: https://www.youtube.com/watch?v=4t_xM7FefWM&list=PLmOn9nNkQxJEFsK2HVO9-WA55Z7LZ2N0S&index=8
@**SpringBootApplication**: Spring Boot 應用標住在某個類上說明這個類是Spring Boot的主配置類,SpringBoot就應該運行這個類的main方法啟動SpringBoot應用。
```java=
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
```
@SpringBootConfiguration: Spring Boot的配置類:
- 標住在某個類上,表示這是一個Spring Boot配置類。
- @Configuration: 配置類上標註這個註解。
- 配置類 ----- 配置文件,配置類也是容器中的一個組件,@Componet
@EnableAutoConfiguration: 開啟自動配置功能:
- 以前我們需要配置的東西,Spring Boot幫我們自動配置, @EnableAutoConfiguration 告訴Spring Boot開啟自動配置功能,這樣配置才會生效。
@AutoConfigurationPackage: 自動配置包
- @Import({AutoConfigurationImportSelector.class})
- Spring的底層註解@Import,給容器中導入一個組件。導入的組件由AutoConfigurationExcludeFilter.class
- 將主配置類(@SpringBootApplication標註的類)的所在包以及下面所有子包裡面所有組件掃描到Spring容器
## 建立 RESTful Web 服務
參考網頁: https://spring.io/guides/gs/rest-service/
```java=
package com.example.demo;
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("/hello") 確保 HTTP GET 請求到 /greeting 被映射到 greeting() 方法
// 也有很多種 HTTP 不同方式的請求例如: POST REQUEST..
// @PostMapping for POST 、 @RequestMapping(method=GET) for GET。
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name" , defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(),String.format(template,name));
}
}
```
好像是 8080 port有用過的關係,而網頁說的是沒有利用GetMapping映射。

在後來重開機之後,不知道為甚麼又成功跑出來了

測試服務:
網址: http://localhost:8080/greeting?name=user

因為我在 Greeting.java 建立了一個 Greeting 的函式,而這個函式主要回傳 id 以及 字串
Greeting.java
```java=
package com.example.demo;
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;
}
}
```
而我在 GreetingController.java 回傳了 Greeting 的建構子,因此我的顯示內容會像蓋房子一樣當我 RequestParam 的 name 稍微更動,而我的 id 也會因此不同。
GreetingController.java
```java=
package com.example.demo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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;
@SpringBootApplication
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
// GetMapping("/hello") 確保 HTTP GET 請求到 /greeting 被映射到 greeting() 方法
// 也有很多種 HTTP 不同方式的請求例如: POST REQUEST..
// @PostMapping for POST 、 @RequestMapping(method=GET) for GET。
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name" , defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(),String.format(template,name));
}
}
```
id 會一直增加因為會不斷新增新的 ID


## Spring Boot 調用 Python腳本運行
學習網站: https://blog.csdn.net/qq_44648936/article/details/123593075
調用 Java Runtime.getRuntime() 方法,以達到成功執行 python 的檔案。
GreetingController.java
```java=
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
@RestController
@RequestMapping("/face")
public class GreetingController {
@Autowired
private FaceService faceService;
@RequestMapping("/face")
public void face() throws IOException {
faceService.faceRecognition();
}
}
```
FaceService.java
```java=
package com.example.demo;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Service
public class FaceService {
// 前面一半是本地環境下的python的啟動文件地址, 後面一半是要執行的python腳本地址
public void faceRecognition() throws IOException {
String[] arguments = new String[] {"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\Shared\\\\Python36_64\\\\python.exe\"", "C:\\Users\\YouKlike\\Code\\Spring Boot\\main.py"};
Process process;
try {
process = Runtime.getRuntime().exec(arguments); // 執行py檔案
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
new InputStreamReader(process.getInputStream());
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
int re = process.waitFor();
System.out.println(re);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
```
連線失敗Orz

我猜應該是已經執行過了所以可能要重開機才能生效
### SpringBoot Initializer 使用向導快速創建Spring Boot應用
IDE都支持使用Spring的項目創建向導快速創建一個Spring Boot項目
### Spring Boot 配置 yaml簡介
- Spring Boot使用一個全局的配置文件,配置文件名是固定的:
- application.properties
- application.yml
配置文件的作用: 修改SpringBoot自動配置的默認值:
SpringBoot在底層都給我們自動配置好了
YMAL (YMAL Ain't Markup Language)
標記語言:
- 以前配置文件,大多都使用的是 xxx.xml文件:
- YMAL