基于轻量型Web服务器Raspkate的RESTful API的实现
在上一篇文章《Raspkate - 基于.NET的可運行于樹莓派的輕量型Web服務器》中,我們已經了解了Raspkate這一輕量型Web服務器,今天,我們再一起了解下如何基于Raspkate實現簡單的RESTful API。
模塊
首先讓我們了解一下“模塊”的概念。Raspkate的模塊包含了一組能夠提供完整業務功能的HTTP處理器(Handler),例如,在Raspkate的源代碼庫中,默認提供了兩個模塊:Default和RaspberryPi,它們分別位于兩個不同的C#項目中:
Raspkate.Modules.Default
Raspkate.Modules.RaspberryPi
Default模塊包含了一個標準的靜態文件訪問服務/處理器,以及一個能夠讀取并返回服務器信息的RESTful API控制器;而RaspberryPi模塊則提供了一個訪問樹莓派信息頁靜態文件的處理器,以及一個讀取樹莓派信息的RESTful API控制器。當然,在這里靜態文件訪問處理都是由FileHandler負責,而RESTful API的處理則由ControllerHandler完成。雖然這兩個模塊使用了相同類型的Handler,但它們所專注的業務功能完全不同,而且它們是相互隔離,獨立執行的。
Raspkate中每個模塊都被存放于modules目錄下的某個子目錄中,在Raspkate服務啟動時,會掃描modules目錄下的所有程序集,定位所有繼承于RaspkateModule類的子類,并根據類型定義對Handler進行初始化然后注冊到Raspkate服務中,以便這些Handler能夠為HTTP請求提供服務。當然,這些模塊也可以放在其它目錄下,但這就需要修改Raspkate服務的配置文件RaspkateService.exe.config,把模塊所在的目錄添加到modules節點下,例如:
| 1 2 3 4 5 6 7 8 9 10 11 12 1 14 | <? xml? version="1.0" encoding="utf-8" ?> < configuration > ?? < configSections > ???? < section? name="raspkateConfiguration" type="Raspkate.Config.RaspkateConfiguration, Raspkate"/> ?? </ configSections > ?? < raspkateConfiguration? xmlns="urn:Raspkate.Config" prefix="http://127.0.0.1:9023/"> ???? < modules > ?????? < add? path="modules"/> ?????? < add? path="d:\\test" relative="false" /> ???? </ modules > ?? </ raspkateConfiguration > </ configuration > |
在模塊的注冊類型中(也就是繼承于RaspkateModule類的子類中),只需要返回該模塊能夠提供的Handler實例即可。接下來,讓我們一起看看,如何開發一個自己的模塊,并通過注冊ControllerHandler,向調用者提供RESTful API服務。
案例:計算器
最簡單的不過就是計算器運算:加、減、乘、除。那么最最簡單的就是計算兩個整數的和,好吧,就以這個為例,開始我們的RESTful API開發之旅。
首先,打開Visual Studio 2013,新建一個C#類庫(Class Library)項目,項目命名為RaspkateCalculatorModule,注意.NET Framework至少選擇4.5.2以上(老版本的Framework除了2.0以外,Microsoft都不再官方支持了)。成功創建項目后,添加對Raspkate.dll的引用。
然后,在這個項目中新建一個名為CalculatorController的類,代碼如下:
| 1 2 3 4 5 6 7 8 9 1 | [RoutePrefix( "calc" )] public? class? CalculatorController : RaspkateController { ???? [HttpGet] ???? [Route( "add/{a}/{b}" )] ???? public? int? Add( int? a, int? b) ???? { ???????? return? a + b; ???? } } |
接著,在這個項目中新建一個名為Module的類,代碼如下:
| 1 2 3 4 5 6 7 8 9 10 1 | internal? sealed? class? Module : RaspkateModule { ???? public? Module(ModuleContext context) ???????? : base (context) ???? { } ???? protected? override? IEnumerable<IRaspkateHandler> CreateHandlers() ???? { ???????? yield? return? new? ControllerHandler( "CalculatorController" , ???????????? new? [] { typeof (CalculatorController) }); ???? } } |
OK,萬事俱備,只欠東風啦!回到Raspkate中,將RaspkateService.exe.config稍微改動一下,將該模塊的輸出目錄添加到modules節點中,即可直接啟動RaspkateService.exe程序了:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 30 31 32 33 34 35 36 37 38 | <? xml? version="1.0" encoding="utf-8" ?> < configuration > ?? < configSections > ???? < section? name="raspkateConfiguration" type="Raspkate.Config.RaspkateConfiguration, Raspkate"/> ???? < section? name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> ?? </ configSections > ?? < raspkateConfiguration? xmlns="urn:Raspkate.Config" prefix="http://127.0.0.1:9023/"> ???? < modules > ?????? < add? path="modules"/> ?????? < add? path="C:\Users\chenqn\Documents\visual studio 2013\Projects\RaspkateCalculatorModule\RaspkateCalculatorModule\bin\Debug" relative="false"/> ???? </ modules > ?? </ raspkateConfiguration > ?? < log4net > ???? < appender? name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> ?????? < layout? type="log4net.Layout.PatternLayout"> ???????? < conversionPattern? value="%utcdate{DATE} [%thread] %level %logger - %message%newline"/> ?????? </ layout > ???? </ appender > ???? < appender? name="FileAppender" type="log4net.Appender.FileAppender"> ?????? < file? value="logs/raspkate.log" /> ?????? < appendToFile? value="true" /> ?????? < lockingModel? type="log4net.Appender.FileAppender+MinimalLock" /> ?????? < layout? type="log4net.Layout.PatternLayout"> ???????? < conversionPattern? value="%date [%thread] %level %logger - %message%newline" /> ?????? </ layout > ???? </ appender > ???? < root > ?????? < level? value="INFO"/> ?????? < appender-ref? ref="ConsoleAppender"/> ?????? < appender-ref? ref="FileAppender" /> ???? </ root > ?? </ log4net > ?? < startup > ???? < supportedRuntime? version="v4.0" sku=".NETFramework,Version=v4.5.2" /> ?? </ startup > </ configuration > |
啟動程序后,你可以在輸出的日志中注意到,CalculatorController已經被注冊到ControllerHandler當中,進而可以開始提供HTTP請求的服務了:
請打開你的瀏覽器,在地址欄中輸入:
| 1 | http://127.0.0.1:9023/calc/add/12/30 |
那么,你應該看到的是:
看來Raspkate服務已經將計算結果返回給你了。怎么樣?使用Raspkate開發RESTful API是不是非常快捷?接下來讓我們看看更加有意思的特性。
案例:計算器(進階)
剛才我們的計算器還是太簡單,接下來我打算讓這個計算器能夠計算復數(包括虛數部分)的乘法。同學們是否還記得復數相乘的計算公式?
OK,也就是我們的RESTful API需要接收兩個復數,每個復數都要包含實數?r?和虛數?i?兩個部分,返回值也應該包含實數和虛數兩個部分。那么,我們的CalculatorController就可以寫成這樣:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [RoutePrefix( "calc" )] public? class? CalculatorController : RaspkateController { ???? [HttpGet] ???? [Route( "add/{a}/{b}" )] ???? public? int? Add( int? a, int? b) ???? { ???????? return? a + b; ???? } ???? [HttpPost] ???? [Route( "mul" )] ???? public? dynamic Multiplicity([FromBody] dynamic input) ???? { ???????? var? a = input.x.r; // 第一個數的實數部分 ???????? var? b = input.x.i; // 第一個數的虛數部分 ???????? var? c = input.y.r; // 第二個數的實數部分 ???????? var? d = input.y.i; // 第二個數的虛數部分 ???????? return? new? { z = new? { r = a * c - b * d, i = b * c + a * d } }; ???? } } |
重新運行Raspkate服務,打開能夠發出HttpPost請求的測試客戶端(我用的是Fiddler),看看我們的程序是否可以正確執行:
測試成功,RESTful API已經以JSON格式返回了我們需要的計算結果。
總結
從上面的演示可以看到,Raspkate服務中RESTful API的實現,沿用了類似微軟ASP.NET Web API的編程習慣,包括:
Controller的編程模型(ASP.NET Web API中使用ApiController作為基類,此處使用RaspkateController作為基類)
Attribute Routing
HttpGet和HttpPost兩種HTTP方法(其它的暫未實現)
FromBody特性修飾符,使得方法的某些參數可以直接從HTTP Post Body中取值
對dynamic類型、匿名類型的支持
相比之下,Raspkate服務所提供的RESTful API編程更為簡單快捷。今后如果這部分的確有應用的話,可以對整個結構作進一步完善。
相關文章:?
Raspkate - 基于.NET的可運行于樹莓派的輕量型Web服務器
在樹莓派下安裝Mono環境
樹莓派上安裝mono和jexus運行ASP.NET程序
樹莓派2發布:四核 CPU+1G RAM 硬件升級不加價,支持Windows 10
陳晴陽(Sunny Chen),2003年畢業于中南大學鐵道校區。高級程序員,系統分析員,微軟MVP(Visual C#)。cnblogs網名daxnet,并打算以該名闖蕩IT江湖。MicrosoftDynamics?AX、Microsoft .NET/C#以及領域驅動設計(DDD)的狂熱愛好者。
原文地址:http://www.cnblogs.com/daxnet/p/5326992.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
贊賞
人贊賞
總結
以上是生活随笔為你收集整理的基于轻量型Web服务器Raspkate的RESTful API的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 来自.NET FM的感谢信
- 下一篇: 3分钟看完Build2016 Day 1