在上一篇博客使用Perfect写服务端–初级(一)中已经示范了在本地启动一个服务的过程,这一篇博客将展示具体的一些基本开发,写接口、连接数据库、数据库增删查改等。
启动HTTP服务
我们之前已经克隆了官方的例子,并且已经编译好生成了Xcode
可以直接打开的工程文件,现在打开工程,在PerfectTemplate
目录下新建一个swift
文件,取名为MyServer
导入需要用到的库
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
然后使用命令
$ swift build
$ swift package generate-xcodeproj
重新编译。
具体代码:
open class MyServer{
fileprivate var server : HTTPServer
internal init(root : String , port : UInt16){
// 构造httpServer对象
server = HTTPServer.init()
// 构造路由对象
var routes = Routes.init()
// 配置路由 (URL,回调函数)
configure(routes: &routes)
// 将路由添加进服务
server.addRoutes(routes)
// 设置根目录和端口
server.documentRoot = root
server.serverPort = port
}
// 配置路由的方法
fileprivate func configure(routes : inout Routes){
// 添加接口, 路径为/,请求方法为GET,回调函数为闭包
routes.add(method: .get, uri: "/") { (request, response) in
// 取得URL中的参数
// let param = request.params()
//返回数据头
response.setHeader(.contentType, value: "text/html")
//返回数据体
response.appendBody(string: "Hello world")
//返回
response.completed()
}
}
// 启动服务
open func start(){
do {
try self.server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: \(err) \(msg)")
} catch{
print("Network unknow error")
}
}
}
这样就写完了一个HTTP Server,包含了一个接口,接口返回的内容是一个字符串形式的Hello world
。使用Perfect
搭建一个HTTP服务还是比较简单,Perfect
已经处理了大部分事物,在路由的创建过程中,开发者只需要提供一个处理该路由的回调函数。
在main.swift
中调用start
启动服务
let myServer = MyServer.init(root: "/Users/admin/Desktop/PerfectTemplate/Sources/file", port: 8181)
myServer.start()
在Xcode
中直接编译运行,在浏览器的地址栏输入localhost:8181就能看到返回的Hello world
字符串
其中参数root
设置的根目录路径下的文件在没有其它设置的情况下是可以通过URL直接访问或者下载的,比如在我当前设置的路径下放入一个json文件
然后我们就可以通过URL http://localhost:8181/loading.json
访问到这个json文件中的内容
类似json
,html
文件,或者图片都可以直接访问,其它文件是可以直接下载的。
添加接口
接口可以在配置路由的方法里添加
// get请求 在闭包里对这个请求做处理 返回一个json
routes.add(method: .get, uri: "/getDatas") { (request, response) in
response.setHeader(.contentType, value: "application/json; charset=utf-8")
// 获取参数
guard let content = request.param(name: "content") else{
let jsonString = self.baseResponseBodyJSONData(status: -1, message: "失败", data: "缺少参数")
response.setBody(string: jsonString)
response.completed()
return
}
let dic = ["content" : content]
let jsonString = self.baseResponseBodyJSONData(status: 200, message: "请求成功", data: dic)
response.setBody(string: jsonString)
response.completed()
}
通用json格式
private func baseResponseBodyJSONData(status : Int, message : String, data : Any!) -> String{
var result = Dictionary<String, Any>()
result.updateValue(status, forKey: "status")
result.updateValue(message, forKey: "message")
if (data != nil){
result.updateValue(data, forKey: "data")
}else{
result.updateValue("", forKey: "data")
}
guard let jsonString = try? result.jsonEncodedString() else{
return ""
}
return jsonString
}
设置完成后重启服务,然后在浏览器中请求
这样一个接口就完成了,很简单,可以根据自己的需求添加一个接口试一试。
如果需要保存数据,或者获取数据那就需要用到数据库了,下面进行接入数据库的实践。
MySQL接入
对于MySQL
的接入可以直接使用Perfect
提供的Perfect-MySQL库。
在Package.swift
添加引用:
.package(url: "https://github.com/PerfectlySoft/Perfect-MySQL.git", from: "3.0.0")
重新编译,下载Perfect-MySQL
库,重新生成工程并且打开
$ swift build
$ swift package generate-xcodeproj
如果执行swift build
有报错,可以先执行swift package generate-xcodeproj
然后请看文章最后的解决办法
安装MySQL
可以参考文章:Mac下使用homebrew安装配置mysql
Mac
下安装MySQL
这里就不多说了,安装和配置可自行谷歌和百度,或者参考上面的博客链接,但是记得请用homebrew
安装,之前我下载的官网的包,然后手动安装后面出了点小问题,后面还是用的homebrew
安装的,所以为了避免后面出现一些小问题记得请用homebrew
安装。
安装数据库管理工具
我现在用的管理工具是Navicat Premium
,有更好的可以推荐。
Navicat Premium下载地址
创建数据库和表
在本地安装配置好MySQL和工具Navicat Premium
后,使用Navicat Premium
连接本地数据库。
1.打开Navicat Premium
,新建一个MySQL
连接
2.创建数据库
选择刚才创建的MySQL
连接,右键新建数据库,数据库名字自己取
3.创建表
选择创建的数据库,双击展开,然后展开表
,右键表
选择新建表
,添加字段
4.插入数据
创建数据库管理类
打开工程,新建数据库管理类
import Foundation
import PerfectMySQL
//MARK: 数据库信息
// XieteProject
let mysql_host = "localhost"
let mysql_user = "root"
let mysql_password = "**********" //这里请填写自己数据库的密码
let mysql_database = "XieteProject"
//MARK: 表信息
let table_column = "tbl_column"
let dbManager = DataBaseManager.init()
open class DataBaseManager {
fileprivate var mysql : MySQL
internal init(){
mysql = MySQL.init() // 创建MySQL对象
//设置客户端字符集,这是非常必要的操作,否则所有中文可能都会变成问号
guard mysql.setOption(.MYSQL_SET_CHARSET_NAME, "utf8mb4") else {
return
}
guard connectedDataBase() else { // 开启MySQL连接
return
}
}
// MARK: 开启连接
private func connectedDataBase() -> Bool{
let connected = mysql.connect(host: mysql_host, user: mysql_user, password: mysql_password, db: mysql_database)
guard connected else {
print("MySQL连接失败" + mysql.errorMessage())
return false
}
print("MySQL连接成功")
return true
}
//MARK: 执行SQL语句
/// 执行SQL语句
///
/// - Parameter sql: sql语句
/// - Returns: 元组
@discardableResult
func mysqlStatement(_ sql : String) -> (success : Bool, mysqlResult : MySQL.Results?, errorMsg: String){
guard mysql.selectDatabase(named: mysql_database) else {
let msg = "未找到\(mysql_database)数据库:\(mysql.errorMessage())"
print(msg)
return (false, nil, msg)
}
let successQuery = mysql.query(statement: sql)
guard successQuery else {
let msg = "SQL失败 :\(sql)"
print(msg)
return(false, nil, msg)
}
let msg = "SQL成功 :\(sql)"
print(msg)
return(true, mysql.storeResults(),msg)
}
/// 增
///
/// - Parameters:
/// - tableName: 表
/// - key: 键 (键,键,键)
/// - value: 值 ('值', '值', '值')
/// - Returns: 元组
func insertDatabaseSQL(tableName : String, key : String, value : String) -> (success : Bool, mysqlResult : MySQL.Results?, errorMsg: String){
let SQL = "INSERT INTO \(tableName) (\(key)) VALUES (\(value))"
return mysqlStatement(SQL)
}
/// 删
///
/// - Parameters:
/// - tableName: 表
/// - key: 键
/// - value: 值
func deleteDatabaseSQL(tableName: String, key: String, value: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "DELETE FROM \(tableName) WHERE \(key) = '\(value)'"
return mysqlStatement(SQL)
}
/// 改
///
/// - Parameters:
/// - tableName: 表
/// - keyValue: 键值对( 键='值', 键='值', 键='值' )
/// - whereKey: 查找key
/// - whereValue: 查找value
func updateDatabaseSQL(tableName: String, keyValue: String, whereKey: String, whereValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "UPDATE \(tableName) SET \(keyValue) WHERE \(whereKey) = '\(whereValue)'"
return mysqlStatement(SQL)
}
/// 查所有
///
/// - Parameters:
/// - tableName: 表
/// - key: 键
func selectAllDatabaseSQL(tableName: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "SELECT * FROM \(tableName)"
return mysqlStatement(SQL)
}
/// 查
///
/// - Parameters:
/// - tableName: 表
/// - keyValue: 键值对
func selectAllDataBaseSQLwhere(tableName: String, keyValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
let SQL = "SELECT * FROM \(tableName) WHERE \(keyValue)"
return mysqlStatement(SQL)
}
}
编写接口获取数据库数据
在路由配置里添加接口
routes.add(method: .get, uri: "/getColumn") { (request, response) in
response.setHeader(.contentType, value: "application/json; charset=utf-8")
let dbManager = DataBaseManager.init()
let result = dbManager.selectAllDatabaseSQL(tableName: table_column)
var resultArray = [Dictionary<String, String>]()
var dic = [String : String]()
result.mysqlResult?.forEachRow(callback: { (row) in
dic["id"] = row[0]
dic["content"] = row[1]
resultArray.append(dic)
})
let jsonString = self.baseResponseBodyJSONData(status: 200, message: "success", data: resultArray)
response.setBody(string: jsonString)
response.completed()
}
最后在Xcode
中直接编译运行,运行成功后在浏览器里输入URL:http://localhost:8181/getColumn就能获取到json数据了。
查询数据库表里的数据已经完成,插入数据可以自己编写实践。后面会更新进行部署服务的一些实践操作。
下面附上本文的demo链接
错误解决办法
引用
Perfect-MySQL
库然后执行swift build
报错,如果是这种错误其实是库里面的
swift
文件报错了,我们可以打开工程,找到PerfectMySQL
库,然后按照下面的方式改好,在Xcode
里编译下就好了。