【Swift-Vapor服务器】系列
【Swift-Vapor服务器】0001、Swift-Vapor入门-环境搭建
【Swift-Vapor服务器】0002、Swift-Vapor的基本使用-搭建一个属于自己歌曲的API
技术:Swift5.7、Vapor4.0、服务器、本地服务器、Vapor基本使用
运行环境:
Swift5.7 + Xcode14 + MacOS12.6 + Docker Desktop 4.12.0 (85629) + Azure Data Studio Version: 1.39.1 + Postman 9.24.2
Homebrew、Vapor 、Postman、Azure Data Studio 、DBeaver 、Docker Desktop
本次的目的是
- 使用Swift的Vapor搭建一个本地服务器
- 并且通过
Docker
启动数据库
? 为什么要使用Docker
启动数据库
因为Xcode启动Vapor项目 只是运行API 没有对数据库进行启动- 使用
Azure Data Studio
查看PostgreSQL
类型的数据库- 能够使用本地的localhost去访问 获取、添加数据
创建一个歌曲的API的Vapor项目 - 其中
Music-Vapor-API
表示项目名称
vapor new
表示 创建一个vapor 项目vapor new Music-Vapor-API
终端指令为 以下
vapor xcode
如果无法启动Xcode 。那么手动将Xcode进行打开Vapor项目
打开之后等待项目将默认的依赖包安装完毕
Command + R
启动项目 ,并且使用postman
进行测试接口是否正常Vapor 默认提供了一个Todo项目来启动
主要目的
是项目 通过下面的路由进行获取对应数据http://127.0.0.1:8080 表示根route - 路由
http://127.0.0.1:8080/songs
这个是我们主要目的 根据此路由获取 歌曲数据
postman
检测接口是否能正常调试
我们可以看到Xcode的控制台 每次访问一次接口 下面都会输出一个信息
说明我们每访问指定的接口 就会输出一次
在route里面编写我们的代码
但是如果一个项目庞大 我们是需要单独进行抽取。跟默认创建Vapor项目自带的todo类型
所以我们需要创建控制器、模型、迁移
New File
选择Swift File
创建一个控制器 命名为SongController
New File
选择Swift File
创建一个迁移 命名为CreateSongs
我们先解释一下 Migrations 是干什么用的
我们数据库什么时候使用到迁移比如 我们Xcode里面有Git版本控制时候 。
当我们输入新的代码时候并且更改Xcode的时候。我们使用Git来告诉我们更改了什么
我们可以恢复迁移到某个时间点我们使用数据库迁移 就类似使用Xcode的Git一样
如何使用表中的数据 我们需要创建Model
New File
选择Swift File
创建一个模型命名为Song
configure
设置真正创建数据库routes
设置歌曲控制器的创建
- 先是执行
configure
进行创建数据库- 然后执行route里面的内容
主要作用 : 增删改查。让数据 添加\删除\修改 到我们数据库里面
注意提示 : 不建议在route里面进行 操作 。这个会使用route非常的庞大。
最好把逻辑分离。让控制器做这个事情。在route里面只需要注册控制器即可
//
// SongController.swift
//
//
// Created by 李宇鸿 on 2022/9/29.
//
import Fluent
import Vapor
// 继承RouteCollection - 路由集合
struct SongController : RouteCollection {
// boot 把它想象成一个初始化函数即可
func boot(routes: Vapor.RoutesBuilder) throws {
// 这里放什么?
// 这里表示
// 当我们去根路由 - 127.0.0.1
// 分组下的 创建一个新功能
let songs = routes.grouped("songs")
// 表示当使用 127.0.0.1/songs get方法的时候
// 然后去就使用index这个函数
// get 一般是获取数据
songs.get(use: index)
// post 一般是发布数据
songs.post(use:create)
}
// songs route
func index(req: Request) throws -> EventLoopFuture<[Song]>{
// 在这里 我们需要返回歌曲查询. 这意味着 这指的是我们
// 因为我们使用的 Fluent 在执行所有功能与我们的数据库对话
// 所以我们做歌曲查询 意味着 我们想要在请求数据上获取我们想要的数据
return Song.query(on: req.db).all()
}
// 返回 http状态
func create(req:Request) throws -> EventLoopFuture<HTTPStatus> {
// decode 类似 iOS里面的 json decode一样
// 解码之后 我们将歌曲类型保存到一个song的变量中
// 然后保存到我们的数据库中
// Song的这个Model.它天生有这个功能.可以用来与数据库对话.
let song = try req.content.decode(Song.self)
return song.save(on: req.db).transform(to: .ok)
}
}
主要作用 : 使用Fluent创建表 和更改删除表的操作
//
// CreateSongs.swift
//
//
// Created by 李宇鸿 on 2022/9/29.
//
//import Foundation
// Fluent是一个框架
// 一个Orm,所以它是一个对象关系映射器或者对象关系映射
// 我们将使用它进行迁移.
// 因此.迁移将跟我们数据库之间添加的内容的差异.
import Fluent
// 所以首先让我们创建一个名为 CreateSongs的结构体
// 它继承自迁移 Migration
// Migration 可以处理数据库迁移,包括添加新表,或者更改现有的变
// 所以这很像让它跟踪我们所有的变化 - 但不是针对我们的xcode.而是针对我们的数据库
struct CreateSongs : Migration {
// 默认它会为我们提供这两个函数 prepare \ revert
// 所以我们说迁移变化
// 下面表示 准备该怎么做,恢复更改该怎么做
// 准备
func prepare(on database: FluentKit.Database) -> NIOCore.EventLoopFuture<Void> {
// 第一件事情 就是使用它创建我们的表 - 表名为 Songs
// 表里面有行\列使我们数据不同的属性
// id \ 通过field函数(字段名\类型\是否必填)创建 其他字段 比如标题等
return database.schema("songs")
.id() // 唯一标识
.field("title", .string, .required) // 其他字段
.create() // 创建表
}
// 恢复更改
func revert(on database: FluentKit.Database) -> NIOCore.EventLoopFuture<Void> {
// 如果想还原 和 准备的所有更改
return database.schema("songs").delete()
}
// 以上就是进行对表的迁移
}
主要作用是: 创建表的数据
//
// Song.swift
//
//
// Created by 李宇鸿 on 2022/9/29.
//
// 导入Fluent表示 我要从数据库中查询数据的方式
import Fluent
import Vapor
// 它继承于 Model 和 Content
final class Song : Model,Content {
// 所以把它想象成我们在iOS项目中创建的普通类
// 这是我们所有的模型 意思是我们在找那个表
static let schema = "songs"
// 这张表里面包含哪些属性
// 我们需要添加一些内容 以帮助Fluent地是识别表中的所有内容
// 当我们添加 @ID(key: .id), @Field(key: "title") 他会告诉Fluent的ID的这个属性匹配我们表中的ID属性
@ID(key: .id)
var id : UUID?
@Field(key: "title")
var title : String
// 初始化程序 - 提供一个空的初始化程序 和一个 带有id\title的初始化
init(){
}
init(id: UUID? = nil,title:String)
{
self.id = id
self.title = title
}
// 所以这个歌曲类 代表我们数据库中的数据
}
import Fluent
import FluentPostgresDriver
import Vapor
// configures your application
public func configure(_ app: Application) throws {
// uncomment to serve files from /Public folder
// app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
// 这个是一个Postgres数据库
// 然后这是尝试为我们的主机获取环境变量,端口,用户名,密码,然后是数据库名称
// 单不是现在创建环境文件,如果找不到,它只会使用这个localhost
// 所以默认情况下,我们的数据库主机是localhost
// 账号密码\数据库表名为 vapor_username,vapor_password,vapor_database 通用的
app.databases.use(.postgres(
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
port: Environment.get("DATABASE_PORT").flatMap(Int.init(_:)) ?? PostgresConfiguration.ianaPortNumber,
username: Environment.get("DATABASE_USERNAME") ?? "vapor_username",
password: Environment.get("DATABASE_PASSWORD") ?? "vapor_password",
database: Environment.get("DATABASE_NAME") ?? "vapor_database"
), as: .psql)
// 真正创建数据库
// 我们输入应用程序迁移
app.migrations.add(CreateSongs())
// 进行自动迁移
// 这意味着 我们拥有的所有迁移.我们想要实际运行它们.这将为我们创建一个数据库
// 它将等待自动完成.然后再执行其他所有操作.
try app.autoMigrate().wait()
// register routes
try routes(app)
}
主要作用是 : 设置每个接口的route返回的内容 以及控制器的创建
import Fluent
import Vapor
func routes(_ app: Application) throws {
// 其中这两个route 我们不会真正使用它们
app.get { req async in
"It works!"
}
app.get("hello") { req async -> String in
"Hello, world!"
}
// 创建歌曲控制器
try app.register(collection: SongController())
}
[ WARNING ] No custom working directory set for this scheme, using /Users/liyuhong/Library/Developer/Xcode/DerivedData/Music-Vapor-API-eebtsvgkhstmqwepwunlncfgmtey/Build/Products/Debug
Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PostgresNIO.PSQLError(base: PostgresNIO.PSQLError.Base.connectionError(underlying: NIOPosix.NIOConnectionError(host: “localhost”, port: 5432, dnsAError: nil, dnsAAAAError: nil, connectionErrors: [NIOPosix.SingleConnectionFailure(target: [IPv6]localhost/::1:5432, error: connection reset (error set): Connection refused (errno: 61)), NIOPosix.SingleConnectionFailure(target: [IPv4]localhost/127.0.0.1:5432, error: connection reset (error set): Connection refused (errno: 61))])))
2022-09-29 16:22:21.468675+0800 Run[20886:24683826] Swift/ErrorType.swift:200: Fatal error: Error raised at top level: PostgresNIO.PSQLError(base: PostgresNIO.PSQLError.Base.connectionError(underlying: NIOPosix.NIOConnectionError(host: “localhost”, port: 5432, dnsAError: nil, dnsAAAAError: nil, connectionErrors: [NIOPosix.SingleConnectionFailure(target: [IPv6]localhost/::1:5432, error: connection reset (error set): Connection refused (errno: 61)), NIOPosix.SingleConnectionFailure(target: [IPv4]localhost/127.0.0.1:5432, error: connection reset (error set): Connection refused (errno: 61))])))
这上面说明它不能做某些事情
意味着数据库连接被拒绝
它无法连接到数据库
因为数据库实际上没有运行
我们需要做的事情是
查看docker-compose.xml
文件 我们可以 docker-compose up db 指令进行单独启动数据库
Xcode运行应用程序 只是API方面的
我们通过Docker启动数据库
docker-compose up db
指令 等待启动 Docker桌面我们发现 我们通过 http://127.0.0.1:8080/songs
访问
返回状态是200
返回的内容[]
因为我们在数据库里面没有添加任何的数据。所以返回的是空数组
Azure Data Studio
查看数据库里面的数据。而无需使用APIPostgreSQL
PostgreSQL
添加歌曲数据
在SongController
添加 create
函数 最主要是将一条歌曲数据添加
并且重启Vapor项目
进行使用PostMan
请求方式改成Post
并且设置 Body为 raw
格式为Json
然后发送请求
Azure Data Studio
检查歌曲数据是否加入
control + C
当数据库显示灰色 表示停止运行
Azure Data Studio
是否关闭