iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
Software Development

Spring Boot 零基礎入門系列 第 28

Spring Boot 零基礎入門 (28) - MVC 架構模式 - Controller-Service-Dao 三層式架構

  • 分享至 

  • xImage
  •  

賀!此系列文榮獲 2023 iThome 鐵人賽《優選》獎項,正在規劃出書中,感謝大家的支持🙏,同名課程「Java 工程師必備!Spring Boot 零基礎入門」也已在 Hahow 平台上架

哈囉大家好,我是古古

在上兩篇文章中,我們有介紹了 Spring JDBC 的兩個核心用法 update()query(),因此大家就可以透過這兩個方法,在 Spring Boot 中執行想要執行的 sql 語法了!

而在介紹完 Spring JDBC 的核心用法之後,接著這篇文章要介紹的,是軟體工程中一個很重要的概念,即是「MVC 架構模式」

什麼是軟體工程?


在介紹什麼是「MVC 架構模式」之前,我們可以先來看一下,「軟體工程」到底是個什麼樣的概念

所謂的軟體工程,即是「在面對一個 大型的系統 時,工程師們要 如何分工合作,一起去解決問題?」,在這句話裡面有兩個重點,分別是「大型的系統」和「如何分工合作」

所以簡單的說的話,當你今天要寫的是一個超過一兩千行的程式,並且你們的團隊中,是有好幾位工程師一起分工合作,在這種情況下,就會開始需要去注重 「軟體工程」

補充:當然小型的系統也可以注重軟體工程,不過效益相對不會那麼大

什麼是 MVC 架構模式?


大概了解了軟體工程的概念之後,我們可以先來看一下「MVC 架構模式」的概念是什麼,然後再接著來介紹,要如何在 Spring Boot 中去套用 MVC 架構模式的概念

所謂的「MVC 架構模式」,他是軟體工程中的一種軟體架構,而 MVC 架構模式的用途,就是將一個系統,去拆分成「Model、View、Controller」三個部分,並且讓每一個部分都各自負責不同的功能

https://ithelp.ithome.com.tw/upload/images/20231012/20151036OzosspWsDk.png

上面這一張圖看起來可能有點抽象,不過其實 MVC 架構模式的概念很簡單,他就只是「想要去把我們所寫的程式分個類」而已

譬如說你今天寫的這段程式,他可能是屬於 Model 的部分,又或是你寫的這段程式,他是被分類到 Controller 的部分,僅此而已,MVC 架構模式並不會添加什麼新功能到你的程式裡面

而 MVC 架構模式之所以被稱為是 MVC,原因就是取自於 Model-View-Controller 這三種分類的第一個字母的縮寫,因此這種架構模式,才被稱為是 MVC 架構模式

Model

在 MVC 架構模式中,Model 所負責的,是「實作業務邏輯,並且處理數據」

也因為 Model 是負責處理數據,因此 Model 會需要去跟資料庫做溝通,將這些數據的改動給儲存起來

因此 Model 算是在 MVC 的架構中,最重要的一個部分,因為他實際上就是負責去處理數據,所以我們都會將核心的業務邏輯,寫在 Model 這個部分裡面

Controller

在 MVC 架構模式中,Controller 所負責的,是「轉發 Http request」

所以簡單的說的話,當 Controller 收到來自前端的 Http request 之後,Controller 就會負責將這些 request,去轉發給 Model,讓 Model 去處理後續的操作

View

在 MVC 架構模式中,View 所負責的,是「使用 Html 的模板去呈現數據」

不過因為近幾年提倡「前後端分離」的關係,所以版面設計就都會交給前端處理,因此在後端這裡,就不需要處理 Html 的版面部分,改成是使用 Json 格式來傳遞數據給前端,因此 View 這部分,相對來說就變得越來越不重要

MVC 架構模式的優點


當我們使用了 MVC 架構模式,將我們所寫的後端程式,去區分成 Model-View-Controller 這三個部分的話,可以得到以下幾個好處:

  1. 職責分離,更容易維護程式
  2. 使程式結構更直覺,有利於團隊分工
  3. 可重複使用寫好的程式

在 Spring Boot 中套用 MVC 架構模式


了解了 MVC 架構模式的運作方式和優點之後,接著我們可以來看一下,要如何在 Spring Boot 中,去套用這個 MVC 架構模式的概念

補充:MVC 架構模式其實是一個比較抽象的概念,具體要怎麼實作,就會依照不同的框架,而有不同寫法

在 Spring Boot 裡面,我們會將 MVC的架構模式,去轉化成是 「Controller-Service-Dao 的三層式架構」 來實作

因此大家以後只要在 Spring Boot 中看到「Controller-Service-Dao」這種三層式架構時,就可以知道他是套用了 MVC 的架構模式在設計了

Controller-Service-Dao 三層式架構


在 Controller-Service-Dao 的三層式架構中,其實就是將 Spring Boot 程式,去分成了Controller、Service、以及 Dao 這三層來管理,讓每一層都去負責不同的功能

像是在下圖中,就呈現了 Controller、Service、Dao 這三層架構之間的關係,以及他們個別負責的功能

https://ithelp.ithome.com.tw/upload/images/20231013/201510363nDRQv54rp.png

Controller 層

Controller 層的用途,是負責去 「接收前端傳過來的 Http request,並且去驗證請求參數」

所以像是我們在 Spring MVC 中所介紹的那些註解 @RequestMapping@RequestParam...等等,舉凡是和「前端」進行溝通的部分,就通通會放在 Controller 層裡面

Service 層

而當 Controller 層接收到前端傳過來的 Http request、並且對其驗證之後,這時候Controller 就會去 call Service層,讓 Service 負責去接手後續的處理

Service 層的用途,主要是負責 「商業邏輯的處理」,而 Service 層在處理商業邏輯的過程中,Service 層會再去 call Dao這一層

Dao 層

Dao 這一層所負責的功能,就是 「專門去和資料庫進行溝通的」,所以換句話說的話,Dao 這一層,就會透過 sql 語法,去操作資料庫,進而去查詢/修改資料庫中的數據

因此我們在 Spring JDBC 中所介紹的所有用法,舉凡只要是和「資料庫」溝通的部分,就通通是會放在 Dao 層裡面

補充:Dao 層是 Data access object 的縮寫

小結

所以透過上面的 Controller-Service-Dao 的三層式架構的設計,就可以將 Spring Boot 中的程式,依照不同的功能,為他放在不同的層級中

因此我們之後就可以去透過 Controller-Service-Dao 的三層式架構,更好的去管理和維護 Spring Boot 的程式了!

實際使用 Controller-Service-Dao 三層式架構


在使用 Controller-Service-Dao 三層式架構之前...

在我們以前沒有 Controller-Service-Dao 三層式架構的概念時,我們所寫出來的 Spring Boot 程式會是下面這樣的

即是將取得前端參數的 @GetMapping 功能,以及去和資料庫溝通的 namedParameterJdbcTemplate 功能,全部放在同一個 class 中去實作,這樣子雖然同樣可以完成功能,但是在後續的管理和維護上,就會比較吃力

https://ithelp.ithome.com.tw/upload/images/20231013/20151036qKan10mdSf.png

使用 Controller-Service-Dao 三層式架構之後!

而當我們將上面的程式,改成是使用 Controller-Service-Dao 的三層式架構的話,就可變成下面這樣的寫法

https://ithelp.ithome.com.tw/upload/images/20231013/20151036u5k4okZ5bQ.png

當我們套用了 Controller-Service-Dao 的三層式架構之後,會將上面的程式,去拆分成是「3 個 class」來負責

Controller 層:StudentController

https://ithelp.ithome.com.tw/upload/images/20231013/201510367ANBMXq5DU.png

