控制器幫助您將相關(guān)的功能組織到一個地方冶忱。它們還可以用于創(chuàng)建RESTful資源。
基本(Basic)
一個基本的控制器看起來像下面這樣:
import Vapor
import HTTP
final class HelloController {
func sayHello(_ req: Request) throws -> ResponseRepresentable {
guard let name = req.data["name"]?.string else {
throw Abort(.badRequest)
}
return "Hello, \(name)"
}
}
簡單的控制器不需要遵守任何協(xié)議。你可以自由地設(shè)計它們,只要你認(rèn)為合適。
注冊(Registering)
唯一需要的結(jié)構(gòu)是控制器中每個方法的簽名盾鳞。為了將這個方法注冊到路由器中,它必須有一個簽名瞻离,(Request) throws -> ResponseRepresentable
腾仅。通過導(dǎo)入HTTP
模塊,可以獲得請求(Request
)和響應(yīng)(ResponseRepresentable
)套利。
import Vapor
let drop = try Droplet()
let hc = HelloController()
drop.get("hello", handler: hc.sayHello)
由于sayHello
”方法的簽名與drop.get
方法的閉包簽名相匹配推励,我們可以直接傳遞它。
類型安全(Type Safe)
您還可以使用帶有類型安全路由的控制器方法肉迫。
final class HelloController {
...
func sayHelloAlternate(_ req: Request) -> ResponseRepresentable {
let name: String = try req.parameters.next(String.self)
return "Hello, \(name)"
}
}
我們在HelloController
中添加一個名為sayHelloAlternate
的新方法验辞,從請求的參數(shù)中獲取一個String
。
let hc = HelloController()
drop.get("hello", String.parameter, handler: hc.sayHelloAlternate)
由于dropget
接受了一個簽名(Request) throws -> ResponseRepresentable
喊衫,我們的方法現(xiàn)在可以作為這條路線的終止跌造。
筆記
在路由參數(shù)(Routing Parameters)部分閱讀更多關(guān)于類型安全路由的信息。
資源(Resources)
符合ResourceRepresentable
的控制器可以很容易地作為一個RESTful資源被注冊到路由器族购。讓我們來看一個UserController
的例子壳贪。
final class UserController {
func index(_ req: Request) throws -> ResponseRepresentable {
return try User.all().makeJSON()
}
func show(_ req: Request) throws -> ResponseRepresentable {
let user = try req.parameters.next(User.self)
return user
}
}
這是一個典型的用戶控制器,它有一個index
和show
路徑寝杖。索引返回所有用戶的JSON列表撑碴,并顯示返回單個用戶的JSON數(shù)據(jù)。
我們可以像這樣注冊控制器:
let users = UserController()
drop.get("users", handler: users.index)
drop.get("users", User.self, handler: users.show)
但是朝墩,ResourceRepresentable
使得這種標(biāo)準(zhǔn)的RESTful結(jié)構(gòu)很容易醉拓。
extension UserController: ResourceRepresentable {
func makeResource() -> Resource<User> {
return Resource(
index: index,
show: show
)
}
}
符合ResourceRepresentable
的UserController
需要index
和show
方法的簽名與Resource<User>
的期望相匹配。
現(xiàn)在收苏,UserController
可以滿足ResourceRepresentable
的需要亿卤,注冊路由很容易。
let users = UserController()
drop.resource("users", users)
drop.resource
將只負(fù)責(zé)注冊由調(diào)用makeResource()
所提供的路由鹿霸。在這種情況下排吴,只提供index
和show
路徑。
Note
drop.resource
還為選擇項(OPTIONS)請求增加了有用的缺省值懦鼠。這些可以被重載钻哩。
行動(Actions)
下面是一個描述所有可用操作的表。
Action | Method | Path | Note |
---|---|---|---|
index | GET | /users | Returns all users, optionally filtered by the request data. |
store | POST | /users | Creates a new user from the request data. |
show | GET | /users/:id | Returns the user with the ID supplied in the path. |
replace | PUT | /users/:id | Updates the specified user, setting any fields not present in the request data to nil. |
update | PATCH | /users/:id | Updates the specified user, only modifying fields present in the request data. |
delete | DELETE | /users/:id | Deletes the specified user. |
clear | DELETE | /users | Deletes all users, optionally filtered by the request data. |
create | GET | /users/create | Displays a form for creating a new user. |
edit | GET | /users/:id/edit | Displays a form for editing the specified user. |
提示
replace
和update
之間的差異是很微妙但很重要的:如果請求數(shù)據(jù)中不存在某個字段(例如肛冶,用戶的年齡丟失了)街氢,update
應(yīng)該不會更新該字段,因為replace
應(yīng)該將其設(shè)置為nil睦袖。如果replace
請求中缺少所需的數(shù)據(jù)珊肃,則應(yīng)該拋出一個錯誤。
文件夾(Folder)
控制器可以在應(yīng)用程序的任何地方進(jìn)行,但它們通常存儲在應(yīng)用App/Controllers/
目錄中伦乔。
提示
如果您正在構(gòu)建一個大型應(yīng)用程序厉亏,您可能希望在一個單獨(dú)的模塊中創(chuàng)建控制器。這將允許您在控制器上執(zhí)行單元測試烈和。