Vapor 是 Swift 在服务器端最受欢迎的 web 框架。 现在 Vapor4 还未 release,截止 10/23 日,最新版本:
Vapor 4.0.0 Alpha 3.2
Vapor4 的变化主要源于底层技术的更新:
- Swift 5.1 的新特性
- SwiftNIO v2 and HTTP2 support
- SwiftLog,苹果发布的日志框架
- ...
Vapor4 中包含以下更新:
Vapor
* services on controllers
* synchronous content decoding
* upload / download streaming
* backpressure
* http/2
* extensible route builder (for openapi)
* apple logging
* improved session syntax
* dotenv support
* validation included
* authentication included
* XCTVapor testing module
* swift server http client
* simplified websocket endpoints
* graceful shutdown
* nio 2
ConsoleKit
* type safe signatures
RoutingKit
* performance improvements
* performance testing bot
Fluent
* dynamic models
* simplified driver requirements
* eager loading: join + subquery
* partial selects
* dirty updates
LeafKit
* improved body syntax
* separate lexer + parser
Toolbox
* dynamic project init
///
....
Fluent
Fluent 的更新会是一个重头戏。
Controllers 将会持有数据库对象,我们操作这个对象直接操作数据库,不需要从 Request 对象中获取。不再用 Future 对 SwiftNIO 的 EventLoopFuture 作为别称。
// Vapor 3
import Vapor
/// Controls basic CRUD operations on `Todo`s.
final class TodoController {
/// Returns a list of all `Todo`s.
func index(_ req: Request) throws -> Future<[Todo]> {
return Todo.query(on: req).all()
}
/// Saves a decoded `Todo` to the database.
func create(_ req: Request) throws -> Future<Todo> {
return try req.content.decode(Todo.self).flatMap { todo in
return todo.save(on: req)
}
}
/// Deletes a parameterized `Todo`.
func delete(_ req: Request) throws -> Future<HTTPStatus> {
return try req.parameters.next(Todo.self).flatMap { todo in
return todo.delete(on: req)
}.transform(to: .ok)
}
}
// Vapor 4
import Fluent
import Vapor
final class TodoController {
let db: Database
init(db: Database) {
self.db = db
}
func index(req: Request) throws -> EventLoopFuture<[Todo]> {
return Todo.query(on: self.db).all()
}
func create(req: Request) throws -> EventLoopFuture<Todo> {
let todo = try req.content.decode(Todo.self)
return todo.save(on: self.db).map { todo }
}
func delete(req: Request) throws -> EventLoopFuture<HTTPStatus> {
return Todo.find(req.parameters.get("todoID"), on: self.db)
.unwrap(or: Abort(.notFound))
.flatMap { $0.delete(on: self.db) }
.transform(to: .ok)
}
}
Fluent 具有动态模型,整个数据库层也更加复杂。您可以自定义自己的 keys, schemas 以及其他你自己喜好的配置。
// Vapor 3
import FluentSQLite
import Vapor
/// A single entry of a Todo list.
final class Todo: SQLiteModel {
/// The unique identifier for this `Todo`.
var id: Int?
/// A title describing what this `Todo` entails.
var title: String
/// Creates a new `Todo`.
init(id: Int? = nil, title: String) {
self.id = id
self.title = title
}
}
/// Allows `Todo` to be used as a dynamic migration.
extension Todo: Migration { }
/// Allows `Todo` to be encoded to and decoded from HTTP messages.
extension Todo: Content { }
/// Allows `Todo` to be used as a dynamic parameter in route definitions.
extension Todo: Parameter { }
// ------------------------------------------------------------------------------------------
// Vapor 4
import Fluent
import Vapor
final class Todo: Model, Content {
static let schema = "todos"
@ID(key: "id")
var id: Int?
@Field(key: "title")
var title: String
init() { }
init(id: Int? = nil, title: String) {
self.id = id
self.title = title
}
}
有一个全新的迁移层,提供易于上手的 API。
import Fluent
struct CreateTodo: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema("todos")
.field("id", .int, .identifier(auto: true))
.field("title", .string, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema("todos").delete()
}
}
Fluent is amazing in Vapor 4!
更多阅读,请关注官方微信公众号: