[Java-Kit] Web Framework — Spring Boot

Tipsy (Jun)
47 min readSep 5, 2023

--

閱讀程度 : ★★★☆☆

適合族群 : 學習架站的初學者/開發者、Web框架趨勢、軟體架構模式(MVC)

※注意事項 — 前言

1. 筆者習慣稱 Spring BootSpBoot,SpBoot 也代表 超級(Super) Web 開發框架 ( Context(任務管理器)工具管理、Restful API(微服務)、內建Server,可以參考 使用簡介 2、3、4 )

2. 筆者經驗: Java 採用 MVC 架構,Golang 採用 三層式開發(PBD-L) 架構。(SpBoot Java框架,應屬 MVC架構 較為適合; Gin Golang 框架,應屬 PBD-L架構 較為適合。SpBoot 適合中小(偏小)型系統(單一功能); Gin 適合大中小型系統(產品))

3. 網路系統性介紹 SpBoot 資料甚少,因此筆者將 SpBoot 框架 (專案簡介、專案結構、SpBoot核心技術Annotations) 系統性依次介紹並方便讀者閱讀

Photo by Mak on Unsplash

● 使用簡介

  1. Spring Boot (SpBoot)SpringStutsHibernete 構成 Java 微服務Web應用程式開發套件
  • Spring (全端應用程式框架和控制反轉容器(IoC容器)框架)
  • Stuts (MVC框架)
  • Hibernete (Java — ORM套件)

1–1. SpBoot 套件意義

  • Spring 採用 Stuts MVC
  • Boot 簡化 Spring 基礎配置 (包含 ORM 套件)
  • Spring Boot 採用 Spring MVC

2. SpBoot 使用 Java 的 Annotation(標註)特性 降低 基礎配置XML 需求。Annotation(標註)特性為一種元數據形式(數據的數據),元數據(照片文件音頻標題、標籤裝置等)提供日期來源收集、轉換等方法幫助 Programming Language 上下文(Context)工具管理程式的任務行程(EX: 中斷處理)所以 SpBoot 達成 DI(依賴注入) 實現 IoC(控制反轉) 機制

3. SpBoot 透過 Annotation 實現基於 Restful API 微服務(微服務: 透過URI(標識某一網際網路資源名稱的字串)使用單一功能服務) 與實現自動配置路徑(Bean、類別、套件),以此簡化對 XML 需求

4. SpBoot 擁有 內建Server (Tomcat、Jetty等)Tomcat 屬於 Apache 基金會開發 Servlet Web容器Web容器 Web ServerAgency,負責管理HTTP協定Servlet 物件的生命週期安全管理 等。Tomcat 實現對Servlet和 JavaServer Page(JSP)的支援。

※ 注意事項

1. DI(依賴注入): OOP(物件導向程式)中,物件依賴其他物件完成實體化

2. SpBoot 學習與開發過程,開發者容易逐漸脫離物件導向、結構導向思維訓練。(因為 SpBoot 加入太多關於套件的開發約束,開發者需要另外學習其他程式語言沒有的意義)

3. 微服務: 輕量化業務邏輯層資料存取層節點的溝通訊息機制。透過業務邏輯層資料存取層 解構 Restful API,目的為擴展簡化設計服務

4. 輕量: 訊息處理設計,系統節點的溝通過程為較容易設計與擴展

● 開發 — 1 (專案架構)

筆者透過 專案架構 介紹 SpBoot 開發 Web應用程式。

  1. Stuts (MVC框架)
  • src/main/java: 撰寫 MC 程式
  • src/main/resources: 撰寫 V 程式
  • src/test/java: 撰寫單元測試(一個功能)、整合測試(一個完整連線)

2. Annotation (標註)

  • pom.xml

■ 檔案目錄 — src/main/java

此目錄的通常分類習慣。(開發者可以依照所需而分類)

  1. 應用主類/啟動類(創建時已有): Application.java (處理框架配置掃描、減少額外撰寫配置加載) (EX: DemoApplication.java (專案名+Application))
  2. controller: Web層 (頁面調度、管理。處理 http協定、接收請求(Request)與響應(Response)) (圖中 HelloWorld.java 為controller層,可以放置在啟動層)
  3. domain(又稱為 Repository): 實體層 (處理資料庫儲取的資料(持久層(JPA,SpBoot又稱為repository)資料訪問對象(DAO)資料傳輸對象(DTO))、輔助業務邏輯的協助層(POJO))
  4. service: 邏輯層 (處理業務邏輯,包含邏輯介面、邏輯實作)
  5. utils: 共用工具層 (開發時,團隊、個人經常會使用到的類class(EX: 基礎設定類別、業務適配器 (Business Adapter)))

※ 注意事項

★ 0. controller、domain、service、utils 資料夾需要與 應用主類/啟動類 建立在同一層

★ 0–1. Web層應有一個跳轉路徑類別並且內部屬性應為常數(constant),此類別可以快速 設定路徑控制

1. JPA(Java Persistence API): 它為一個標準規範 (介面API) 實現 ORM (object-relational mapping) 並且透過 Annotation (@Entity、@Table、@Column等)、XML描述物件的映射關係,最後將執行期的物件持久化至資料庫。JPA通稱持久層。JPA類別實現讀取某資料庫某資料表指定資料

