Vapor文档学习七:Controllers

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的结构。 RequestResponseRepresentable的使用需要引入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,包含indexshow两个路由,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 {
        return Resource(
            index: index,
            show: show
        )
    }
}

UserController遵守ResourceRepresentable协议要求将
showindex方法的签名与Resource期望的格式相匹配。

看一下Resource类的实现:

final class Resource {
    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()方法提供的路由。在这种情况下,只会启用indexshow这两个路由。

Note:drop.resource还为OPTIONS requests添加了有用的默认值。这些可以被重写。

Folder

Controllers可以放在应用的任何目录下,但是一般放在Controllers/目录中。

Modules

如果你的项目比较庞大,你可能需要在单独的模块中创建Controllers,这样可以允许你对你的controllers进行单元测试。更多关于模块创建的信息请参考文档Swift Package Manager

你可能感兴趣的:(Vapor文档学习七:Controllers)