首先是第一個 class 是 StudentController,因為這個 class 的名字是以 Controller 為結尾,因此他是代表 Controller 層,負責去處理和前端的溝通

在 StudentController 裡面,我們只保留 @GetMapping@PathVariable 的部分,使用 Spring MVC 的功能,去和前端溝通,取得前端傳過來的參數 studentId

而取得到 studentId 這個參數的值之後,StudentController 就會去 call StudentService 的 getById() 方法,後續交由 Service 層來處理

Service 層:StudentService

https://ithelp.ithome.com.tw/upload/images/20231013/20151036GZBfBHjEVf.png

而第二個 class 則是 StudentService,同樣的道理,因為這個 class 的名字是以 Service 做為結尾,因此他是代表 Service 層,負責進行商業邏輯的處理

在 StudentService 裡面,我們新增了一個 getById() 的方法,而這個方法的用途,就是去根據 student 的 id,去查詢這一筆 student 的數據出來

因為目前這個例子比較簡單,所以我們沒有太複雜的商業邏輯要做,只需要去資料庫中,查詢這一筆 student 的數據出來就可以了,因此在 StudentService 這裡,只需要直接去 call StudentDao 的 getById() 方法,後續交由 Dao 層去和資料庫溝通

Dao 層:StudentDao

https://ithelp.ithome.com.tw/upload/images/20231013/20151036KJv0y1vEZv.png

最後第三個 class 是 StudentDao,同樣的道理,因為這個 class 的名字是以 Dao 做為結尾,因此他是代表 Dao 層,負責處理和資料庫的溝通

也因為 StudentDao 是 Dao 層,負責處理和資料庫的溝通,因此我們在這裡就會直接去透過 namedParameterJdbcTemplate 的寫法,使用 Spring JDBC 的功能,從資料庫中查詢一筆數據出來

小結

所以透過上面這樣子的改寫,我們將原本的程式,由 1 個 class 拆分成 3 個 class,分別透過 StudentController、StudentService、StudentDao 這三個 class,各自去完成 Controller 層、Service 層、以及 Dao 層的功能

因此後續在維護上,假設我們想修改「查詢的 sql 語法」,那我們就只要去修改 StudentDao 中的程式即可(因為是由 Dao 層管理和資料庫的溝通)

又或是我們想要修改的是「前端的請求參數」,那我們就只要去修改 StudentController 中的程式即可(因為是由 Controller 層管理和前端的溝通)

所以透過 Controller-Service-Dao 的三層式架構,就可以讓我們的 Spring Boot 程式更好管理,以利後續的維護了

https://ithelp.ithome.com.tw/upload/images/20231013/20151036D1vY7ID3XX.png

使用 Controller-Service-Dao 三層式架構的注意事項


在使用 Controller-Service-Dao 的三層式架構時,有幾個注意事項需要遵守

1. 透過 Class 名字結尾,表示這是哪一層

像是上面的例子,StudentController 這個 class,因為他是以 Controller 做為結尾,因此在默契上,我們就會將他區分為 Controller 層

又或是 StudentService 這個 class,因為他是以 Service 做為結尾,所以我們就會將他區分為 Service 層

因此大家之後在使用 Controller-Service-Dao 的三層式架構時,就可以透過這個 class 名字的結尾,快速的知道這個 class 是屬於哪一層,進而知道他所負責的功能是「和前端溝通」、「處理商業邏輯」、還是「和資料庫溝通」了

2. 將 Controller、Service、Dao,全部變成 Bean

在設計上,我們通常會將 Controller、Service、Dao 這些 class,全部變成是 Spring 容器所管理的 Bean,然後需要使用的時候,就透過 @Autowired 的方式,去注入想要使用的 Bean 進來

譬如說我們會在 StudentController 裡面,使用 @Autowired 去注入 StudentService,這樣就可以在 StudentController 裡面,去 call StudentService 的方法來使用

https://ithelp.ithome.com.tw/upload/images/20231013/20151036NY5mKhrIh0.png

