團主要開一張團購訂單:挑一家店、給團名、設一個截止時間,這個時候前端帶著登入時拿到的 JWT 送出:
POST /order/create_order
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
{
"storeId": "S001",
"orderName": "下午茶",
"deadline": "2026-09-02 15:00:00"
}
這一筆 request 進來之後,系統依序回答四個問題——
1.你是誰?
2.你能不能開團?
3.資料對不對?
4.業務上開得成嗎?
回答完才寫進資料庫。從spring security確認"你是誰"、經過controller驗證請求內容,再通過service的業務邏輯決定業務上開不開的成,最後進到資料庫,見下圖示。

這裡可以把每一層想成接力賽:前一層只處理自己的問題,處理完就把結果交給下一層。認證不負責判斷業務規則,Controller 不負責查店家,Service 也不需要知道 HTTP 長什麼樣子————關注點分離。
| 站 | 負責 | 不負責 |
|---|---|---|
| ① 認證 | 這個請求是誰 | 這個人能不能做這件事 |
| ② 授權 | 這個人能不能打這個端點 | 這筆訂單是不是他的 |
| ③ 驗證 | 欄位格式對不對 | 業務規則 |
| ④ Controller | HTTP 的事:狀態碼、資料進出 | 業務規則 |
| ⑤ Service | 業務規則、交易邊界 | HTTP 的存在 |
| ⑥ Mapper | 一句 SQL | 判斷這句該不該執行 |
第②站與第⑤站的分界看起來很相似,但定義其實不同。
舉例:
1.「團主這個角色能不能打取消端點」查一次規則表就知道,屬於第②站
2.「只能取消自己開的那一團」得先把那筆訂單讀出來比對開團者,屬於第⑤站。
查規則的歸授權,查資料才知道的歸業務層。
同一件事——建立一張團購訂單——大可以全部寫在一個方法裡:驗 token、查權限、檢查欄位、查店家、寫 DB。功能會一模一樣。
先把關注點分離,才能一次只理解一件事。