Swift Vapor服务器配置及使用

vapor服务器SSL配置 https://www.jianshu.com/p/93c0d6ac5d80

前言:Swift服务器开发,主要有四个框架perfect,vapor,kitura,zewo它们之间的优异和区别,各位自己去了解。之前笔者曾研究过perfect框架,总结下笔者的感悟。perfect框架目前只能作为后台开发框架,而vapor框架,笔者所了解的,除了能作为后台开发框架,还能作为前端开发框架。总体功能上,vapor比perfect要多,但从单一的服务器功能开发上来说,perfect要比vapor高校,使用简单,这点开发者可以自己去体会。但在集成和配置方面,vapor的优势要比perfect大,vapor无论在mac上还是在linux服务器上,都比perfect要容易集成的多。个有优劣,开发者自行选择,本文简略讲下vapor的集成,重点在于其用法。
关于vapor的集成,已有很多文章,但是大多都是没有及时更新,随着Swift语法的更新,不同版本在集成上,会遇到不同的问题,所以这里建议大家,在集成的时候,参考

官方文档:https://docs.vapor.codes/2.0/getting-started/install-on-macos/

笔者就是查看其它文章时,没有集成成功,而参考官方文档集成成功的。

perfect框架搭建及使用 http://www.jianshu.com/p/599c5e874fda

一:Mac OS上集成Vapor

1,打开终端运行以下命令

屏幕快照 2017-09-18 下午1.38.08.png

现在你的mac已经有Swift3.1或者更高版本了,笔者写文章的时候,是Swift3.1

2,install HomeBrew 初始化HomeBrew

如果你还没有安装Homebrew,安装它!它对于安装像OpenSSL、MySQL、Postgres、Redis、SQLite等软件依赖非常有用。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

3,Add Homebrew Tap

brew tap vapor/homebrew-tap
brew update
brew install vapor

4,创建vapor项目

vapor new 项目名

出现下面这个大仙桃的时候,就表示你创建成功了


屏幕快照 2017-09-18 下午1.45.52.png

5,使用终端,进入到你刚才创建的项目的根目录执行build命令

耐心等待吧,看个小电影什么的。

  vapor build 

一般不会失败的,失败了,就重来一次吧,成功之后,执行run命令,运行起来服务器

vapor run
屏幕快照 2017-09-18 下午1.56.44.png

这就代表着你的服务器运行成功了,可以去测试里面的接口了,不过笔者在测试中发现,在mac OS上,通过终端来运行服务器,它里面自带的接口可以访问,但是你自己写的访问不了。笔者自己建了.xcodeproj文件之后,用xcode运行可以访问

终端内终止启动

control 、

创建.xcodeproj文件

vapor xcode -y

然后你可以使用xcode打开了,然后运行

屏幕快照 2017-09-18 下午2.00.07.png

二:在linux服务器上集成vapor

不在累赘,极少有去配置的

eval "$(curl -sL https://apt.vapor.sh)"
RUN /bin/bash -c "$(wget -qO- https://apt.vapor.sh)"
wget -q https://repo.vapor.codes/apt/keyring.gpg -O- | sudo apt-key add -
echo "deb https://repo.vapor.codes/apt $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/vapor.list
sudo apt-get update
sudo apt-get install swift vapor
eval "$(curl -sL check.vapor.sh)"
检查swift版本
swift —version
检查vapor版本
vapor —version
进入主目录 cd / 创建项目
vapor new 项目名   

剩下的与之前一样,注意不能创建.xcodeproj文件

三:Vapor使用篇

接口在这两个文件内,哪个文件里写都可

屏幕快照 2017-09-18 下午2.07.56.png

1,添加一个get接口

drop.get("接口名"){ req in

    return "请求结果"
}

2,添加一个post接口

drop.post("testAPi"){ req in
    return "请求结果"
}

3,返回JSON数据,get和post接口方法相同

drop.post("postBeier") { request in
    return try JSON(node:["message":"bei er te lun"])
}

4,获取请求参数,get和post获取方式相同

drop.post("postBeier") { request in

    guard let name = request.data["zykey"]?.string else{
        throw Abort.badRequest
    }

    return try JSON(node:["message":"bei er te lun","name":name])
}

5,多路径请求

//http://localhost/z/x/h

drop.get("z", "x", "h") { request in
    return "You requested /z/x/h"
}

6,返回一个网页

 drop.get("zxh") { request in
return Response(redirect: "http://www.jianshu.com/u/d20fcc519630")
}

7,返回图片

drop.get("testImage"){ req in
    return try Response.init(filePath: "/Users/xiaocangkeji/Desktop/001.png");
}

