文档章节

Project Perfect让Swift在服务器端跑起来-让Perfect更Rails (五)

猴亮屏
 猴亮屏
发布于 2016/06/02 10:13
字数 1006
阅读 20
收藏 0

编者语:努力会有回报,加油吧!

       关于Perfect,已经从开发工具,原理,运行环境做了介绍。今天开始进入架构。其实,Perfect更像Java Servlet,我很喜欢Rails这种方式去构建。说句真心话,对于我这种.NET程序员,更希望只是换种语言,毕竟现在ASP.NET Core 很Cool。好!让大家看看我对Perfect的改造。

       再说说Perfect的运行原理。其实当用户发送请求时,都是首先找到PerfectServerModuleInit()这个方法,根据指定规则去找对应的Handlers,之后通过Handlers的方法handleRequest去处理相对应的事务处理。我们把这个流程用图的方式表示一下。
       
       其实handleRequest很接近我们的Controller,如果做成一个类似Rails的框架不是不可能的。这里我参考了在Github上的一个项目(https://github.com/groovelab/SwiftBBS)大家也可以去看看。

       首先我要扩展一下PerfectLib中的WebRequest和WebResponse这两个方法,针对WebRequest增加了action和参数,由于用到Rails思想,所以action是不能缺少的,后面的参数也是。而WebRepsonse把页面渲染和数据JSON输出做成统一的方法。这样做的好处就是减少了每个Handler一堆重复的工作.对应的文件是extension.Swift

[plain] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. //  
  2. //  extension.swift  
  3. //  MVCDemo  
  4. //  
  5. //  Created by 卢建晖 on 16/2/27.  
  6. //  Copyright © 2016年 Kinfey. All rights reserved.  
  7. //  
  8.   
  9. import PerfectLib  
  10.   
  11. extension WebRequest {  
  12.     var action: String {  
  13.         return urlVariables["action"] ?? "index"  
  14.     }  
  15.     var acceptJson: Bool {  
  16.         return httpAccept().contains("application/json")  
  17.     }  
  18. }  
  19.   
  20. extension WebResponse {  
  21.     func render(templatePath: String, values: MustacheEvaluationContext.MapType) throws -> String {  
  22.         let fullPath =  templatePath  
  23.         let file = File(fullPath)  
  24.           
  25.         try file.openRead()  
  26.         defer { file.close() }  
  27.         let bytes = try file.readSomeBytes(file.size())  
  28.           
  29.         let parser = MustacheParser()  
  30.         let str = UTF8Encoding.encode(bytes)  
  31.         let template = try parser.parse(str)  
  32.           
  33.         let context = MustacheEvaluationContext(map: values)  
  34.         context.filePath = file.path()  
  35.         let collector = MustacheEvaluationOutputCollector()  
  36.         try template.evaluatePragmas(context, collector: collector, requireHandler: false)  
  37.         template.evaluate(context, collector: collector)  
  38.         return collector.asString()  
  39.     }  
  40.       
  41.     func renderHTML(templatePath: String, values: MustacheEvaluationContext.MapType) throws {  
  42.         let responsBody = try render(templatePath, values: values)  
  43.         appendBodyString(responsBody)  
  44.         addHeader("Content-type", value: "text/html")  
  45.     }  
  46.       
  47.     func outputJson(values: [String:JSONValue]) throws {  
  48.         addHeader("content-type", value: "application/json")  
  49.         let encoded = try values.jsonEncodedString()  
  50.         appendBodyString(encoded)  
  51.     }  
  52. }  

       接下来我们做一个Controller.swift的基类,这个基类继承自RequesHandler包括了每个action所返回的结果。我这里参照.NET Core 把返回结果封装成IActionResult.并把handlerRequest做成一个统一处理的方法。

[plain] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. //  
  2. //  Controller.swift  
  3. //  MVCDemo  
  4. //  
  5. //  Created by 卢建晖 on 16/2/26.  
  6. //  Copyright © 2016年 Kinfey. All rights reserved.  
  7. //  
  8.   
  9. import PerfectLib  
  10.   
  11. class Controller : RequestHandler{  
  12.       
  13.       
  14.     enum IActionResult {  
  15.         case View(templatePath: String?, values: [String: Any])  
  16.         case Redirect(url: String)  
  17.         case Error(status: Int, message: String)  
  18.     }  
  19.       
  20.       
  21.     var request: WebRequest!  
  22.     var response: WebResponse!  
  23.       
  24.       
  25.     func handleRequest(request: WebRequest, response: WebResponse) {  
  26.         self.request = request  
  27.         self.response = response  
  28.           
  29.           
  30.           
  31.         defer {  
  32.             response.requestCompletedCallback()  
  33.         }  
  34.           
  35.         do{  
  36.           
  37.         switch try Action(request.action) {  
  38.         case let .View(templatePath, responseValues):  
  39.             let values = responseValues  
  40.             if request.acceptJson {  
  41.                 try response.outputJson(values)  
  42.             } else if let templatePath = templatePath {  
  43.                 try response.renderHTML(templatePath, values: values)  
  44.             }  
  45.         case let .Redirect(url):  
  46.             response.redirectTo(url)  
  47.         case let .Error(status, message):  
  48.             response.setStatus(status, message: message)  
  49.             break;  
  50.         }  
  51.         }catch let e {  
  52.             print(e)  
  53.         }  
  54.     }  
  55.       
  56.     func Action(action: String) throws -> IActionResult {  
  57.         return .Error(status: 500, message: "need implement")  
  58.     }  
  59.       
  60. }  

       为何要这样做,这里有一个方法Action,根据URL Routing去找到对应的Action方法,之后通过handlerRequest处理返回对应的页面或者JSON数据,我们做一个HomeController.swift看看。

[plain] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. import PerfectLib  
  2.   
  3. class HomeController: Controller {  
  4.       
  5.     override func Action(action: String) throws -> IActionResult {  
  6.           
  7.         switch request.action {  
  8.         case "about" :  
  9.             return try About()  
  10.         default:  
  11.             return try Index()  
  12.         }  
  13.           
  14.     }  
  15.       
  16.     func Index() throws -> IActionResult{  
  17.           
  18.         var values = [String: Any]()  
  19.           
  20.         values["str"]="Hello Swift MVC Framework"  
  21.           
  22.         return .View(templatePath: "Index.mustache", values: values)  
  23.     }  
  24.       
  25.     func About() throws -> IActionResult{  
  26.           
  27.         var values = [String: Any]()  
  28.           
  29.         values["str"]="Hello Swift MVC Framework"  
  30.           
  31.         return .View(templatePath: "About.mustache", values: values)  
  32.     }  
  33.       
  34.       
  35. }  

      这里就是我们改造后的HomeController,而对应的URL Routing我参照.NET Core的方式放在Startup.swift上

[plain] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. import PerfectLib  
  2.   
  3. public func PerfectServerModuleInit() {  
  4.       
  5.     Routing.Handler.registerGlobally();  
  6.     Routing.Routes["GET", ["/","/Home/{action}"] ] = { _ in return HomeController() }  
  7.       
  8.       
  9. }  

      最后我们把页面加上 index.mustache

[html] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <title>Swift MVC</title>  
  5. </head>  
  6. <body>  
  7. <h1>{{str}}</h1>  
  8. </body>  
  9. </html>  

 

     about.mustache

[html] view plain copy

 print?在CODE上查看代码片派生到我的代码片

  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4. <title>About</title>  
  5. </head>  
  6. <body>  
  7. <h1>This is Kinfey design</h1>  
  8. </body>  
  9. </html>  

    基本上就可以完成我们的Rails改造了,看看在Xcode的结构,很Rails,很.NET Core吧
    
    看看运行的过程,如图
    
    我们运行下
       

    
    这里补充一点,如果你要把页面模版在Xcode中使用必须要对Build Phase进行设置,在Copy Files中添加,需要设置Desination为Product Directory,如图
    
     今天说到这里,祝周末愉快!

本文转载自:http://blog.csdn.net/kinfey/article/details/50754770

猴亮屏

猴亮屏

粉丝 38
博文 542
码字总数 60882
作品 4
北京
Android工程师
私信 提问
Project Perfect让Swift在服务器端跑起来-引言(一)

编者语:今天是大年初一,先和大家简单说一句猴年快乐! 你认识Swift或者是在客户端,因为它是苹果用来开发客户端的新一代语言。在Swift开源后苹果让它不仅在MacOS/iOS上跑,也运行到了Linux...

微笑的江豚
2016/06/02
45
0
Project Perfect让Swift在服务器端跑起来-Hi Linux(二)

编者语:就这样就过完年了,话说大家开始回到各自的工作单位上,感觉还不错吧。开篇写了一个简单的入门,今天想说说怎么让Perfect项目在Linux上运行。 Swift开源后,苹果让Swift不仅在OSX/i...

微笑的江豚
2016/06/02
35
0
Project Perfect让Swift在服务器端跑起来-在Linux上创建你的Perfect项

编者语: 对于一个新事物,如果你花点心机还是有很多收获的。 前两篇,分别讲述了入门和在Linux下部署,现在得说说如何在Linux下开发了。在Linux下开发,相对比在Mac下开发更灵活。 我们先来看...

微笑的江豚
2016/06/02
82
0
Perfect:Swift 语言服务器端软件框架简介

Perfect:Swift 语言服务器端软件框架 Perfect 开源项目 参与 Perfect 开发 Slack 在线协同 Perfect:Swift 语言服务器端软件框架 Perfect是一组完整、强大的工具箱、软件框架体系和Web应用服...

rockford
2017/11/29
0
0
Project Perfect让Swift在服务器端跑起来-Perfect in Visual St

编者语 : 本系列文章已经被Perfect官方引用了,这种感觉很好,感恩!Thx all ! Visual Studio Code是一个轻量级的编辑器,但也功能丰富,通过插件你可以完成如Cordova,ReactNative,NodeJS,...

微笑的江豚
2016/06/02
17
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
5
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部