同樣的道理,假設 StudentService 想要使用 StudentDao 的話,那就一樣是可以使用 @Autowired 去注入 StudentDao,進而就可以使用 StudentDao 中的方法,去取得資料庫中的數據了

https://ithelp.ithome.com.tw/upload/images/20231013/20151036zVXwfV1by6.png

所以換句話說的話,其實我們在 Day 5~Day 10 所介紹的 Spring IoC 的部分,就都是為了這裡在鋪陳!!!

為了要能夠在 Spring Boot 中運用 Controller-Service-Dao 的三層式架構,所以我們必須要先有 Bean 的概念,知道如何創建 Bean、以及 Bean 之間是怎麼注入的,這樣子我們真的進到實作時,才能夠知道如何在 StudentService 中,去注入一個 StudentDao 進來

因此想要掌握 Spring Boot 中的 Controller-Service-Dao 的用法的話,先決條件就是先了解 Bean 的相關操作!!得 Bean 者得天下啦!!!

補充:如果對 Bean 的部分不太熟悉,可以查看 Day 5~Day 10 Spring IoC 的相關介紹

3. 不能在 Controller 中直接使用 Dao

在 Controller-Service-Dao 的三層式架構中,各層的分層是很明確的,其中就有一項潛規則,即是「Controller 層不能直接使用 Dao 層」的 class

所以簡單的說的話,Controller 就一定只能去 call Service,再讓 Service 去 call Dao,不能讓 Controller 直接去 call Dao 就對了

https://ithelp.ithome.com.tw/upload/images/20231013/20151036me1tlUCdtd.png

4. Dao 層只能執行 sql 語法,不能添加商業邏輯

因為 Dao 層的功能,是負責去「和資料庫溝通」的,所以在 Dao 這個 class 裡面,只能夠去執行 sql 語法,去存取資料庫中的數據

所以換句話說的話,就是「不能」在 Dao 層裡面添加商業邏輯的程式

所以像是取得資料庫的數據之後,假設想要進行排序、或是篩選之類的動作,就得回到 Service 層再處理(因為 Service 層是負責商業處理)

因此在 Controller-Service-Dao 的三層式架構裡面,就會盡量保持 Dao 是非常單純的和資料庫溝通,一切複雜的商業邏輯處理,就通通回到 Service 層進行

總結


這篇文章先介紹了什麼是軟體工程,接著介紹了什麼是 MVC 架構模式,以及將 MVC 架構模式,轉化成 Spring Boot 中的 Controller-Service-Dao 的三層式架構

同時我們也詳細介紹了 Controller-Service-Dao 三層式架構的用法,比較了使用三層式架構的前後差別,最後也補充了使用 Controller-Service-Dao 三層式架構的注意事項,因此大家後續就可以透過這些用法,在你的 Spring Boot 程式中套用軟體工程的概念了!

那麼到這篇文章為止,我們就完成了所有 Spring Boot 中的基礎介紹,分別是:

  • Day 1 ~ Day 4:Spring Boot 簡介、環境安裝
  • Day 5 ~ Day 10:Spring IoC(Bean 的用法)
  • Day 11 ~ Day 12:Spring AOP
  • Day 13 ~ Day 23:Spring MVC(和前端溝通)
  • Day 24 ~ Day 28:Spring JDBC(和資料庫溝通)

因此介紹到這邊,大家就可以結合上述提到的功能,並且套用此篇文章的 Controller-Service-Dao 三層式架構,去搭建出一個簡易的後端系統出來了!

所以下一篇文章,我們就會來做個實戰演練,實際的透過上述的功能,去創建一個圖書館的管理系統出來,那我們就下一篇文章見啦!

相關連結



上一篇
Spring Boot 零基礎入門 (27) - Spring JDBC 的用法 (下) - 執行 SELECT sql
下一篇
Spring Boot 零基礎入門 (29) - 實戰演練 - 打造一個簡單的圖書館系統
系列文
Spring Boot 零基礎入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言