8,上传单张图片

 drop.post("upImage"){ request in
    let img = request.formData?["img"];
    let imgPart = img?.part;
    let imgBody = imgPart?.body;

    if let imgDat = imgBody{
        let data = NSData.init(bytes: imgDat, length: (imgBody?.count)!);
        try?data.write(to: URL.init(fileURLWithPath: "/Users/xiaocangkeji/Desktop/011.jpg"), options: NSData.WritingOptions.atomic);
    } else{
        throw Abort.badRequest
    }

    return try JSON(node:["message":"success"]);
}

9,多图上传,非最优方案,日后更新

drop.post("upMoreImage"){ request in
  for i in 1...9{
    //根据字段名获取图片信息
    let img = request.formData?["img\(i)"];
    let imgPart = img?.part;
    let imgBody = imgPart?.body;
    if let imgDat = imgBody{
        //将bytes数据转为Data类型数据
        let data = NSData.init(bytes: imgDat, length: (imgBody?.count)!);
        //存到电脑桌面
        try?data.write(to: URL.init(fileURLWithPath: "/Users/xiaocangkeji/Desktop/img\(i).jpg"), options: NSData.WritingOptions.atomic);
    }
  }
   return try JSON(node:["message":"success"]);
}

10,上传视频 统归于上传文件

其实和上传图片一样,无论上传图片,视频,word,音频文件等,上传的都是文件,可以统一归属于上传文件类,步骤只是在存储时改下文件格式而已,开发者也可以让接口使用者,在客户端指定存储类型,这样只需要写一个接口就可以了。

drop.post("upVideo"){ request in
    let video = request.formData?["video"];
    let videoPart = video?.part;
    let videoBody = videoPart?.body;
    //文件名 建议使用时间戳
    let fileName = String.init(format: "%.0f", Date().timeIntervalSince1970);
    //文件格式 这里让客户端传来
    let fileType = request.data["fileType"]?.string
    //如果没有传文件类型则返回错误
    guard (request.data["fileType"]?.string) != nil else{
        throw Abort.badRequest
    }
    if let videoDat = videoBody{
    let data = NSData.init(bytes: videoDat, length: (videoBody?.count)!);
        try?data.write(to: URL.init(fileURLWithPath: "/Users/xiaocangkeji/Desktop/" + fileName + "." + fileType!), options: NSData.WritingOptions.atomic);
    } else{
    throw Abort.badRequest
    }

    return try JSON(node:["message":"success"]);
}

11 返回一个html代码类型的网页

此方法的作用,各位自己琢磨

drop.get("BRService","getAnimalHelpInfo"){ request in


let res = Response.init(status: .ok, body: "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><title>宠宝儿寻狗启示</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head><body><center><lable style=\"font-size:20px\">寻找寻找小花猫 </lable></center><div class=\"headerDiv\"><img class=\"headerImg\" src=\"http://47.98.152.252:8081/testImage?path=UserHeaderImg&name=520180419075931.jpg\" /><div class=\"nameLabel\">贝尔特伦 </div><div class=\"timeLabel\">2018-17-19</div></div><div><label class=\"infoLabel\">地址:</label><label class=\"infoLabel\">南京市 </label><a  href=\"map://chongbaoer\" style=\"font-size:14px\">查看地图 </a></div><div><label class=\"infoLabel\">联系电话 :</label><label class=\"infoLabel\">13260750669 </label></div><div><label class=\"infoLabel\">微信号  :</label><label class=\"infoLabel\">ZXHTD123456 </label></div><label class=\"contentLabel\">wo men我们zhe li我们这里dou shi我们这里都是s l d k j f我们这里都是善良的会计法 s十点f l s十是雷锋精神的理解点发牢骚s l d j f十点发牢骚善良的肌肤带来 s l f j s d l j</label><div><img width=\"100%\" src=\"http://47.98.152.252:8081/testImage?path=UserHeaderImg&name=520180419075931.jpg\" /></div></body></html><style type=\"text/css\">.headerDiv{height: 80px;}.headerImg{width:60px;height:60px;margin-left: 10px;margin-top: 10px;border-radius:60px;}.nameLabel{margin-left: 80px;margin-top: -55px;}.timeLabel{margin-left: 80px;margin-top: 10px;}.infoLabel{font-size: 15px;}.contentLabel{font-size: 14px;}</style>")

 return res
}

四:SQLite 数据操作篇

数据的操作,其实就是增删改查四类。进行数据库的操作了,开发者都有自己的数据库操作工具了,笔者用的Navicat工具。vapor支持多种数据库操作框架,mysql,sqlite等等,这里我直接用的sqlite,要使用mysql的话,还得配置。

使用前的准备

打开项目中的sqlite文件夹,可以看到里面有三个类


屏幕快照 2017-09-21 下午3.02.43.png