2. DAO(Data Access Object): 它為一個資料庫的抽象介面並且呼叫持久層。目的為無須暴露資料庫細節並支援單一功能原則(每個類都應該有一個單一的功能,並且封裝此功能)。DAO類別實現某一功能(EX: 訂餐),功能可能需要讀取多個資料庫資料表取得功能需要的資料。

3. DTO(Data Transfer Object): 它為一個Web服務的傳輸物件並且不包含業務邏輯、只包含可序列化反序列化邏輯。目的為重新封裝傳輸資料降低服務之間的通信成本,所以通常DTO資訊內容較少。(EX: 成本是 Client 和 Server 之間的來回通信時間)

4. POJO(Plain old Java object): 它為一個單純只有私有屬性公開方法(setter、getter method) Java物件。其他物件(Object) 都基於 POJO 開始延伸。(最初 POJO 表示不遵循任何主要 Java的對象模型、框架)。筆者偏向放置在 domain 資料夾 (也可以放在 utils)

5. POJO 與 Bean

- Bean 目的: 它為一個單純封裝 Java 存取類別私有屬性的對象,它為一種獨立對象並且它不與 其他Bean 的屬性、功能交錯。此對象可以為許多 JPA、DAO、DTO、POJO 提供一個基礎序列化對象。(Bean 為 特殊的 POJO 類別)

- POJO 目的: 它為一個封裝 Java 業務邏輯 的對象,它可以自身為Bean或者成為Bean收集體 (功能複合體,它可以收集一至多個Bean,甚至也收集POJO)。例如對象可以為 JPA、DAO 提供一個資料表實體。(※它主要功能序列化(實現Serializable interface (可以不實現)),因為 Java 的 POJO 關係,所以使 SpBoot 一些標註擁有 @Bean 輔助對象序列化)

- 所有 Java Bean 都為 POJO,但是不是所有 POJO 都為 Java Bean。因為 POJO 可以擁有比 Bean 更多功能

- POJO 只能提供無參數建構子 並 只能由無參數建構子、getter、setter 訪問私有屬性

- POJO 與 Bean 有共通性: 可讀性、可重用性

6. 功能層級順序

- 資料庫: DAO > JPA

- Web 溝通: DTO

- 封裝能力: POJO(Bean收集體) > Bean

■ 檔案目錄 — src/main/resources

此目錄管理專案的前端網頁內容與表現格式、基礎配置。

  1. static: SpBoot 存放網頁的內容資源 (Javascript, css, image等)
  2. templates(模板引擎): SpBoot 構建網頁的表現格式 (EX: ThymeleafFreeMarker、Velocity、Groovy、Mustache) (SpBoot 避免使用 Jsp)
  3. application.properties: SpBoot 設定專案的初始化基礎配置,SpBoot 啟動時自動默認加載主要配置參數/初始化參數文件 (EX: Server Port、資料庫連線資訊)

※ 注意事項

1. 官方推薦 application.yml 取代 application.properties

2. 模板引擎 (templates): HTML5 的 Web模板

推薦選擇這兩個套件。

◆ 1. Thymeleaf (筆者採用)

- 可擴展性較佳 (可加入自定義功能)

- 豐富的網路教學資料

- 學習曲線較低

- 擁有不錯的IDE支持

◆ 2. Freemarker

- 擁有網路教學資料 (較零散)

- 因為語法較乾淨,學習曲線較低

- 擁有不錯的IDE支持

■ 檔案目錄 — src/test/java

此目錄管理專案的測試程式。

※由於此篇主要講解 SpBoot專案架構 SpBoot Annotation,未來或許會寫一篇介紹 SpBoot 如何測試程式。

■ pom.xml (專案依賴)

為了方便開發者對照,底下為 JDK1.7版 SpBoot 的 完整 pom.xml。

◆ 筆者載入初始依賴套件

  • spring-boot-starter-thymeleaf: HTML模板
  • spring-boot-starter-web: RESTful 應用、內建Server(EX: Tomcat)、websocket與logging服務(spring-boot-starter-tomcat所有)
  • spring-boot-devtools: 自動配置(EX:默認屬性值)、自動重啟、嵌入式 LiveReload 服務器(資源更改觸發瀏覽器刷新)、全域設定(spring-boot-devtools.properties)、HTTP遠程調試
  • spring-boot-starter-test: 單元測試 (mock功能)
  • lombok: 省略常用方法的語法糖 (EX: getter、setter)

<?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>3.1.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>

◆ pom.xml — 介紹

  1. pom 全名為 Project Object Model (專案物件模型),它主要管理專案的任務依賴(俗稱:專案依賴)、plugin配置
  2. pom 主要為 Maven (自動化建構工具) 必要文件。(Maven 為 Apache 專案管理 與 自動建構工具)
  3. SpBoot 透過 pom.xmlAnnotation 簡化基礎配置並降低對 XML 需求。

◆ pom.xml — Tag (又稱 Task 任務) 講解

  1. Maven 工具
  • modelVersion: Maven — 版本

2. Project 專案

  • parent: 專案 — 父專案
  • version: 專案 — 版本
  • name: 專案 — 名稱
  • description: 專案 — 描述 (細步描述 package 意義)
  • properties: 專案 — 其他參數設定 (EX: JDK版本)
  • dependencies: 專案 — 依賴套件
  • build: 專案 — 建構方式

