Controllers可以帮你将相关功能整合到一起,或者创建一些依赖性的资源。
Basic
下面是一个基本的Controller
:
final class HelloController {
func sayHello(_ req: Request) throws -> ResponseRepresentable {
guard let name = req.data["name"] else {
throw Abort.badRequest
}
return "Hello, \(name)"
}
}
一个简单的控制器类不需要遵守任何协议,你可以自由的设计、实现你想要的功能。
Registering
实现注册唯一要做的事情就是为controller中的每个方法进行签名(看看上面sayHello
方法的结构)。为了将controller中的方法注册到路由中去,需要方法实现类似于(Request) throws -> ResponseRepresentable
的结构。 Request
和ResponseRepresentable
的使用需要引入HTTP
模块。
let hc = HelloController()
drop.get("hello", handler: hc.sayHello)
由于sayHello
方法的签名与drop.get
方法的闭包签名相匹配,所以我们可以直接传递。
Type Safe(类型安全)
你也可以使用具有类型安全路由的控制器方法:
final class HelloController {
...
func sayHelloAlternate(_ req: Request, _ name: String) -> ResponseRepresentable {
return "Hello, \(name)"
}
}
将sayHelloAlternate
方法添加到HelloController
当中,它可以接收第二个参数name: String
。
let hc = HelloController()
drop.get("hello", String.self, handler: hc.sayHelloAlternate)
类型安全的drop.get
接收(Request, String) throws -> ResponseRepresentable
签名之后,我们的方法就可以用作这个路由的闭包。
Resources
遵守ResourceRepresentable
的Controllers可以很轻松的作为RESTful资源注册到路由当中,下面用UserController
举例:
final class UserController {
func index(_ request: Request) throws -> ResponseRepresentable {
return try User.all().makeNode().converted(to: JSON.self)
}
func show(_ request: Request, _ user: User) -> ResponseRepresentable {
return user
}
}
上面的UserController
是一个很基本的controller,包含index
和show
两个路由,index
路由返回的是所有user
列表的json数据,show
路由返回的是一个具体user
的json数据。
我们注册这个controller的时候这样写:
let users = UserController()
drop.get("users", handler: users.index)
drop.get("users", User.self, handler: users.show)
但是ResourceRepresentable
协议使得这个标准的RESTful结构变得非常容易:
extension UserController: ResourceRepresentable {
func makeResource() -> Resource<User> {
return Resource(
index: index,
show: show
)
}
}
UserController
遵守ResourceRepresentable
协议要求将
show
和index
方法的签名与Resource<User>
期望的格式相匹配。
看一下Resource类的实现:
final class Resource<Model: StringInitializable> {
typealias Multiple = (Request) throws -> ResponseRepresentable
typealias Item = (Request, Model) throws -> ResponseRepresentable
var index: Multiple?
var store: Multiple?
var show: Item?
var replace: Item?
var modify: Item?
var destroy: Item?
var clear: Multiple?
var aboutItem: Item?
var aboutMultiple: Multiple?
...
}
现在UserController
遵守了ResourceRepresentable
协议,注册路由就变的简单了:
let users = UserController()
drop.resource("users", users)
drop.resource
只会注册通过调用makeResource()
方法提供的路由。在这种情况下,只会启用index
和show
这两个路由。
Note:
drop.resource
还为OPTIONS requests
添加了有用的默认值。这些可以被重写。
Folder
Controllers可以放在应用的任何目录下,但是一般放在Controllers/
目录中。
Modules
如果你的项目比较庞大,你可能需要在单独的模块中创建Controllers,这样可以允许你对你的controllers进行单元测试。更多关于模块创建的信息请参考文档Swift Package Manager
网友评论