这个是人家封装好的sqlite的库,一开始肯定都不知道怎么使用,没关系,咱们可以猜,然后点进去看。
1,第一个sqlite+result看名字,应该是跟结果有关系的,那他应该请求结果的处理类。
2,第二个sqlite+statement (拿出我的终极武器---有道,翻一下后面单词的意思)连起来就是sqlite的声明之类的意思,联想平时使用sqlit的方法,那这里应该是跟结果集有关系,那就跟数据绑定有关系。
3,第三个 sqlite 看名字不用想了,一个库的总管家。
这几个文件开发者可以自己去研究研究,笔者这里,就直接写一些简单的用法(ps:笔者都还没研究透呢,无法给你们讲解,就不装这个逼了 0.0)。

导入Sqlite库

import SQLite

连接数据库

let zySql = try SQLite.init(path: "/Users/beier/Desktop/Vapor.db");

1,path为数据库DB文件路径
2,sqlite对象设为全局变量
3,连接时,数据库自动打开
(小细节:笔者建了一个名为Vapor的DB文件,然后建了一个名为UserList的表,表内字段有 id,name,addr,age,类型分别为INTEGER,TEXT,TEXT,INTEGER)

1,添加数据

drop.post("addUser"){ request in
    let name = request.data["name"]?.string
    let age = request.data["age"]?.string
    let addr = request.data["addr"]?.string
    if name == nil || age == nil || addr == nil{
        throw Abort.badRequest
    }
    let sqlStr = "insert into UserList (name,age,addr) values (?,?,?);"
    let result = try zySql.execute(sqlStr, prepareClosure: { (stmt) in
       //绑定数据
      try stmt.bind(name!)
      try stmt.bind(age!)
      try stmt.bind(addr!)
  })
    print(result)
    return try JSON(node:["message":"success"]);
}
注意,sql语句中的字段顺序,要和下面绑定数据的顺序保持一致,不然数据会错乱。

1,PostMan调用接口

屏幕快照 2017-09-21 下午3.26.18.png

2,刷新UserList表中数据

屏幕快照 2017-09-21 下午3.25.51.png

可以看到,数据已经添加到数据库里面了。

2,更改数据

drop.post("updateUser"){ request in
    let name = request.data["name"]?.string
    let age = request.data["age"]?.string
    let addr = request.data["addr"]?.string
    let userId = request.data["id"]?.string
    if name == nil || age == nil || addr == nil || userId == nil{
        throw Abort.badRequest
    }
    let sqlStr = String.init(format: "update UserList set name='%@',age=%@,addr='%@' where id=%@", name!,age!,addr!,userId!)
let result = try zySql.execute(sqlStr, prepareClosure: { (stmt) in
  
    })
    print(result)
    return try JSON(node:["message":"success"]);

}

3,删除数据

drop.post("deletUser"){ request in
    let userId = request.data["id"]?.string
    if userId == nil{
        throw Abort.badRequest
    }
    let sqlStr = "delete from UserList where id=" + userId! + ";"
    let result = try zySql.execute(sqlStr, prepareClosure: { (stmt) in
   
    })
    print(result)

    return try JSON(node:["message":"success"]);
}

4,查询数据

drop.post("searchUser"){ request in
    let userId = request.data["id"]?.string
    if userId == nil{
        throw Abort.badRequest
    }
    let sqlStr = "select *from UserList where id=" + userId! + ";"
    let result = try zySql.execute(sqlStr, prepareClosure: { (stmt) in
    
    })
    //result就是一个数组
    var dataArr:Array<Dictionary<String,Any>> = []
    for rowData in result{
        let data = rowData.data
        var dic:Dictionary<String,Any> = [:]
        let name = data["name"]?.wrapped
        let age = data["age"]?.wrapped
        let addr = data["addr"]?.wrapped
        let userID = data["id"]?.wrapped
        dic["name"] = name
        dic["age"] = age
        dic["addr"] = addr
        dic["id"] = userID
        dataArr.append(dic)
    }

    return try JSON(node:["message":"success","data":dataArr]);
}

关于sql语句,需要各位开发者去自学了,对数据库操作,sql语句很重要,各位可以花一些时间记一些常用的sql语句。

注释:可能遇到的问题

1,开发者添加的接口,通过终端启动,或者在服务器上启动,访问404,而通过建立的xcode文件启动,就能访问。
解决方案:终端启动前执行 vapor build一次,以后再启动即可访问。
2,更改端口号
启动时命令变为 vapor run serve -—port=8081
或者修改Config文件夹下server.json文件中的端口号

备注:转载请标注来源及署名,谢谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 张秋分享:今天的学习,明白了穿过对错看问题。不要太在意孩子对待问题和处理问题的结果,重点放在孩子实践过程中积极点上...
    程蕾阅读 292评论 0 1
  • 海子:我们最终都要远行,最终都要与稚嫩的自己告别,告别是通向成长的苦行之路。 每个人都是一本完整的书,是有故事的灵...
    小兵写作业阅读 1,440评论 34 44
  • 291976-陈国艳《2017-03-01》 【第18天总结】 A、目标完成情况 1、背诵5A200字完成100%...
    国艳更文的365天阅读 92评论 0 0