3. Package 套件

  • groupId: 專案 package — 所屬群體名稱
  • artifactId: 專案 package — 識別名 alias (初步描述 package 意義)

● 開發 — 2 (Annotations)

筆者分類 Annotation(標註) 功能並介紹 SpBoot 核心技術。

SpBoot 使用 Annotation(標註) 管理常見Web應用,比如: 路徑配置物件的生命週期Context任務管理器(EX: 任務中斷處理、AOP等)、MVC框架設計物件導向依賴設計(DI、IoC)。

※SpBoot 透過 Annotations (大多為介面(介面與抽象有關)) 使 變數、DI 達成全域溝通,如同 Golang Channel。

■ 配置

◆ @Configuration

  1. 標註對象: 類別
  2. 特性 (※底下標註當下介紹的標註 (EX: @Configuration)後面依此類推)
  • 標註幫助 SpBoot 設定 基礎配置 (EX: 基礎類別、Bean、方法)
  • 標註為 Spring 的標註
  • 標註通常應用 Context 管理、IoC容器 (EX: Service、其他元件)
  • 標註對象可以包含一個 or 多個 Bean
  • 標註對象不能為實例對象
  • 標註對象根據擁有 field、Method 區分不同 Configuration 意義

◆ @ComponentScan

  1. 標註對象: 類別
  2. 特性
  • 標註掃描指定套件(package) 擁有元件、Bean、Annotations 並加載至 SpBoot 的 IoC容器。
  • 標註掃描 特定package 以至於加快掃描Bean速度。(SpBoot 預設會掃描 @Compoment、@Repository、@Service、@Controller、@Configuration,所以 SpBoot 加載較慢)

◆ @EnableAutoConfiguration

  1. 標註對象: 類別
  2. 特性
  • 標註對象自動配置符合條件的 Bean 並加載至 SpBoot 的 IoC容器

◆ @SpringBootConfiguration

  1. 標註對象: 類別
  2. 特性
  • 標註為 SpBoot 的標註
  • 標註繼承 @Configuration 並將其擁有 Bean 注入 SpBoot 的 IoC 容器
  • 標註主要應用 Context 管理
  • 標註簡化 SpBoot 不同基礎配置功能(較全面) 並 可以自定義修改應用程序的屬性

◆ @SpringBootApplication (常用)

  1. 標註對象: 類別
  2. 特性
  • 包含 @ComponentScan@EnableAutoConfiguration@SpringBootConfiguration

■ MVC (MC 管理)

◆ @Component (元標註: 所有標註的基礎)

  1. 標註對象: 類別
  2. 特性
  • 標註為其它標註的元標註,標註自動偵測自定義 Bean 並實例化 Bean,再收集至 SpBoot IoC容器。目的為開發者可以隨時注入管理 Bean (EX: 生命週期(初始化、創建、銷毀))
  • 標註對象可以為 @Service、@Controller
  • 因為元標註的功能較少,開發者偏向使用元標註子類(擁有較多功能)

◆ @Repository

  1. 標註對象: 類別
  2. 特性
  • 標註對象視為持久層 (又稱 數據訪問層,EX: 資料庫)
  • SpBoot 自動創建 標註對象 並添加至 Context

◆ @Service

  1. 標註對象: 類別
  2. 特性
  • 標註對象視為邏輯層 (商業邏輯功能開發)

◆ @Bean (常用)

  1. 標註對象: 方法
  2. 特性
  • 標註在 @Configuration類別 中才能使用
  • 標註對象被實例化一次收集至 SpBoot 的 IoC容器,標註對象獲得類似 Java Bean特性(序列化) 並使用 Context 訪問此標註對象
  • [★] 標註主要使用情境: 標註對象採取回傳一個新物件 (主要功能)

■ 頁面轉換/跳轉

◆ @Controller

  1. 標註對象: 類別
  2. 特性
  • 標註繼承 @Component 並使 標註對象 成為 Controller 層
  • 標註擁有 View(視圖)解析器(輔助渲染結果) 並且可以將資料返回 指定/相對應頁面 Web Page (e.g. Jsp) (View解析器: 解析 HTML畫面,它偏向為模板(Template))

無加入 @ResponseBody

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SampleController {
@RequestMapping("/")
public String home() {
return "index.html"; // 指定頁面: localhost:/8080/inedx.html
}
}

加入 @ResponseBody (@Controller + @ResponseBody = @RestController)

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 SampleController {
@RequestMapping("/")
@ResponseBody
public String home() {
return "Hello World"; // 無指定頁面 localhost:8080/
}
}

◆ @RestController (常用)

  1. 標註對象: 類別
  2. 特性
  • 標註主要使用情境: RESTful API (Spring 4 加入)
  • 標註包含 @Controller、@ResponseBody 並且 標註可以返回 JSON格式 至 client
  • 標註被使用時,頁面單純顯示 JSON格式
  • 標註無法指定回傳頁面

