就算開發(fā) Android APP 也得懂一點API接口開發(fā)(二)之從零開始

承接上一篇文章,接下來會說些非常簡單的例子,也比較符合 Restful API 的規(guī)范,并且會選用 .NET Core 作為后臺開發(fā)平臺柱彻,使用 C# 作為開發(fā)語言,.NET Core 目前最新版本是 2.1 餐胀,很多人質疑 .NET 和 C#哟楷,覺得太老了,市場上已經沒有什么占有率了否灾,學校也不怎么交了卖擅,工作也不怎么好找了,被 Java 吊著打之類的墨技。在網(wǎng)絡中惩阶,或是在工作中,我使用的技術椏弁簦總是會被各種人 Diss断楷,這其中有使用 Java的,有使用 Python 的崭别,有使用 Go Lang 的冬筒,有使用 Ruby 的恐锣,甚至也有使用 Nodejs 的。每一種語言或平臺或 Framework 都有它的不足舞痰,覺得自己順手的才是最好的土榴。質疑 .NET 也完全沒必要,在企業(yè)應用中响牛,.NET 還占據(jù)很大的市場玷禽,甚至騰訊的支付清算網(wǎng)關也已經使用了 .NET Core 重寫了,如果現(xiàn)在開始學習 .NET 的話呀打,我覺得從 .NET Core 會是一個絕好的開端论衍。并且在我上家公司中,我建議了公司采用了 .NET Core + Nancy + SQLServer 完全重寫了服務后端和數(shù)據(jù)分析平臺聚磺,并且服務也是運行在 Cent OS 上,穩(wěn)定性也非常高炬丸。

.NET Core 入門非常簡單瘫寝,簡單到什么程序呢,我覺得任何使用過 Nodejs 和 Python 的都能上手稠炬,官網(wǎng)地址是:

https://www.microsoft.com/net/learn/get-started-with-dotnet-tutorial

開發(fā)工具也非常豐富焕阿,假如以前是用 Notepad++ 或 Sublime 寫 PHP 的碼農,可以使用 Vscode 首启,這是官方指定的編輯器暮屡,或者繼續(xù)使用 Notepad+。如果是 .NET 老碼農毅桃,可以繼續(xù)使用宇宙第一的 IDE Visual Studio 2018 community褒纲。如果是 Java 或者 Android 或者習慣腦漿噴射全家桶 (Jetbrains) 的碼農,可以使用 Rider钥飞,所以無論你以前使用什么語言莺掠,都能找到順手的工具。

這里读宙,我使用 Rider彻秆,因為和 Android Sutdio 界面基本相同,都是 Jetbrains 家的结闸,并確保你已經安裝了最新的 .NET Core唇兑,安裝完成后,使用 dotnet --version 查看一下版本號桦锄,并且我會使用 Fancy 作為 Web 框架扎附,而不是使用 .NET Core ,這有一個好處结耀,就是可以在 Windows帕棉、Linux针肥、Mac OS 下都可以運行,并且不論是 IIS 還是 Owin 承載方式都能運行起來香伴,甚至丟在一個虛擬主機上也能完整的運行起來慰枕。我之前寫了一個輕博客系統(tǒng)用來同步我的簡書文章,就是使用 Nancy 作為框架即纲,支持任何 .NET 運行環(huán)境和服務器軟件具帮,甚至可以生成靜態(tài)頁面,支持 GitPages 和任何靜態(tài)頁面服務低斋。

參見 http://1ll.co

讓我們先從一個學生管理系統(tǒng)說起蜂厅,這也是大多數(shù)例子常用的場景,首先創(chuàng)建一個 Solution膊畴,類型為 .NET Core Console Application掘猿。確保右側的選項卡中,Language 為 C#唇跨,F(xiàn)ramework 為 netcoreapp2.x稠通。

之后我們會在解決方案資源管理器中看見以下工程結構:

Program.cs 就是整個工程的入口點,也是 Main 方法所在的類买猖,就像是 MainActivity 一樣(雖然不太恰當)改橘,可以看到右側編輯器中代碼內容如下:

using System;

namespace StudentManagementSystem
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

點擊工具欄上的綠色三角形就可以啟動我們的第一個 .NET Core Console Application 了,旁邊的小蟲子圖標就是 Debug玉控,搞過 Android 開發(fā)用過 Android Studio 的都知道飞主。

