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,打开终端运行以下命令
现在你的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 项目名
出现下面这个大仙桃的时候,就表示你创建成功了
5,使用终端,进入到你刚才创建的项目的根目录执行build命令
耐心等待吧,看个小电影什么的。
vapor build
一般不会失败的,失败了,就重来一次吧,成功之后,执行run命令,运行起来服务器
vapor run
这就代表着你的服务器运行成功了,可以去测试里面的接口了,不过笔者在测试中发现,在mac OS上,通过终端来运行服务器,它里面自带的接口可以访问,但是你自己写的访问不了。笔者自己建了.xcodeproj文件之后,用xcode运行可以访问
终端内终止启动
control 、
创建.xcodeproj文件
vapor xcode -y
然后你可以使用xcode打开了,然后运行
二:在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使用篇
接口在这两个文件内,哪个文件里写都可
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,多路径请求
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文件夹,可以看到里面有三个类
这个是人家封装好的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调用接口
2,刷新UserList表中数据
可以看到,数据已经添加到数据库里面了。
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文件中的端口号