◆ @ResponseBody ( Java對象 -> JSON、XML 格式) (常用)

  1. 標註對象: 方法
  2. 特性
  • 標註主要使用情境: 標註用於 @Controller方法 並且透過 異步通信(EX: Ajax) 獲取數據
  • 標註將 Java對象 轉成 JSON格式數據 並 寫入 HTTP response
  • 標註使用時,@Controller 不會使用 View解析器。標註直接將數據寫進輸出串流stream (等同直接透過 response 輸出 JSON、XML格式,HTML 頁面不會進行渲染)
  • 標註不使用時,頁面根據相對應 URL路徑 跳轉

◆ @RequestMapping (常用)

  1. 標註對象: 類別、方法
  2. 特性
  • 標註主要使用情境: RESTful API
  • 開發者一般將 長Mapping 用於類別短Mapping 用於方法
  • 標註可被替換成短Mapping (Spring 4.3 引入)
  • 標註設定 HTTP Request 指定 URL 映射至 MVC@RestController 方法
  • 標註對象為類別,此類別 所有Response 將 標註指定 URL 視為 父路徑

3. 範例

@RequestMapping(value = "/get" , method = RequestMethod.GET) (筆者習慣稱為長Mapping)

=> @GetMapping(value= "/get") (筆者習慣稱為短Mapping)

@RequestMapping(value = "/post" , method = RequestMethod.POST)

=> @PostMapping(value="/post")

@RequestMapping(value = "/put" , method = RequestMethod.PUT)

=> @PutMapping(value="/put")

@RequestMapping(value = "/delete" , method = RequestMethod.DELETE)

=> @DeleteMapping(value="/delete")

■ 網址請求

◆ @PathVariable

  1. 標註對象: 方法參數
  2. 特性
  • 標註主要使用情境: 取得URL變數值
  • 標註可搭配 @RequestMapping 存取指定資料
  • 標註對象變數值與標註所屬方法使用的URL相同,標註可省略標註的變數值。如果不同,則不可省略

◆ @RequestParam (常用)

  1. 標註對象: 方法參數
  2. 特性
  • 標註主要使用情境: 取得URL參數值(RESTfulGET、POST)
  • 標註可搭配 @RequestMapping 存取指定資料
  • 標註可搭配 Postman 並 進行驗證URL

範例1. 簡單取值

@GetMapping("/api/thing")
public String getThing(@RequestParam String id){
return "ID: " + id;
}
curl http://localhost:8080/api/thing?id=abc

ID: abc

範例2. 指定參數名稱

