今天开始用 swift 写服务器 (一)

3,362 阅读6分钟
原文链接: blog.csdn.net

用swift写服务器的已经不是什么新鲜事了,这几年的发展,也是swift在服务端的表现越来越成熟,目前比较流行服务端框架主要有Vapor、Perfect、Kitura和Zewo,他们各有长短,本人这次主要是使用Perfect来写的,因为Perfect的功能比较完善,在GitHub上具有1W+的星,而且有一个非常重要的原因是,Perfect有中文文档。

Perfect 包括了您所期待的所有基本功能,包括路由、websockets 基于 HTTP 的网络套接字、TLS(SSL)通信加密、Mustache 模板和 Markdown 模板、JSON 结构化数据等等,以及全部其他所有 Swift 后台框架加在一起才有的 XML 结构化数据、苹果推送消息 APNS、MqTT 消息队列和 SMTP 邮件发送,甚至大数据也支持Perfect 的数据库支持非常广泛,其原生 SQL 驱动包括 MySQL、SQLite、PostgreSQL 和 MariaDB,还支持 MongoDB、Redis、CouchDB 甚至还包括 FileMaker(苹果自己的数据库 Swift 都不支持,Perfect 反过来支持——译者注)。Perfect 据说还部分支持微软的 ODBC,即多种数据库的底层兼容界面——有点像 ORM,但是以 C 函数库为基础。提到 ORM 数据库对象关系自动化管理,Perfect 有 StORM 并完整实现了 PostgreSQL、MySQL、CouchDB 和 SQLite。

经过对Perfect框架一周的学习,基本可以开启服务,该踩的坑也踩的差不多了,然后打算用Perfect写一个后台,希望可以上线使用。

本篇主要介绍使用Perfect开启第一个服务,后续还会持续更新。对于环境配置这里就不多介绍了,Perfect官方文档和GitHub上都有。这里是使用MacOS系统和Xcode进行开发的


废话不多说,现在开始创建我们swift服务器,先使用swift的SPM(Swift Package Manager)创建和管理我们的工程

先创建一个空文件夹,然后使用终端创建我们的框架管理工程,如果你是iOS开发工程师,你可以把它看做cocoapods

  1. swift package init  
swift package init

这时,就创建出没有xcodeproj的工程,使用命令创建xcodeproj,这样就可以使用Xcode来编译了

  1. swift package generate-xcodeproj  
swift package generate-xcodeproj

然后打开这个工程,选择Package.swift这个文件,如下图编辑,或按官方文档编辑都可以


编辑完成以后,使用命令

  1. swift build  
swift build

然后就会自动从GitHub上把需要的框架下载下来。这样,我们的框架管理工程就算暂时建好了,以后如果要添加新的方法,只要在url的数组中添加git地址就可以了。但是这里有两个坑,首先每次更新或添加库或框架,xcodeproj就需要重新创建一次,不然无法引用到新库或新框架;其次,在source文件夹如果发生任何改动,库或框架的更新就会失败。这就是为什么我要专门建一个工程来管理这些框架或者库(这是我踩的最恶心的坑)。为了解决这个大坑,就再创建一个项目工程,然后使用workspace来管理,就像iOS中,使用了cocoapods一样。项目工程的创建和上面基本一样,但是在创建的时候,需要有一个可执行文件。因此,创建命令和之前的不一样,

  1. swift package init --type executable  
swift package init --type executable
还有,就是在Package.swift文件中不需要添加任何git地址,因为已经有一个工程帮助管理了。

workspace的创建:

打开Xcode,然后File->New->Workspace



这样就创建出了一个空的workspace,然后添加工程


添加完需要的工程后,需要给我们的项目工程做配置,让它与框架工程关联,可以使其引用需要的模块



然后,我们可以开始写代码啦。

首先,我先建了一个server类和一个接口类以及一个管理接口的文件


在server类中,配置我们的服务

  1. import PerfectHTTPServer  
  2. import PerfectHTTP  
  3. import PerfectLib  
  4.   
  5. class CXServer {  
  6.     let server = HTTPServer()  
  7.       
  8. //    static let shareServer = CXServer()  
  9.       
  10.     init() {  
  11.         setupServer()  
  12.     }  
  13.       
  14.     private func setupServer() {  
  15.         server.serverPort = 8080  
  16.         server.serverName = "localhost"  
  17.         server.documentRoot = "./webroot"  
  18.     }  
  19.       
  20.     func configRoutes(_ routes: [Routes]) {  
  21.         for route in routes {  
  22.             server.addRoutes(route)  
  23.         }  
  24.     }  
  25.       
  26.       
  27.     //MARK: - 启动服务  
  28.     func startServer() {  
  29.         do {  
  30.             // Launch the servers based on the configuration data.  
  31.             //try HTTPServer.launch(configurationData: confData)  
  32.             try server.start()  
  33.         } catch {  
  34.             fatalError("\(error)") // fatal error launching one of the servers  
  35.         }  
  36.     }  
  37.       
  38. }  
import PerfectHTTPServer
import PerfectHTTP
import PerfectLib

class CXServer {
    let server = HTTPServer()
    
//    static let shareServer = CXServer()
    
    init() {
        setupServer()
    }
    
    private func setupServer() {
        server.serverPort = 8080
        server.serverName = "localhost"
        server.documentRoot = "./webroot"
    }
    
    func configRoutes(_ routes: [Routes]) {
        for route in routes {
            server.addRoutes(route)
        }
    }
    
    
    //MARK: - 启动服务
    func startServer() {
        do {
            // Launch the servers based on the configuration data.
            //try HTTPServer.launch(configurationData: confData)
            try server.start()
        } catch {
            fatalError("\(error)") // fatal error launching one of the servers
        }
    }
    
}

在testRoute中的代码

  1. import PerfectHTTP  
  2.   
  3.   
  4. class TestRoute {  
  5.     var testRoute = Routes()  
  6.       
  7.     init() {  
  8.         testRoute.add(method: .get, uri: "/") { (request, response) in  
  9.             response.setHeader(.contentType, value: "text/html")  
  10.             response.appendBody(string: "<html><title>Hello, world!</title><body>Hello, world!</body></html>")  
  11.             response.completed()  
  12.         }  
  13.     }  
  14. }<span style="color:#ffffff;">  
  15. </span>  
import PerfectHTTP


class TestRoute {
    var testRoute = Routes()
    
    init() {
        testRoute.add(method: .get, uri: "/") { (request, response) in
            response.setHeader(.contentType, value: "text/html")
            response.appendBody(string: "<html><title>Hello, world!</title><body>Hello, world!</body></html>")
            response.completed()
        }
    }
}
接口管理文件中的代码

  1. let test = TestRoute().testRoute  
let test = TestRoute().testRoute
在程序入口main文件中开启服务

  1. let server = CXServer()  
  2. server.configRoutes([test])  
  3. server.startServer()  
let server = CXServer()
server.configRoutes([test])
server.startServer()


然后运行,这样,我们的第一个服务就开启了,可以在网页中输入http://0.0.0.0:8080/试试,效果如下




大家可以有空尝试一下,说不定swift真会火到和JAVA一样

项目地址:https://github.com/NickQCX/ServerOfPerfect

参考:

http://geek.csdn.net/news/detail/191056#10006-weixin-1-52626-6b3bffd01fdde4900130bc5a2751b6d1

https://swift.org/package-manager/#conceptual-overview

https://github.com/PerfectlySoft/Perfect