之后會彈出下面的對話框,讓你做第一次運行配置高诺,如果不知道下面的每一項代表什么意思碌识,那就直接點擊 Run 就可以。

然后就可以在狀態(tài)窗口中看到結果輸出:

如果能正常進行到這一步虱而,我覺得是時候配置 Web 容器(框架)了丸冕,就像 Jetty 或者 Springboot 里的內置 Tomcat 一樣,它不直接處理業(yè)務邏輯薛窥,而是處理 HTTP 請求胖烛,路由等,然后由 Nancy 根據(jù)對應的路由來處理對應的業(yè)務诅迷,最終發(fā)布自身可以完成端口注冊監(jiān)聽佩番,不過在實際生產環(huán)境中都會使用反向代理服務器。

好的罢杉,扯遠了趟畏,在 .NET Core 中,我建議使用 Kestrel 作為 Web 容器服務器滩租,項目地址:

KestrelHttpServer: https://github.com/aspnet/KestrelHttpServer

Kestrel 是微軟開發(fā)的一個跨平臺的 Web 容器服務器赋秀,它基于 libuv 這個網(wǎng)絡庫開發(fā)的利朵。libuv 是一個抽象層,它在 Linux 上是由 libev 實現(xiàn)猎莲,在 Windows 上是由 IOCP 實現(xiàn)绍弟。

要引用第三方庫,我們使用包管理器 Nuget著洼,切換到 Nuget 任務窗格樟遣。

然后搜索 Kestrel 關鍵字,選擇 Microsoft.AspNetCore.Server.Kestrel 并在右側窗格中加入到項目中引用身笤。

同理依次添加下列第三方庫的引用:

Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Owin
Microsoft.Extensions.Configuration.Binder
Microsoft.Extensions.Configuration.Json
Nancy

然后豹悬,在項目中創(chuàng)建一個名為 Startup 的類,Startup 是一個每個 Owin 程序都會有的一個類液荸,Owin 是一組應用服務器承載規(guī)范瞻佛,理論上 Startup 需要實現(xiàn)接口 IStartup,不過在 .NET Core 中娇钱,都沒有明確表示必須使用接口實現(xiàn)伤柄,而是被反射調用。

 public interface IStartup
 {
     IServiceProvider ConfigureServices(IServiceCollection services);
     void Configure(IApplicationBuilder app);
 }

所以我們創(chuàng)建一個 Startup 類忍弛,指定應用程序管道模型將會由 Nancy 進行處理。

namespace StudentManagementSystem
{
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Nancy.Owin;

    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseOwin(x => x.UseNancy());
        }
    }
}

接下來創(chuàng)建一個 Nancy 處理模塊考抄,名為 HomeModule细疚,如果對 ASP.NET MVC 或者 Java Servlet 有所了解的朋友應該了解這么個意思,它用來處理對應的 URL 的 HTTP 請求川梅,可以根據(jù)不同的 HTTP 謂詞返回不同的結果疯兼。

所有的 Module 必須繼承于它的父類 NancyModule,并在默認構造函數(shù)里處理請求贫途,這用起來雖然有點怪吧彪,不過沒關系,用習慣了就會一發(fā)不可收拾丢早。

所有的謂詞都是可以通過 NancyModule 中提供的虛方法自行實現(xiàn)姨裸,例如 GET 請求,其源代碼如下:

 /// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get(string path, Func<dynamic, object> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.Get<object>(path, action, condition, name);
}

/// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <typeparam name="T">The return type of the <paramref name="action"/></typeparam>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get<T>(string path, Func<dynamic, T> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.Get(path, args => Task.FromResult(action((DynamicDictionary)args)), condition, name);
}

/// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get(string path, Func<dynamic, Task<object>> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.Get<object>(path, action, condition, name);
}

/// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <typeparam name="T">The return type of the <paramref name="action"/></typeparam>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get<T>(string path, Func<dynamic, Task<T>> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.Get(path, (args, ct) => action((DynamicDictionary)args), condition, name);
}

/// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get(string path, Func<dynamic, CancellationToken, Task<object>> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.Get<object>(path, action, condition, name);
}