@PostMapping("api/foods")
public String getFood(@RequestParam("name="id") String foodId, @ReuqestParam String name){
return "ID: " + foodId + "Name: " + name;
}

範例3. 請求參數可能沒有收到 (使用required 設定,可避免錯誤)

@GetMapping("/api/foods")
public String getFood(@RquestParam("name=id" required=false) String foodId){
return "ID: " + foodId + "foodName: " + name;
}
http://localhost:8080/api/foods?id=abc

=> ID: abc

http://localhost:8080/api/foods

=> ID: null

範例4: 設定默認預設值

@GetMapping("/api/foods")
public String getFoods(@RequestParam(defaultvalue="test") String id){
return "ID: " + id;
}
http://localhost:8080/api/foods

=> ID: test

http://localhost:8080/api/foods?id=abc

=> ID: abc

範例5: 映射所有參數

@PostMapping("/api/foods")
public String updateFoods(@RequestParam Map<String, String> allParams){
return "Parameters are " + allParams.entrySet();
}
curl -X POST -F 'name=abc' -F 'id=123' http://localhost:8080/api/foos

Parameters are {[name=abc], [id=123]}

範例6: 映射多值參數

@GetMapping("/api/foods")
public String getFood(@RequestParam List<String> id){
return "IDs are " + id;
}
http://localhost:8080/api/foods?id=1,2,3

=> IDs are [1,2,3]

https://localhost:8080/api/foods?id=1&id=2

=> IDs are [1,2]

◆ @Requestbody ( JSON格式 -> Java對象 ) (常用)

  1. 標註對象: 方法參數
  2. 特性
  • 標註主要使用情境: 請求的 JSON格式 並將它轉換成 Java對象 (通常用於 POST)
  • 標註最多接收一個 Request,但是不限定其Request擁有的參數數量@RequestParam可以接收多個 Request
  • 標註 與 @RequestParam 搭配使用時,標註接收 Request 數據,@RequestParam 接收 key-value 的參數

※如果參數放在請求application/json傳入後台,後台透過 @Requestbody 接收; 如果參數不放在請求,後台透過 @RequestParam 接收

◆ @RequestAttribute

  1. 標註對象: 方法參數
  2. 特性
  • 標註主要使用情境 — 1: 取得 Filter(過濾器)、Interceptor(攔截器) 建立預先存在的Request屬性 (通常為 已經實例化父類別屬性)
  • 標註主要使用情境 — 2: 用於 Server 訪問一段時間並在同一HTTP Request 的對象
  • 標註不適用搭配 Postmancurl (當下傳遞新 Request)

■ 提供實例化物件 — @ModelAttribute (跟 @Bean 思維有些相像)

  1. 標註對象: 方法、方法參數
  2. 特性
  • 標註主要使用情境: 在執行類別其他方法、方法參數之前,標註對象提前執行
  • 標註在方法此方法比其它方法先執行 並且 方法結果 存放至 Model
  • 標註在方法,標註經常用於公共屬性、資料 (EX: 下拉列表的預設狀態、HTML表單渲染的命令對象)
  • 標註在方法參數,標註可以接收任何參數類型 (EX: Model、Map、String、一般類別等)
  • 標註在方法參數,開發者可以直接方法參數取值 (因為標註實例化方法參數加入 Model,所以 Model 可以找到此方法參數)
  • 標註沒有使用時,開發者可能取不到方法參數
  • 標註在方法參數,其作法類似 Golang Channel 傳過來已實例化對象

※ 注意事項

實例化對象,使SpBoot 的 Model 擁有此對象的物件之後的方法可以直接拿取此對象的物件

■ Spring 中心思想 ( DI(依賴注入) 實現 IoC(控制反轉) )

◆ @Autowired (Spring 2.5 提供) (常用)

  1. 標註對象: 屬性(Field)、方法(Method — setter)、建構子(Constructor)、方法參數
  2. 特性
  • 標註主要使用情境:標註對象進行 注入(injection) 並 自動裝配內容
  • 標註無法判斷使用哪個 Bean 時,SpBoot 透過 @Qualifier 選擇相對應的 Bean
  • 標註無法找到適當 Bean 時,標註屬性 required = true,SpBoot 執行時可能會出現 NoSuchBeanDefinitionExceptionrequired = false,SpBoot 執行時不會顯示 Exception (預設為 true)
  • 標註對象屬性(Field): 可省略使用 UserDAO setter 方法取得過程,直接取得 setter 的值 (標註類似簡化序列化做法) (常用)
  • 標註對象方法(Method — setter): 自動找尋匹配方法參數 Bean 注入至標註對象中的 Bean
  • 標註對象建構子(Constructor): 直接將建構子注入 (較少看過)

■ Others (輔助開發 Bean、Logger、AOP)

◆ @Before

  1. 標註對象: 方法
  2. 特性
  • 標註通常用於 AOP(切面導向程式設計) 的流程控管
  • 標註通常在 PointCut 之前處理

◆ @Data

  1. 標註對象: 類別
  2. 特性
  • 標註對象可以生成讀寫方法equals、hashCode()、toString() 並且標註對象可以成為 POJO (因為自動生成 POJO 樣板)

◆ @Getter、@Setter

  1. 標註對象: 類別
  2. 特性
  • 標註對象自動為標註對象的屬性生成讀寫方法

◆ @toString

  1. 標註對象: 類別
  2. 特性
  • 標註對象自動生成 toString() 方法

◆ @Slf4j (Simple Logging Facade for Java)

  1. 標註對象: 類別
  2. 特性
  • Simple Logging Facade for Java 為日誌框架(java.util.logging、logback、log4j)的應用介面
  • 標註對象自動生成一個 log4j型態 的 log屬性的日誌對象
  • 標註對象提供 TRACE, DEBUG, INFO, WARN, ERROR 五種紀錄等級

◆ @Log4j (Apache Log4j)

  1. 標註對象: 類別
  2. 特性
  • Apache Log4j 為一個非常古老的日誌框架並且受到歡迎
  • 標註對象自動生成一個 log4j型態 的 log屬性的日誌對象
  • 標註對象提供 TRACE, DEBUG, INFO, WARN, ERROR 及 FATAL 六種紀錄等級

◆ @Value

  1. 標註對象: 類別屬性
  2. 特性
  • 標註對象將外部資源注入,注入方法分成兩種不通過配置文件通過配置文件(文件資源、URL)
  • 注入對象可以為字串操作系統屬性表達式結果其他Bean屬性文件資源URL

範例: Spring Boot系列四 Spring @Value 属性注入使用总结一

// 注入 - 字串
@value("normal")
private String normal;

// 注入 - 操作系統屬性
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName;

// 注入 - 表達式
@Value("#{T(java.lang.Math).random() * 1000.0}")
private double randNum;

// 注入 - 其他屬性
@Value("#{BeanInj.another}")
private String fromAnotherBean;

// 注入 - 文件資源
@Value("classpath:com/hry/spring/configInject/config.txt")
private Resource resourceFile;

// 注入 - URL
@Value("http://www.baidu.com")
private Resource testUrl;
@Component
public class BeanInj{
@Value("其他Bean屬性")
private String another;
}
// 文件: com/hry/spring/configInject/config.txt

test configuration file

◆ @Required (Spring 5.1 版已經棄用)

  1. 標註對象: 類別方法
  2. 特性
  • 標註對象為 setter,Bean屬性必須設定在 XML (e.g. Beans.xml(筆者定義)),否則會拋出 BeanInitializationException
  • Spring 5.1 版已經棄用支援使用建構子注入 或者 自訂 InitializingBean 實作

範例: Spring @Required Annotation

  • Bean

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Required;

public class Student {
private Integer age;
private String name;

@Required
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}

@Required
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
  • Main
package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

Student student = (Student) context.getBean("student");
System.out.println("Name : " + student.getName() );
System.out.println("Age : " + student.getAge() );
}
}

// 輸出結果
Name : Zara
Age : 11
  • Beans.xml (開發者自訂)
<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context = "http://www.springframework.org/schema/context"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/>

<!-- Definition for student bean -->
<bean id = "student" class = "com.tutorialspoint.Student">
<property name = "name" value = "Zara" />
<property name = "age" value = "11"/>
</bean>

</beans>

■ 資料庫類

