控制器与 MVC 架构 封面
Vapor 教程

控制器与 MVC 架构

路由只有两三条时,全写进 routes.swift 还凑合;等到几十条,就成了灾难。Vapor 用「控制器」把相关路由收拢成模块,背后的思想就是经典的 MVC。

一、为什么需要控制器

Web 开发里有个流行套路叫 MVC

把路由按主题塞进各自的控制器,routes.swift 就只剩「挂载」这件事,清爽得多。

二、控制器长什么样

一个控制器就是一个遵循 RouteCollection 的结构体,在 boot() 里注册自己的路由:

import Vapor
import Fluent

struct AcronymsController: RouteCollection {
    func boot(routes: RoutesBuilder) throws {
        routes.post("api", "acronyms", use: createHandler)
    }

    func createHandler(_ req: Request) throws -> EventLoopFuture<Acronym> {
        let data = try req.content.decode(CreateAcronymData.self)
        let acronym = Acronym(short: data.short, long: data.long)
        return acronym.save(on: req.db).map { acronym }
    }
}
版本提示:上面是 Vapor 4 写法(用 RoutesBuilderreq.db)。Vapor 3 里对应的是 func boot(router: Router) 以及 req 上的 .save(on: req) 返回 Future。思路一致,只是 API 名字不同。

三、把控制器挂上去

routes.swift 退居「接线员」角色,只负责创建并注册控制器:

import Vapor

func routes(_ app: Application) throws {
    let acronymsController = AcronymsController()
    try app.register(collection: acronymsController)

    let websiteController = WebsiteController()
    try app.register(collection: websiteController)
}

这样「接口类路由」和「网页类路由」各归各家,文件不再是一坨。

四、RouteGroup:给路由加统一前缀

当控制器里多条路由都挂在 api/acronyms 下,每条都写完整路径就太啰嗦。用 RouteGroup 提一次前缀:

func boot(routes: RoutesBuilder) throws {
    let group = routes.grouped("api", "acronyms")
    group.post(use: createHandler)
    group.get(use: getAllHandler)
    group.get(":acronymID", use: getHandler)
    group.delete(":acronymID", use: deleteHandler)
}

四条路由自动带上 /api/acronyms 前缀,少写很多重复字符串,也少了拼错路径的机会。

五、控制器里能做什么

控制器是真正的「业务中枢」:

把路由逻辑从 routes.swift 搬到控制器,是你项目从「玩具」走向「能维护」的关键一步。


本系列其他文章