/// <summary>
/// Declares a route for GET requests.
/// </summary>
/// <typeparam name="T">The return type of the <paramref name="action"/></typeparam>
/// <param name="path">The path that the route will respond to</param>
/// <param name="action">Action that will be invoked when the route it hit</param>
/// <param name="name">Name of the route</param>
/// <param name="condition">A condition to determine if the route can be hit</param>
public virtual void Get<T>(string path, Func<dynamic, CancellationToken, Task<T>> action, Func<NancyContext, bool> condition = null, string name = null)
{
    this.AddRoute("GET", path, action, condition, name);
}

我們可以實現(xiàn)一個處理 GET 路由請求 /api/hello 的處理方法怨酝,如下:

public class HomeModule:NancyModule
{
    public HomeModule()
    {
        Get("/api/hello", _ => { return "hello nancy!"; });
    }
}

現(xiàn)在是時候檢驗一下我們的這個路由是否生效傀缩,并且是否能按照我們預期處理這個 GET 請求,還需要做一件事农猬,就是在 Main 方法里啟動 Kestrel赡艰,并制定啟動管道配置和處理類為 Startup。

var host = new WebHostBuilder()
          .UseContentRoot(Directory.GetCurrentDirectory())
          .UseKestrel()
          .UseStartup<Startup>()
          .Build();
host.Run();

添加完這部分代碼之后斤葱,編譯執(zhí)行慷垮,看看 Run 窗口有沒有下面的輸出:

如果由揖闸,恭喜你你的第一個 .NET Core 接口服務已經成功 Run 起來了,此時可以點擊這個超鏈接 http://localhost:5000 看看瀏覽器有什么料身,不出意外汤纸,會出現(xiàn)一個 404 頁面,這是因為我們沒有為根請求進行任何處理惯驼,而此時只要輸入我們的第一個 GET 請求的 URL http://localhost:5000/api/hello 的時候蹲嚣,就會出現(xiàn)下面的頁面,赫然已經看到了我們的代碼已經生效祟牲,這個 GET 請求已經被成功處理了隙畜。

或者,我們嚴謹一定啊说贝,讓這個接口返回 JSON 數(shù)據(jù)议惰,畢竟 APP 請求接口,還是 JSON 處理的比較方便乡恕。

public HomeModule()
{
    Get("/api/hello", _ => 
    { 
        return this.Response.AsJson(new
        {
            result = 0, 
            message = "ok"
        }); 
    });
}

再次執(zhí)行查看輸出言询,即可看到我們已經成功輸出了 JSON 類型的數(shù)據(jù)了。

OK傲宜,從零開始就到這里了运杭,感謝各位看官!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末函卒,一起剝皮案震驚了整個濱河市辆憔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌报嵌,老刑警劉巖虱咧,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锚国,居然都是意外死亡腕巡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進店門血筑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绘沉,“玉大人,你說我怎么就攤上這事豺总“鹪遥” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵园欣,是天一觀的道長帖世。 經常有香客問我,道長,這世上最難降的妖魔是什么日矫? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任赂弓,我火速辦了婚禮,結果婚禮上哪轿,老公的妹妹穿的比我還像新娘盈魁。我一直安慰自己,他們只是感情好窃诉,可當我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布杨耙。 她就那樣靜靜地躺著,像睡著了一般飘痛。 火紅的嫁衣襯著肌膚如雪珊膜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天宣脉,我揣著相機與錄音车柠,去河邊找鬼。 笑死塑猖,一個胖子當著我的面吹牛竹祷,可吹牛的內容都是我干的。 我是一名探鬼主播羊苟,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼塑陵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜡励?” 一聲冷哼從身側響起令花,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巍虫,沒想到半個月后彭则,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳍刷,經...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡占遥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了输瓜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓦胎。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尤揣,靈堂內的尸體忽然破棺而出搔啊,到底是詐尸還是另有隱情,我是刑警寧澤北戏,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布负芋,位于F島的核電站,受9級特大地震影響嗜愈,放射性物質發(fā)生泄漏旧蛾。R本人自食惡果不足惜莽龟,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锨天。 院中可真熱鬧毯盈,春花似錦、人聲如沸病袄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽益缠。三九已至脑奠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間左刽,已是汗流浹背捺信。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工帽驯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厢塘,地道東北人。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓卓缰,卻偏偏與公主長得像喇辽,于是被迫代替她去往敵國和親掌挚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內容