◆ @Entity

  1. 標註對象: 類別、枚舉的介面 (e.g. Serializable)
  2. 特性
  • 標註對象宣告持久層,並指定標註對象為一個實體。目的為輔助業務服務 (實體為資料庫的表,實體的每個實例為表中的一行)
  • 標註對象為儲存至資料庫的POJO
  • Spring容器透過實體管理關聯式資料庫的持久性並自動儲存資料庫資料
  • 使用 JPA 時,建議使用標註綁定類別並建立一個主鍵欄位 @id
  • 開發者可以使用實體表示細顆粒度的持久對象 並且建立單一業務流程業務實體或者為多個操作進行建模

◆ @Table

  1. 標註對象: 類別
  2. 特性
  • 標註對象被指定為資料庫的資料表,開發者可以自由選擇使用此標註,如果不使用,則需要使用 @Entity 表示資料表名稱
  • 開發者不使用 @TableHibernate 預設會使用 @Entity 名稱視為表名

範例

// 第一種 (允許編寫 HQL 或 JPQL 時存取與實體同名的表。)
@Entity(name = "someThing") => this name will be used to name the Entity
@Table(name = "someThing") => this name will be used to name a table in DB

// 第二種 (編寫查詢需要使用 @Entity 設定的名稱 並且 應用 @Table 名稱用於資料表)
// HQL 中,someThing 將引用資料表 otherThing
@Entity(name = "someThing")
@Table(name = "otherThing")

// 第三種 (一般常用),可以使用 SQL、HQL、JPQL
@Entity
@Table(name="someThing")

// 第四種,可以使用 SQL
@Entity(name="")

◆ @Id

  1. 標註對象: 類別屬性
  2. 特性
  • 標註對象被指定為實體的主鍵

◆ @GeneratedValue

  1. 標註對象: 類別屬性
  2. 特性
  • 標註時常與 @Id 搭配使用
  • 標註對象可以指定主鍵產生策略。(TABLE、SEQUENCE、IDENTITY、AUTO)
- TABLE: 使用一個特定的資料庫的資料表保存主鍵

- SEQUENCE: 根據底層資料庫的序列生成主鍵 (資料庫需要支持序列)

- IDENTITY: 主鍵由資料庫自動生成 (主要為自動增長型)

- AUTO: 主鍵由程式開發者控制 (GeneratedValue 的預設)

範例: 理解JPA注解@GeneratedValue

// IDENTITY
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

// AUTO
@Id
@GeneratedValue(strategy = GenerationType.AUTO)

◆ @Column

  1. 標註對象: 類別屬性
  2. 特性
  • 標註對象被指定為資料表的欄位並且標註的Name屬性為表的列名稱

◆ 事務(交易) REQUIRES_NEW & REQUIRED

  1. 標註對象: 類別方法
  2. 特性
  • REQUIRES_NEW: 創建一個新事務(交易),如果當前事務存在,則會掛起當前事務內部不受外層調用者影響但會影響外層的事務
  • REQUIRED: 支持當前事務,如果不存在,則創建一個新事務內部受外層調用者影響,也會影響外層的事務

[實務上]

  • REQUIRES_NEW: 少數情境使用。其中一個事務與其他事務無關。假設其他事務異常,此事務不會被影響與回滾
  • REQUIRED: 多數情境使用。一系列事務保證全部成功,全部失敗。假設其他事務異常,此事務也會被影響與回滾

3. 參考

■ Java 與 關聯式資料庫 — 操作關係

  1. SQL(Structured Query Language): 透過 SQL 提供關聯式資料庫(實體)操作分類(DML、DDL、DCL、TCL、DQL)並且管理關聯式資料庫的儲取查詢
  2. HQL(Hibernate Query Language): 透過 HQL 提供 Hibernate (關聯式資料庫的物件導向式ORM方案) 模擬 SQL 並且處理對象為 JPA實體實體屬性。 (※ HQL: 物件關係查詢語言)
  3. JPQL (Java Persistence Query Language): 透過 JPQL 提供 Java 模擬 SQL 並且 JPQL 基於 HQL 創造,不直接影響關聯資料庫。
  4. Spring Data JPA — @Query: 可以使用 JPQL,JPA默認使用 Hibernate (HQL)

◆ 三者差異

  • HQL 允許 select 將 table 替換成 類別屬性類別名稱
  • JPQL 允許 select 將 table 替換成 類別屬性類別名稱並支持 inner joinouter join 與 支持刪、查、改操作

◆ JPA & Spring Data JPA

  1. JPA(Java Persistence API): 它為 Java 提供物件與關聯式資料庫之間持久化、讀取和管理資料的標準。其中定義一組概念與API,使開發者能處理應用程式的關聯式資料。
  2. Spring Data JPA: 它為 Spring 採用 JPA概念實作而成的串接資料庫樣板。它優化使用 JPA 原則最大程度減少開發程式碼的數量。

■ Spring — byName、byType

開發者可以自訂 xml 為 Beans.xml,會比較好分類。

  1. byName: 找尋 xml bean 節點 <bean id="">,如果找不到會丟出 NullPointerException。
  2. byType: 找尋 xml bean 節點 <bean class="">,如果找不到會丟出 NullPointerException。bean 透過 <bean autowire="byType"> 使用開發者需要保證Spring容器中同一類型的對象只能唯一
  3. @Quailfier: 輔助 @Autowired (根據 byName 自動裝配),標註不能單純使用。標註對象為類別屬性

