昨天我們學習如何在單檔裡設計 /notes
RESTful API。
今天我們把程式碼「模組化」,拆成 app.js(主程式)、routes/notes.js(路由層)、controllers/notes.js(控制器層)。
project/
├── app.js # 主程式
├── routes/
│ └── notes.js # Router:定義路由
└── controllers/
└── notes.js # Controller:業務邏輯
import express from "express";
import notesRouter from "./routes/notes.js";
const app = express();
app.use(express.json()); // 解析 JSON body
// 使用 notes 路由
app.use("/notes", notesRouter);
app.listen(3000, () => {
console.log("🚀 伺服器運行中:http://localhost:3000");
});
Router 的角色就是 URL 配置表,把不同的請求導到對應的控制器。
import express from "express";
import {
getAllNotes,
createNote,
updateNote,
deleteNote
} from "../controllers/notes.js";
const router = express.Router();
// GET /notes
router.get("/", getAllNotes);
// POST /notes
router.post("/", createNote);
// PUT /notes/:id
router.put("/:id", updateNote);
// DELETE /notes/:id
router.delete("/:id", deleteNote);
export default router;
控制器負責「業務邏輯」,讓路由層保持乾淨。
這裡我們仍用記憶體中的假資料做示範。
let notes = [
{ id: 1, title: "第一則筆記" },
{ id: 2, title: "第二則筆記" }
];
// 取得所有筆記
export function getAllNotes(req, res) {
res.json(notes);
}
// 新增筆記
export function createNote(req, res) {
const newNote = { id: Date.now(), title: req.body.title };
notes.push(newNote);
res.status(201).json(newNote);
}
// 更新筆記
export function updateNote(req, res) {
const note = notes.find((n) => n.id == req.params.id);
if (!note) return res.status(404).json({ error: "找不到筆記" });
note.title = req.body.title;
res.json(note);
}
// 刪除筆記
export function deleteNote(req, res) {
notes = notes.filter((n) => n.id != req.params.id);
res.status(204).send();
}
[Client 請求]
│
▼
[app.js]
│ app.use("/notes", notesRouter)
▼
[routes/notes.js]
│ router.get/post/put/delete
▼
[controllers/notes.js]
│ 實作邏輯(CRUD)
▼
[Response 回傳 JSON 給 Client]
這樣拆分的好處: