亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

自我總結:對博客園的服務接口進行封裝

2019-11-14 16:17:53
字體:
來源:轉載
供稿:網友

之前在開發博客園新聞客戶端的時候,需要獲取博客園的新聞數據,最早開發出來的版本使用的是手機版的 html 解釋的方式。效果算是做出來了,但是感覺獲取到的數據太冗余,于是便查了一下有沒有相應的接口。皇天不負有心人,博客園果然開放了些接口供我們使用。

博客服務接口:http://wcf.open.VEVb.com/blog/help

新聞服務接口:http://wcf.open.VEVb.com/news/help

博客服務:

UriMethodDescription
48HoursTopViewPosts/{itemCount}GET48小時閱讀排行
bloggers/recommend/{pageIndex}/{pageSize}GET分頁獲取推薦博客列表
bloggers/recommend/countGET獲取推薦博客總數
bloggers/searchGET根據作者名搜索博主
post/{postId}/comments/{pageIndex}/{pageSize}GET獲取文章評論
post/body/{postId}GET獲取文章內容
sitehome/paged/{pageIndex}/{pageSize}GET分頁獲取首頁文章列表
sitehome/recent/{itemcount}GET獲取首頁文章列表
TenDaysTopDiggPosts/{itemCount}GET10天內推薦排行
u/{blogapp}/posts/{pageIndex}/{pageSize}GET分頁獲取個人博客文章列表

新聞服務:

UriMethodDescription
GetDataGET獲取新聞列表
hot/{itemcount}GET獲取熱門新聞列表
item/{contentId}GET獲取新聞內容
item/{contentId}/comments/{pageIndex}/{pageSize}GET獲取新聞評論
recent/{itemcount}GET獲取最新新聞列表
recent/paged/{pageIndex}/{pageSize}GET分頁獲取最新新聞列表
recommend/paged/{pageIndex}/{pageSize}GET分頁獲取推薦新聞列表

可以看見,博客園官方團隊還算是挺厚道的,基本的接口都開放出來了。(除了博客文章按分類獲取-_-|||博主我的碎碎念)

 

由于需要盡可能使我們封裝好的類庫盡可能在多個平臺使用,于是乎就想到了使用可移植類庫(PCL)來開發。

建起項目

當然是通通選上,哪知道以后哪天會不會心血來潮再搞個什么平臺的客戶端。

 

因為就分兩大類,于是果斷碼上 BlogService 和 NewsService 兩個靜態類。

作為相應服務的入口。

 

接下來,看見新聞的接口比較少,先寫這部分。

測試 GetData 接口。

啥玩意?!2012年的數據!那這個就不理他了。。。

 

接下來就是 hot(獲取熱門新聞列表)這個接口。

測試下:http://wcf.open.VEVb.com/news/hot/10

工作良好,于是開始寫這個接口的封裝。

在 NewsService 中寫上

public static async Task<IEnumerable<News>> HotAsync(int itemCount){    // TODO}

會發覺編譯不通過(廢話)。

于是新建一個News類先。修改方法。

編譯!

不通過?。?!

看錯誤列表:

不是4.5了么?怎么不能用 async?

解決方法:http://www.49028c.com/h82258652/p/4119118.html(注:本文為總結性文章,所以時間線的跳躍你們要跟上)

 

裝好巨硬給我們的異步補丁包后就可以編譯通過了。

 

接下來觀察接口返回的xml文檔,可以發現每一個entry節點就相當于一條新聞。

根據entry分析,完善News類:

  1 using System;  2   3 namespace SoftwareKobo.CnblogsAPI.Model  4 {  5     /// <summary>  6     /// 新聞。  7     /// </summary>  8     public class News  9     { 10         /// <summary> 11         /// Id。 12         /// </summary> 13         public int Id 14         { 15             get; 16             internal set; 17         } 18  19         /// <summary> 20         /// 標題。 21         /// </summary> 22         public string Title 23         { 24             get; 25             internal set; 26         } 27  28         /// <summary> 29         /// 摘要。 30         /// </summary> 31         public string Summary 32         { 33             get; 34             internal set; 35         } 36  37         /// <summary> 38         /// 發表時間。 39         /// </summary> 40         public DateTime Published 41         { 42             get; 43             internal set; 44         } 45  46         /// <summary> 47         /// 更新時間。 48         /// </summary> 49         public DateTime Updated 50         { 51             get; 52             internal set; 53         } 54  55         /// <summary> 56         /// 新聞鏈接。 57         /// </summary> 58         public Uri Link 59         { 60             get; 61             internal set; 62         } 63  64         /// <summary> 65         /// 推薦數。 66         /// </summary> 67         public int Diggs 68         { 69             get; 70             internal set; 71         } 72  73         /// <summary> 74         /// 查看數。 75         /// </summary> 76         public int Views 77         { 78             get; 79             internal set; 80         } 81  82         /// <summary> 83         /// 評論數。 84         /// </summary> 85         public int Comments 86         { 87             get; 88             internal set; 89         } 90  91         /// <summary> 92         /// 主題。 93         /// </summary> 94         public string Topic 95         { 96             get; 97             internal set; 98         } 99 100         /// <summary>101         /// 主題圖標。102         /// </summary>103         public Uri TopicIcon104         {105             get;106             internal set;107         }108 109         /// <summary>110         /// 轉載自。111         /// </summary>112         public string SourceName113         {114             get;115             internal set;116         }117     }118 }
View Code

PS:Q:為什么set方法都寫為internal?A:為什么外部要修改?Q:好吧,你贏了。

接下來就開始寫我們的 HotAsync 方法了。

HotAsync 方法有一個參數——itemCount,那么當然要進行驗證。(不發送這些無謂的請求一方面可以不讓用戶等待、一方面減輕博客園的壓力)

if (itemCount < 1){    throw new ArgumentOutOfRangeException(nameof(itemCount));}

nameof,還沒跟上時代節奏的小伙伴就趕緊跟上了,這里不解釋。

 

接下來當然是拼接 url。

var url = string.Format(CultureInfo.InvariantCulture, HotUrlTemplate, itemCount);var uri = new Uri(url, UriKind.Absolute);

HotUrlTemplate 的定義:

PRivate const string HotUrlTemplate = "http://wcf.open.VEVb.com/news/hot/{0}";

常量最好不要出現在方法中這是好習慣哦。

 

準備WebRequest,并且調用GetResponse。

var request = WebRequest.Create(uri);using (var response = await request.GetResponseAsync()){    // TODO}

由于返回的是一個xml,所以直接使用 XDocument 加載(PS:我特討厭XmlDocument那套API)

var document = XDocument.Load(response.GetResponseStream());

接下來就是將XDocument轉換為News實體類的列表,這里我們寫到別的方法去,因為下面幾個服務接口可能也會用到。

新建NewsHelper類。

根據entry節點的結果,寫出以下代碼:

 1     internal static class NewsHelper 2     { 3         internal static IEnumerable<News> Deserialize(XDocument document) 4         { 5             var root = document?.Root; 6             if (root == null) 7             { 8                 return null; 9             }10 11             var ns = root.GetDefaultNamespace();12             var news = from entry in root.Elements(ns + "entry")13                        where entry.HasElements14                        let temp = Deserialize(entry)15                        where temp != null16                        select temp;17             return news;18         }19 20         internal static News Deserialize(XElement element)21         {22             if (element == null)23             {24                 return null;25             }26 27             var ns = element.GetDefaultNamespace();28             var id = element.Element(ns + "id");29             var title = element.Element(ns + "title");30             var summary = element.Element(ns + "summary");31             var published = element.Element(ns + "published");32             var updated = element.Element(ns + "updated");33             var href = element.Element(ns + "link")?.Attribute("href");34             var diggs = element.Element(ns + "diggs");35             var views = element.Element(ns + "views");36             var comments = element.Element(ns + "comments");37             var topic = element.Element(ns + "topic");38             var topicIcon = element.Element(ns + "topicIcon");39             var sourceName = element.Element(ns + "sourceName");40 41             if (id == null42                 || title == null43                 || summary == null44                 || published == null45                 || updated == null46                 || href == null47                 || diggs == null48                 || views == null49                 || comments == null50                 || topic == null51                 || topicIcon == null52                 || sourceName == null)53             {54                 return null;55             }56 57             return new News58             {59                 Id = int.Parse(id.Value, CultureInfo.InvariantCulture),60                 Title = WebUtility.HtmlDecode(title.Value),61                 Summary = WebUtility.HtmlDecode(summary.Value),62                 Published = DateTime.Parse(published.Value, CultureInfo.InvariantCulture),63                 Updated = DateTime.Parse(updated.Value, CultureInfo.InvariantCulture),64                 Link = new Uri(href.Value, UriKind.Absolute),65                 Diggs = int.Parse(diggs.Value, CultureInfo.InvariantCulture),66                 Views = int.Parse(views.Value, CultureInfo.InvariantCulture),67                 Comments = int.Parse(comments.Value, CultureInfo.InvariantCulture),68                 Topic = topic.Value,69                 TopicIcon = topicIcon.IsEmpty ? null : new Uri(topicIcon.Value, UriKind.Absolute),70                 SourceName = sourceName.Value71             };72         }73     }
View Code

由于我們需要的是IEnumerable<News>,所以直接返回Linq的結果就行了,不用ToList或者啥的。

 

注意PCL中是沒有HtmlDecode、HtmlEncode的,nuget上有一個PCL用的,可惜人家作者沒更新了,版本過舊,引用不了,沒辦法,自己動手豐衣足食。

項目地址:https://github.com/h82258652/SoftwareKobo.Net.WebUtility

Nuget地址:https://www.nuget.org/packages/SoftwareKobo.Net.WebUtility/

也是自己隨便寫的,反正能處理一下常見的字符就算了。(=_=)(巨硬的源碼我實在是看不懂。。還打算照抄的……)

 

接下來回到 HotAsync 補充最后一句:

return NewsHelper.Deserialize(document);

完事。

其他什么 Recent(最新的)、Recommend(推薦)如法炮制。(Recent有兩個接口,選擇分頁那個好了,反正感覺博客園內部實現也是重載)

 

接下來看新聞內容這個接口:

寫上 DetailAsync 方法:

public static async Task<NewsDetail> DetailAsync(int newsId)

當然也有建上NewsDetail類。

 1     /// <summary> 2     /// 新聞內容。 3     /// </summary> 4     public class NewsDetail 5     { 6         /// <summary> 7         /// Id。 8         /// </summary> 9         public int Id10         {11             get;12             internal set;13         }14 15         /// <summary>16         /// 標題。17         /// </summary>18         public string Title19         {20             get;21             internal set;22         }23 24         /// <summary>25         /// 轉載自。26         /// </summary>27         public string SourceName28         {29             get;30             internal set;31         }32 33         /// <summary>34         /// 發表時間。35         /// </summary>36         public DateTime SubmitDate37         {38             get;39             internal set;40         }41 42         /// <summary>43         /// 內容。44         /// </summary>45         public string Content46         {47             get;48             internal set;49         }50 51         /// <summary>52         /// 新聞中用到的圖片的路徑。53         /// </summary>54         public ReadOnlyCollection<Uri> ImageUrl55         {56             get;57             internal set;58         }59 60         /// <summary>61         /// 上一條新聞的 Id。62         /// </summary>63         public int? PrevNews64         {65             get;66             internal set;67         }68 69         /// <summary>70         /// 下一條新聞的 Id。71         /// </summary>72         public int? NextNews73         {74             get;75             internal set;76         }77 78         /// <summary>79         /// 評論數。80         /// </summary>81         public int CommentCount82         {83             get;84             internal set;85         }86     }
View Code

注意:

1、ImageUrl 用了 ReadOnlyCollection,原因同上,外部沒必要修改。

2、PreNews 和 NextNews 使用可空類型,因為不一定有上一條或下一條。(都最新了,還能有下一條么)

 

接下來也是寫個Helper,將Xml的內容轉換為對象列表。完事。

剩下來獲取評論也是差不多。

博客方面的接口封裝基本上也是這么搞,注意的是新聞的評論和博客文章的評論可以用同一個模型來表達。

 

都寫完后,感覺獲取新聞獲取評論不方便啊,得先訪問Id,再調NewsService。天生懶,沒辦法,寫個擴展方法。

 1     /// <summary> 2     /// 新聞擴展。 3     /// </summary> 4     public static class NewsExtension 5     { 6         /// <summary> 7         /// 獲取新聞評論。 8         /// </summary> 9         /// <param name="news">新聞。</param>10         /// <param name="pageIndex">第幾頁,從 1 開始。</param>11         /// <param name="pageSize">每頁條數。</param>12         /// <returns>新聞評論。</returns>13         /// <exception cref="ArgumentNullException">新聞為 null。</exception>14         public static async Task<IEnumerable<Comment>> CommentAsync(this News news, int pageIndex, int pageSize)15         {16             if (news == null)17             {18                 throw new ArgumentNullException(nameof(news));19             }20             return await NewsService.CommentAsync(news.Id, pageIndex, pageSize);21         }22 23         /// <summary>24         /// 獲取新聞內容。25         /// </summary>26         /// <param name="news">新聞。</param>27         /// <returns>新聞內容。</returns>28         /// <exception cref="ArgumentNullException">新聞為 null。</exception>29         public static async Task<NewsDetail> DetailAsync(this News news)30         {31             if (news == null)32             {33                 throw new ArgumentNullException(nameof(news));34             }35             return await NewsService.DetailAsync(news.Id);36         }37     }
View Code

Q:為什么不在News類里寫?A:沒什么,保持模型純正而已。-_-|||也好管理。

 

完事了,Release編譯,弄到nuget包里,發布。測試添加引用,沒注釋!?。?/p>

回到項目,修改項目屬性,生成XML,勾上!!

把XML一同弄到nuget包里,再發布,測試,好了。

 

At The End:

項目地址:https://github.com/h82258652/SoftwareKobo.CnblogsAPI

 

Nuget地址:https://www.nuget.org/packages/SoftwareKobo.CnblogsAPI/

博主我(h82258652)的話:有什么建議歡迎在下面評論提,畢竟博主我也是菜鳥。

↑重點當然要大只字!


上一篇:Nlog

下一篇:[C#]RandomHelper

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一视频网站| 亚洲国产高潮在线观看| 国产午夜精品全部视频播放| 日韩精品中文字幕有码专区| www.午夜精品| 精品日本美女福利在线观看| 亚洲奶大毛多的老太婆| 91精品免费看| 亚洲人成免费电影| 欧美国产日本高清在线| 国产精品久久久久久久av电影| 美女扒开尿口让男人操亚洲视频网站| 成人av在线天堂| 亚洲第一网站男人都懂| 欧美成人在线影院| 国产亚洲精品日韩| 91久久精品国产91久久性色| 久久99久久99精品中文字幕| 国产精品18久久久久久麻辣| 日韩欧亚中文在线| 欧美日韩国产限制| 日韩在线不卡视频| 亚洲国产欧美一区二区三区久久| 亚洲精品国产拍免费91在线| 青青草原成人在线视频| 日韩av电影在线播放| 国产噜噜噜噜噜久久久久久久久| 国产精品老女人精品视频| 日本久久久久久久久久久| 一区二区欧美亚洲| 国产精品久久久久久亚洲影视| 91久久精品国产91性色| 国产一区二区日韩精品欧美精品| 欧美日韩国产中文字幕| 日韩欧美在线视频日韩欧美在线视频| 亚洲视频免费一区| 亚洲国产成人91精品| 欧美性猛交xxxx富婆| 疯狂做受xxxx欧美肥白少妇| 伊人av综合网| 久久亚洲精品成人| 亚洲成人精品视频在线观看| 久久综合久久八八| 日韩在线视频免费观看| 91久久精品国产| 国产精品电影久久久久电影网| 亚洲性生活视频在线观看| 色哟哟亚洲精品一区二区| 久久久精品国产网站| 国模精品视频一区二区三区| 欧美中文字幕在线视频| 国产欧美一区二区三区在线看| 日韩中文娱乐网| 日韩一区二区福利| 久久久久久久亚洲精品| 日韩精品免费视频| 欧美国产在线视频| 7777kkkk成人观看| 久久亚洲国产精品| 久久99久久99精品中文字幕| 成人网在线免费看| 欧美中文字幕在线视频| 亚洲第一区第一页| 亚州欧美日韩中文视频| 国产精品v片在线观看不卡| 国产成人精品免高潮费视频| 色综合天天狠天天透天天伊人| 欧美成人精品在线视频| 在线成人中文字幕| 91沈先生作品| 亚洲欧美日韩视频一区| 欧美性开放视频| 成人免费视频在线观看超级碰| 亚洲国产美女精品久久久久∴| 欧美日韩美女在线观看| 欧美日韩亚洲91| 亚洲成人黄色在线观看| 欧美日韩美女在线| 91亚洲午夜在线| 亚洲人成网站777色婷婷| 97精品视频在线播放| 色诱女教师一区二区三区| 成人国产精品久久久久久亚洲| 国产精品看片资源| 久久天天躁狠狠躁夜夜躁2014| 久久精品91久久香蕉加勒比| 欧美最猛性xxxxx亚洲精品| 69久久夜色精品国产69乱青草| 国产成人高潮免费观看精品| 中文字幕日韩免费视频| 黑人巨大精品欧美一区二区三区| 欧美激情精品久久久久久大尺度| 欧美性猛交xxx| 2020久久国产精品| 色噜噜久久综合伊人一本| 日韩免费电影在线观看| 日韩高清免费在线| 午夜精品理论片| 亚洲视频在线观看网站| 国产精品国产自产拍高清av水多| 国产福利成人在线| 亚洲天堂影视av| 欧美激情aaaa| 亚洲欧洲免费视频| 久久久999成人| 亚洲男人的天堂在线播放| 欧美交受高潮1| 久久6精品影院| 青青草成人在线| 一区二区三区视频免费| 26uuu日韩精品一区二区| 成人午夜在线观看| 亚洲人免费视频| 2019最新中文字幕| 欧美中在线观看| 国产手机视频精品| 不用播放器成人网| 欧美在线一级视频| 欧美日韩国产在线| 性欧美亚洲xxxx乳在线观看| 欧美多人乱p欧美4p久久| 日韩一区二区在线视频| 国产精品免费视频久久久| 国产精品678| 91av视频在线免费观看| 一级做a爰片久久毛片美女图片| 欧美亚洲午夜视频在线观看| 美女性感视频久久久| 亚洲国产另类久久精品| www.日韩欧美| 国产精品嫩草影院一区二区| 在线播放日韩av| 在线观看亚洲区| 国产精品九九久久久久久久| 亚洲欧美日韩中文在线制服| 97视频在线看| 国产精品视频大全| 欧美风情在线观看| 欧美在线观看视频| 国产精品高潮呻吟视频| 亚洲欧美日韩国产中文专区| 国产成人精品午夜| 亚洲美女中文字幕| 国产美女久久久| 久久99热这里只有精品国产| 久久天堂电影网| 久久九九亚洲综合| 性欧美xxxx视频在线观看| 91精品一区二区| 国产综合久久久久| 欧美一级片免费在线| 欧美多人乱p欧美4p久久| 78m国产成人精品视频| 最新91在线视频| 成人午夜在线视频一区| 国产精品av在线| 日韩高清av一区二区三区| 日韩精品视频免费专区在线播放| 亚洲精品国产精品国自产在线| 日韩激情在线视频| 亚洲欧美综合图区| 欧美日韩在线另类| 欧美最顶级的aⅴ艳星| 日韩欧美a级成人黄色|