※Spring 預設會找尋 byType (e.g. @Autowired),其中應用 <bean class=""> 自動裝配。

範例: Spring中byName和byType的区别

// Cat 類別
public class Cat{
public void say(){
System.out.println("This is Cat class");
}
}

// Dog 類別
public class Dog{
public void say(){
System.out.println("This is Dog class");
}
}

// People 類別
public class People{

@Autowired(required=false)
@Qualifier(value="cat2")
private Cat cat;

@Autowired(required=false)
@Qualifier(value="dog2")
private Dog dog;

private String name;

public Cat getCat(){
var tmpCat = new Cat();
return tmpCat;
}

public Dog getDog(){
var tmpDog = new Dog();
return tmpDog;
}

public String getName(){
return this.name;
}
}

// 輸出結果
this is Cat class
this is Dog class
<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context = "http://www.springframework.org/schema/context"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/> <!--開啟屬性標註支持-->

<!-- Definition for student bean -->
<bean id = "cat" class="com.hello.pojo.Cat"/>
<bean id = "cat2" class="com.hello.pojo.Cat"/>
<bean id = "dog" class="com.hello.pojo.Dog"/>
<bean id = "dog2" class="com.hello.pojo.Dog"/>

<!--Bean & Bean屬性-->
<bean id = "people" class="com.hello.pojo.People" autowire="byName">
<property name="cat" ref="cat"/>
<porperty name="dog" ref="dog"/>
<property name="name" value="wsh"/>
</bean>

</beans>

◆ @Resource

  1. 標註對象: 類別屬性、類別方法
  2. 特性
  • 標註可以透過 byName、byType 注入,使用順序: byName > byType。如果找不到 byName,才會使用 byType。
  • 標註功能如同 @Autowired,@Autowired 使用 byType 注入。
  • 標註 與 @Autowired 可以用於 setter 方法

範例: Spring中 javax.annotation.Resource注解用法

// 屬性 - 字串
@Resource(name="userDao")
private UserDao userDao;

// 方法 - setter
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}

■ Spring Boot — 測試 (注意事項)

  1. 單元測試: 在 Junit測試時,透過 @RunWith(SpringRunner.class) 標註啟用 spring boot 功能@Autowire,例如@MockBean等。一般測試對象為 Service(業務邏輯)
  2. 整合測試: 在 Junit測試時,透過 @SpringBootTest 標註載入完整的應用程式 Context(任務管理器) 並進行端到端的整合測試。一般測試對象為 DAO(資料持久層 (與資料庫串接))
  3. @Test 標註對象類別方法,目的為開發者撰寫測試案例(test case)。

■ Spring Boot — AOP (注意事項)

  1. AOP (特性導向程式設計): 業務流程的某步驟分析多個業務邏輯的觀點,觀點分離業務主體的核心關注點,藉此提高程式碼的模組化
  2. 範例: 對所有以set*開頭的方法添加Server紀錄檔,以泛型形式記錄。目的為降低程式碼的核心功能負擔(e.g. 紀錄log功能不是核心功能),同時不降低業務邏輯的可讀性。 (※紀錄log功能融入至業務流程)

● 結論/心得

  1. SpBoot 適合建立微服務(單一服務),但是它不適合中大型專案。
  2. SpBoot 核心 Annotation 為一種全域機制,它是一個非常先進技術。如果開發者有結構導向(EX: Golang)開發經驗,開發者可以知道 Annotation 完成 Golang 的 Channel 曾經想做的開發方向 (全域 Channel ),不過 全域 Channel可能難以系統化功能設計。
  3. SpBoot 透過 Annotation 完成 DI 實現 IoC,如同 Golang 開發的 Taskfile (自動化建構工具),其目的為開發者需要撰寫 task內容 (Java Code) 並使用 序列化 完成任務(task)其過程宛如將 task內容 注入至 task,然後呼叫此任務task
  4. SpBoot 核心技術 Annotation 創造許多有趣詞彙提供開發者在其他語言稱呼相對應意義
  5. ▲ 筆者大致已完成此篇 SpBoot 介紹,介紹還須打磨其內容(格式化)並加入圖片程式碼幫助開發者了解其意義 (※之後補充)

● 參考資料 — 1 (J.J.’s Blogs)

1. Spring Boot 教學

● 參考資料 — 2 (cailiwu)

1. 站在Web前端人員角度,學習 Spring Boot 後端開發

2. Day 11 — Spring Boot 模版引擎 x Thymeleaf

● 參考資料 — 3 (模板)

1. [推薦] FreeMarker vs Groovy vs Mustache vs Thymeleaf

● 參考資料 — 4 (Annotations (標註、註解))

1. [極推薦] 2023 年最常用的 10 個 Spring Boot 註解

2. javatpoint — Spring Boot Annotations

3. stackOverflow — 如何使用postman或feign客戶端在Spring boot中設置@RequestAttribute的值

4. 墨天輪 — SpringMVC注解

5. [Day 11] — @GetMapping 和 @RequestMapping 的比較及使用

6. Spring Boot教程(9) — Model的用法

7. [推薦] [SpringMVC]@ModelAttribute 2種用法與解釋( @ModelAttribute — Used on Method and Parameter )

8. [推薦]【Spring】@ModelAttribute三种使用场景

9. [推薦 — @RequestAttribute 範例] Spring MVC — Accessing pre-existing request attributes using @RequestAttribute

10. [@ComponentScan 範例] Spring系列(三):@ComponentScan注解用法介绍

11. [@ComponentScan 範例] Spring Boot注解之@ComponentScan用法和实现原理

12. [@ComponentScan 介紹] Spring 之 @Component 和 @ComponentScan 注解用法介绍和注意事项

13. [@ComponentScan 範例] Spring注解 — — 使用@ComponentScan自动扫描组件

14. [推薦 — DI、IoC] Spring 註解 之 @Autowired

15. [推薦 — @RequestBody] @RequestBody是干嘛的,作用是甚麼?

16. [推薦 — @RequestBody & @RequestParam 比較] @RequestBody的使用

17. [推薦 — @Bean 範例] 就是要让你彻底学会 @Bean 注解

18. Spring系列第十九講@Configuration和@Bean註解詳解

19. [推薦 — Java 基礎標註 Annotations] Day 08 — Spring Boot 常用註釋(上)

20. [推薦 — Beans 範例] Spring 系列之 Bean 注解用法介绍

21. [Component 範例] Spring @Component 註解

22. [大推薦 — @PathVariable 範例] @PathVariable注解的用法和作用(Demo详解)

23. [大推薦 — @RequestAttribute 範例] 从原理层面掌握@RequestAttribute、@SessionAttribute的使用【享学Spring MVC】

24. [大推薦 — SpBoot 回應與接收 JSON] 回應與接收 JSON

25. [推薦 — 注入方式] Springboot中一些註解的作用 (@Autowired、@Inject、@Resource)

26. Spring基于@Configuration的类配置的用法

27. [推薦 — @ModelAttribute 與 HTML 用法] TPIU — Thymeleaf & 資料傳遞

28. Spring @RequestParam注解

29. SpringBoot最常用的36个注解

● 參考資料 — 5 (Others (AOP、DataBase、Log))

1. [AOP] spring boot AOP @Before @After 最简单的切面

2. [AOP] wiki — 特性導向程式設計 (將交叉切入關注點與作為業務主體的核心關注點進行分離,以提高程式碼的模組化程度)

3. iThome — 過路劫財 (AOP)

4. [推薦 — AOP] [Day 27] 遠征 Kotlin × Spring Boot 介紹 Spring AOP 機制

5. Azure — 什麼是 Java Spring Boot?

6. wiki — Apache Tomcat

7. Openhome.CC — 何謂容器

8. [推薦 JPA、Hibernate 圖解] [Day 13] — 認識Spring Data JPA, JPA, Hibernate

9. Spring Boot EP 10:透過Spring Data JPA與Hibernate讀取(select)資料庫

10. wiki — 資料訪問對象(DAO)

11. wiki — 單一功能原則

12. [推薦 — POJO 解釋] 一次搞懂POJO、PO、DTO、VO、BO

13. wiki — Plain old Java object(POJO)

14. wiki — 資料傳輸對象(DTO)

15. wiki — 網頁模板

16. Java Maven的pom.xml是什麼?

17. [推薦] Spring Boot 官方

18. [推薦 — 何謂是 Beans] wiki — JavaBeans

19. [大推薦 — Spring IOC] Spring Boot 零基礎入門學習筆記 — IoC

20. Spring Boot 初學用法介紹

21. Spring MVC的简单用法

22. [推薦 Spring Boot 如何發布 可執行檔] SpringBoot發佈將靜態資源及設定抽離

23. SpringBoot — 探究Spring Boot應用是如何通過 java -jar 啟動

24. 應用程式伺服器 : JBoss簡介

25. Spring Boot Starters是什么?

26. [推薦 SpBoot 返回對象都為 ModelAndView] Spring MVC视图和视图解析器

27. [推薦 — SpBoot 官方 DOC (最良心,雖然不好看)] Web MVC framework

28. [推薦] 中文群 SpBoot 資源

29. [大推薦 SpBoot學習教材] openhome — SpBoot

30. POJO 與 Java Bean

31. 了解 Spring Boot @Autowired 註解

32. caterpillar — 11.1 常數設置與列舉型態

33. springboot使用@data註解,減少不必要程式碼

34. [詳細] Spring Boot系列四 Spring @Value 属性注入使用总结一

35. 理解JPA注解@GeneratedValue

36. [不錯] Spring @Required Annotation

37. Spring @Required Annotation with Example

38. Spring @Required Annotation deprecated?

● 參考資料 — 5.1 (byName、byType)

1. Spring 註解 javax.annotation.Resource和@Autowired

2. Spring Autowiring byName & byType Example

3. Spring Bean Autowire byName, byType, constructor and default Example

● 參考資料 — 6 (JPA — SQL、HQL、JPQL)

1. SQL、HQL、JPQL 到底有什么区别

2. JPQL & HQL & Spring Data JPA @Query | 最全知识清单

--

--

Tipsy (Jun)

Chill & Cozy Coding City ☕️(Software Engineer , Decentralized Engineer(Blockchain) ) | Research systematic field for 5 years.| Coding Tour