ASP.NET Core 6框架揭秘實例演示[30]:利用路由開發REST API

借助路由系統提供的請求URL模式與對應終結點之間的映射關系,我們可以將具有相同URL模式的請求分發給與之匹配的終結點進行處理。ASP.NET的路由是通過EndpointRoutingMiddleware和EndpointMiddleware這兩個中間件協作完成的,它們在ASP.NET平臺上具有舉足輕重的地位,MVC和gRPC框架,Dapr的Actor和發布訂閱編程模式都建立在路由系統之上。Minimal API更是將提升到了前所未有的高度,是我們直接在路由系統基礎上定義REST API。[本文節選《ASP.NET Core 6框架揭秘》第20章]

[S2001]注冊路由終結點 (源代碼)
[S2002]以內聯方式設置路由參數的約束(源代碼)
[S2003]定義可缺省的路由參數(源代碼)
[S2004]為路由參數指定默認值(源代碼)
[S2005]一個路徑分段定義多個路由參數(源代碼)
[S2006]一個路由參數跨越多個路徑分段(源代碼)
[S2007]主機名綁定(源代碼)
[S2008]將終結點處理定義為任意類型的委托(源代碼)
[S2009]IResult 的應用(源代碼)

[S2001]注冊路由終結點

我們演示的這個ASP.NET應用是一個簡易版的天氣預報站點。服務端利用注冊的一個終結點來提供某個城市在未來N天之內的天氣信息,對應城市(采用電話區號表示)和天數直接至于請求URL的路徑中。如圖1所示,為了得到成都未來兩天的天氣信息,我們將發送請求的路徑設置為“weather/028/2”。路徑為“weather/0512/4”的請求返回就是蘇州未來4天的天氣信息。

455bf8579efd669317c00f4f6d57f47f.png

圖1 獲取天氣預報信息

演示程序定義了如下這個WeatherReport記錄類型來表示某個城市在某段時間范圍內的天氣報告。如代碼片段所示,某一天的天氣體現為一個WeatherInfo記錄。簡單起見,我們讓WeatherInfo記錄只攜帶基本天氣狀況和氣溫區間的信息。

public?readonly?record?struct?WeatherInfo(string?Condition,?double?HighTemperature,?double?LowTemperature);
public?readonly?record?struct?WeatherReport(string?CityCode,?string?CityName,IDictionary<DateTime,?WeatherInfo>?WeatherInfos);

我們定義了如下這個工具類型WeatherReportUtility,兩個Generate方法會根據指定的城市代碼和天數/日期生成一份由WeatherReport對象表示的天氣報告。為了將這份報告呈現在網頁上,我們定義了另一個RenderAsync方法將指定的WeatherReport轉換成HTML,并利用指定的HttpContext上下文將它作為響應內容,具體的HTML內容由AsHtml方法生成。

public?static?class?WeatherReportUtility
{private?static?readonly?Random?_random?=?new();private?static?readonly?Dictionary<string,?string>?_cities?=?new(){["010"]?=?"北京",["028"]?=?"成都",["0512"]?=?"蘇州"};private?static?readonly?string[]?_conditions?=?new?string[]?{?"晴",?"多云",?"小雨"?};public?static?WeatherReport?Generate(string?city,?int?days){var?report?=?new?WeatherReport(city,?_cities[city],??new?Dictionary<DateTime,?WeatherInfo>());for?(int?i?=?0;?i?<?days;?i++){report.WeatherInfos[DateTime.Today.AddDays(i?+?1)]?=?new?WeatherInfo(_conditions[_random.Next(0,?2)],?_random.Next(20,?30),?_random.Next(10,?20));}return?report;}public?static?WeatherReport?Generate(string?city,?DateTime?date){var?report?=?new?WeatherReport(city,?_cities[city],??new?Dictionary<DateTime,?WeatherInfo>());report.WeatherInfos[date]?=?new?WeatherInfo(_conditions[_random.Next(0,?2)],?_random.Next(20,?30),?_random.Next(10,?20));return?report;}public?static?Task?RenderAsync(HttpContext?context,?WeatherReport?report){context.Response.ContentType?=?"text/html;charset=utf-8";return?context.Response.WriteAsync(AsHtml(report));}public?static?string?AsHtml(WeatherReport?report){return?@$"
<html>
<head><title>Weather</title></head>
<body>
<h3>{report.CityName}</h3>
{AsHtml(report.WeatherInfos)}
</body>
</html>
";static?string?AsHtml(IDictionary<DateTime,?WeatherInfo>?dictionary){var?builder?=?new?StringBuilder();foreach?(var?kv?in?dictionary){var?date?=?kv.Key.ToString("yyyy-MM-dd");var?tempFrom?=?$"{kv.Value.LowTemperature}℃?";var?tempTo?=?$"{kv.Value.HighTemperature}℃?";builder.Append(?$"{date}:?{kv.Value.Condition}?({tempFrom}~{tempTo})<br/></br>");}return?builder.ToString();}}
}

Minimal API會默認添加針對路由的服務注冊,完成路由的兩個中間件(RoutingMiddleware和EndpointRoutingMiddleware)也會在自動注冊到創建的WebApplication對象上。WebApplication類型同時實現了IEndpointRouteBuilder接口,我們只需要利用它注冊相應的終結點就可以了。如下的演示程序調用了WebApplication對象的MapGet方法注冊了一個僅針對GET請求的終結點,終結點采用的路徑模板為“weather/{city}/{days}”,攜帶的兩個路由參數({city}和{days})分別代表目標城市代碼(區號)和天數。

using?App;
var?app?=?WebApplication.Create();
app.MapGet("weather/{city}/{days}",?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context)
{var?routeValues?=?context.GetRouteData().Values;var?city?=?routeValues["city"]!.ToString();var?days?=?int.Parse(routeValues["days"]!.ToString()!);var?report?=?WeatherReportUtility.Generate(city!,?days);return?WeatherReportUtility.RenderAsync(context,?report);
}

注冊中間件采用的處理器是一個RequestDelegate委托,我們將它指向ForecastAsync方法。該方法調用HttpContext上下文的GetRouteData方法得到承載“路由數據”的RouteData對象,后者的Values屬性返回路由參數字典。我們從中提取出代表城市代碼和天數的路由參數,并創建出對應的天氣報告,最后將其轉換成HTML作為響應內容。

[S2002]以內聯方式設置路由參數的約束

上面的演示實例注冊的路由模板中定義了兩個參數({city}和{days}),分別表示獲取天氣預報的目標城市對應的區號和天數。區號應該具有一定的格式(以零開始的3~4位數字),而天數除了必須是一個整數,還應該具有一定的范圍。由于沒有對這兩個路由參數坐任何約束,所以請求URL攜帶的任何字符都是有效的。ForecastAsync方法也并沒有對提取的路由參數做任何驗證,所以在執行過程中面對不合法的輸入會直接拋出異常。

為了確保路由參數值的有效性,在進行中間件注冊時可以采用內聯(Inline)的方式直接將相應的約束規則定義在路由模板中。ASP.NET為常用的驗證規則定義了相應的約束表達式,我們可以根據需要為某個路由參數指定一個或者多個約束表達式。如下面的代碼片段所示,我們為路由參數“{city}”指定了一個基于“區號”的正則表達式(“:regex(^0[1-9]{{2,3}}$)”)。另一個路由參數{days}則應用了兩個約束,一個是針對數據類型的約束(“:int”),另一個是針對區間的約束(“:range(1,4)”)。

using?App;
var?template?=?@"weather/{city:regex(^0\d{{2,3}}$)}/{days:int:range(1,4)}";
var?app?=?WebApplication.Create();
app.MapGet(template,?ForecastAsync);
app.Run();

如果在注冊路由時應用了約束,那么RoutingMiddleware中間件在進行路由解析時除了要求請求路徑必須與路由模板具有相同的模式,還要求攜帶的數據滿足對應路由參數的約束條件。如果不能同時滿足這兩個條件,RoutingMiddleware中間件將無法選擇一個終結點來處理當前請求。對于我們演示的這個實例來說,如果提供的是一個不合法的區號(1014)和預報天數(5),那么客戶端都將得到圖2所示的狀態碼為“404 Not Found”的響應。

020d9452e4dceb8560faa1b1475bfa59.png

圖2 不滿足路由約束而返回的“404 Not Found”響應

[S2003]定義可缺省的路由參數

路由模板(如“weather/{city}/{days}”)可以包含靜態的字符(如“weather”),也可以包含動態的參數(如{city}和{days}),我們將后者稱為路由參數。并非每個路由參數都必須有請求URL對應的部分來指定,如果賦予路由參數一個默認值,那么它在請求URL中就是可以缺省的。對上面演示的實例來說,我們可以采用如下方式在路由參數名后面添加一個問號(“?”)將原本必需的路由參數變成可以缺省的默認參數的。可以缺省的路由參數與在方法中定義可缺省的(Optional)params參數一樣,只能出現在路由模板尾部。

using?App;var?template?=?"weather/{city?}/{days?}";
var?app?=?WebApplication.Create();
app.MapGet(template,?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context)
{var?routeValues?=?context.GetRouteData().Values;var?city?=?routeValues.TryGetValue("city",?out?var?v1)???v1!.ToString()?:?"010";var?days?=?routeValues.TryGetValue("days",?out?var?v2)???v1!.ToString()?:?"4";var?report?=?WeatherReportUtility.Generate(city!,?int.Parse(days!));return?WeatherReportUtility.RenderAsync(context,?report);
}

既然路由變量占據的部分路徑是可以缺省的,那么即使請求的URL不具有對應的值(如“weather”和“weather/010”),它與路由規則也是匹配的,但此時在路由參數字典中是找不到它們的。此時我們不得不對處理請求的ForecastAsync方法進行相應的改動。針對上述改動,如果希望獲取北京未來4天的天氣狀況,我們可以采用圖3所示的三種URL(“weather”、“weather/010”和“weather/010/4”),這三個請求的URL本質上是完全等效的。

b772b03f9469c87cfd89e50843c36477.png

圖3 不同URL針對默認路由參數的等效性

[S2004]為路由參數指定默認值

實際上可缺省路由參數默認值的設置還有一種更簡單的方式,那就是按照如下所示的方式直接將默認值定義在路由模板中。這樣針對ForecastAsync方法的改動就完全沒有必要。

using?App;var?template?=?@"weather/{city=010}/{days=4}";
var?app?=?WebApplication.Create();
app.MapGet(template,?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context)
{var?routeValues?=?context.GetRouteData().Values;var?city?=?routeValues["city"]!.ToString();var?days?=?int.Parse(routeValues["days"]!.ToString()!);var?report?=?WeatherReportUtility.Generate(city!,?days);return?WeatherReportUtility.RenderAsync(context,?report);
}

[S2005]一個路徑分段定義多個路由參數

一個URL可以通過分隔符“/”劃分為多個路徑分段(Segment),路由參數一般來說會占據某個獨立的分段(如“weather/{city}/{days}”)。但也有例外情況,我們既可以在一個單獨的路徑分段中定義多個路由參數,也可以讓一個路由參數跨越多個連續的路徑分段。以我們的演示程序為例,我們需要設計一種路徑模式來獲取某個城市某一天的天氣信息,如使用“/weather/010/2019.11.11”這樣URL獲取北京在2019年11月11日的天氣,對應模板為“/weather/{city}/{year}.{month}.{day}”。

using?App;var?template?=?"weather/{city}/{year}.{month}.{day}";
var?app?=?WebApplication.Create();
app.MapGet(template,?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context)
{var?routeValues?=?context.GetRouteData().Values;var?city?=?routeValues["city"]!.ToString();var?year?=?int.Parse(routeValues["year"]!.ToString()!);var?month?=?int.Parse(routeValues["month"]!.ToString()!);var?day?=?int.Parse(routeValues["day"]!.ToString()!);var?report?=?WeatherReportUtility.Generate(city!,?new?DateTime(year,month,day));return?WeatherReportUtility.RenderAsync(context,?report);
}

對于修改后的程序,如果采用“/weather/{city}/{yyyy}.{mm}.{dd}”這樣的URL,我們就可以獲取某個城市指定日期的天氣。如圖4所示,我們采用請求路徑“/weather/010/2019.11.11”可以獲取北京在2019年11月11日的天氣。

d5c0816c5e39c04f057add3b1587a79d.png

圖4 一個路徑分段定義多個路由參數

[S2006]一個路由參數跨越多個路徑分段

上面設計的路由模板采用“.”作為日期分隔符,如果采用“/”作為日期分隔符(如2019/11/11),這個路由默認應該如何定義呢?由于“/”同時也是路徑分隔符,就意味著同一個路由參數跨越了多個路徑分段,這種情況只能采用“通配符”的形式才能達成我們的目標。通配符路由參數采用{*variable}或者{**variable}的形式,星號(*)表示路徑“余下的部分”,所以這樣的路由參數也只能出現在模板的尾端。演示程序的路由模板可以定義成“/weather/{city}/{*date}”。

using?App;
using?System.Globalization;var?template?=?"weather/{city}/{*date}";
var?app?=?WebApplication.Create();
app.MapGet(template,?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context)
{var?routeValues?=?context.GetRouteData().Values;var?city?=?routeValues["city"]!.ToString();var?date?=?DateTime.ParseExact(routeValues["date"]?.ToString()!,"yyyy/MM/dd",CultureInfo.InvariantCulture);var?report?=?WeatherReportUtility.Generate(city!,?date);return?WeatherReportUtility.RenderAsync(context,?report);
}

我們可以對程序做如上修改來使用新的URL模板(“/weather/{city}/{*date}”)。為了得到北京在2019年11月11日的天氣,請求的URL可以替換成“/weather/010/2019/11/11”,返回的天氣信息如圖5所示。

b547f3872f28804b5230253e42113c75.png

圖5 一個路由參數跨越多個路徑分段

[S2007]主機名綁定

一般來說,在利用某路由終結點與待路由的請求進行匹配的時候只需要考慮請求地址的路徑部分,并忽略主機(Host)名稱和端口號,但是一定要加上針對主機名稱(含端口)的匹配策略也未嘗不可。在如下這個演示程序中,我們通過調用MapGet擴展方法為根路徑“/”添加了三個路由終結點,并調用該方法返回的IEndpointConventionBuilder對象的RequireHost擴展方法綁定了對應的主機名(“*.artech.com”、“www.foo.artech.com”和“www.foo.artech.com:9999”)。指定的第一個主機名包含一個前置通配符“*”,最后一個則指定了端口號。注冊的這三個終結點會直接將指定的主機名作為響應內容。

var?app?=?WebApplication.Create();
app.Urls.Add("http://0.0.0.0:6666");
app.Urls.Add("http://0.0.0.0:9999");
app.MapHost("*.artech.com").MapHost("www.foo.artech.com").MapHost("www.foo.artech.com:9999");
app.Run();internal?static?class?Extensions
{public?static?IEndpointRouteBuilder?MapHost(this?IEndpointRouteBuilder?endpoints,string?host){endpoints.MapGet("/",?context?=>?context.Response.WriteAsync(host)).RequireHost(host);return?endpoints;}
}

為了能夠在本機采用不同的域名對演示應用發起請求,我們通過修改Hosts文件的方式將本地地址(“127.0.0.1”)映射為多個不同的域名。我們以管理員(Administrator)身份打開文件Hosts “%windir%\System32\drivers\etc\hosts”,并以如下所示的方式添加了針對兩個域名的映射。

127.0.0.1?www.foo.artech.com
127.0.0.1?www.bar.artech.com

應用啟動之后,我們利用瀏覽器使用不同的域名和端口對其發起請求,并得到如圖6所示的輸出結果。輸出的內容不僅僅體現了終結點選擇過程中針對主機名的過濾,還體現了終結點選擇策略的一個重要的特性,那就是路由系統總是試圖選擇一個與當前請求匹配度最高的終結點,而不是選擇第一個匹配的終結點。

c041832c6e4b0efc28699af6a53f153a.png

圖6 主機名綁定

[S2008]將終結點處理定義為任意類型的委托

上面的例子都直接使用一個RequestDelegate委托作為終結點的處理器,實際上我們在注冊終結點時可以將處理器設置為任何類型的委托都可以。當路由請求分發給注冊的委托進行處理器時,會盡可能地從當前HttpContext上下文中提取相應的數據對委托的輸入參數進行綁定。對于委托的執行結果,路由系統也會按照預定義的規則“智能”地將它應用到針對請求的響應中。按照這個規則,我們演示程序中用來處理請求的ForecastAsync方法可以簡寫成如下形式。第一個參數會自動綁定為當前HttpContext上下文,后面的兩個參數則自動與同名的路由參數進行綁定。

using?App;var?app?=?WebApplication.Create();
app.MapGet("weather/{city}/{days}",?ForecastAsync);
app.Run();static?Task?ForecastAsync(HttpContext?context,?string?city,?int?days){var?report?=?WeatherReportUtility.Generate(city,days);return?WeatherReportUtility.RenderAsync(context,?report);
}

[S2009]IResult 的應用

不論終結點處理器的委托返回何種類型的對象,路由系統總能做出對應的處理。比如對于返回的字符串會直接作為響應的主體內容,并將Content-Type報頭設置為“text/plain”。如果希望對返回對象具有明確的控制,最好返回一個IResult對象(或者Task<IResult>和ValueTask<IResult>),IResult相當ASP.NET MVC中的IActionResult。我們演示程序中的ForecastAsync方法也可以改寫成如下這個返回類型為IResult的Forecast方法,該方法通過調用Results類型的靜態Content方法返回一個ContentResult對象,它將天氣報告轉換成的HTML作為響應類型,Content-Type報頭設置為 “text/html” 。

using?App;var?app?=?WebApplication.Create();
app.MapGet("weather/{city}/{days}",?Forecast);
app.Run();static?IResult?Forecast(HttpContext?context,?string?city,?int?days)
{var?report?=?WeatherReportUtility.Generate(city,days);return?Results.Content(WeatherReportUtility.AsHtml(report),?"text/html");
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281530.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281530.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281530.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫(二)tab補全功能,使數據庫支持簡體中文,日志管理,備份腳本

一、如何在MySQL數據庫中使用tab鍵補全功能 1.修改主配置文件/etc/my.cnf vim /etc/my.cnf [mysql] #no-auto-rehash auto-rehash 2.重啟MySQL服務&#xff0c;登錄測試 /etc/init.d/mysqld restart mysql -uroot -p (可在數據庫中使用tab鍵&#xff09; 3.&#xff1b;臨時支持…

php new self()關鍵字的用法

今天開框架源碼&#xff0c;發現有用到new self()的用法 有點不懂 在網上查了一下&#xff0c;給大家說一下&#xff1a; 在類中 self的用法 和this的用法差不多 &#xff0c; php new self() 一般在類內部使用&#xff0c;作用是對自身類實例化&#xff0c;下面給個實例講解…

android listview item置頂,ListView的item置頂

ListView的item設置置頂1.activitypublic class TopListViewActivity extends Activity {private static int ON_TOP 1;private static int CANCEL_TOP 0;public static String TOP_STATES "TOP";private ListView mListView;private List sessionList;private Se…

電信運營商x86服務器定制策略

近幾年&#xff0c;伴隨云計算、大數據、移動互聯網、物聯網等新技術從概念到實踐&#xff0c;業務、用戶數據海量式爆發增長&#xff0c;作為承載這些業務發展的服務器行業也面臨巨大的機遇和挑戰。一方面&#xff0c;需求的爆發式增長大幅提升了市場空間&#xff0c;尤其是大…

企業數字化轉型服務+方案

前言&#xff1a;本文的閱讀對象是公司老板、或企業高層管理者&#xff01;1【背景介紹】數字經濟與實體經濟深度融合是助推我國經濟高質量發展的重要環節。為加快數字中國建設&#xff0c;中央和地方政府都出臺各類政策扶植數字化轉型相關項目。馬云在接受采訪時也提到&#x…

在 MongoDB 上模擬事務操作來實現支付

我們的產品叫「學海密探」&#xff0c;屬于在線教育行業&#xff0c;產品需要有支付功能&#xff0c;然而支付最蛋疼是什么&#xff1f;有人會說是支付寶和微信等支付接口的接入開發&#xff01;沒錯&#xff0c;但支付接口的開發算是比較簡單的了&#xff0c;我覺得凡是跟錢有…

Zabbix server is not running

問題描述 Dashbord中提示Zabbix server is not running 分析過程 首先查看zabbix-server的運行狀態 systemctl status zabbix-server 確定是否是active(running)狀態&#xff0c;如果不是&#xff0c;重啟zabbix-server查看log tail -f /var/log/zabbix/zabbix_server.log 導致…

android 把異常寫入到文本里,嘗試在Android中將文件寫入sdcard時發生FileNotFoundException(權限被拒絕)...

從標題中可以看到&#xff0c;我在Android中將文件寫入sdcard時遇到問題.我想寫入將在sdcard上的公共空間中的文件&#xff0c;以便任何其他應用程序都可以讀取它。首先&#xff0c;我檢查sdcard是否已安裝&#xff1a;Environment.getExternalStorageState();然后&#xff0c;…

.NET性能優化-使用ValueStringBuilder拼接字符串

前言這一次要和大家分享的一個Tips是在字符串拼接場景使用的&#xff0c;我們經常會遇到有很多短小的字符串需要拼接的場景&#xff0c;在這種場景下及其的不推薦使用String.Concat也就是使用運算符。 目前來說官方最推薦的方案就是使用StringBuilder來構建這些字符串&#xff…

Buildroot 龍芯1C支持指南

本文轉載自&#xff1a;https://github.com/pengphei/smartloong-sphinx/blob/master/source/cn/loongson1c_buildroot_guide.rst Buildroot 龍芯1C支持指南 引子&#xff1a;從龍芯1C預訂拿到板子已經很長一段時間了&#xff0c;因為各種事情&#xff0c;一直讓它呆在角落的冷…

STOLUCK:經濟下行的當下 ,STO或將幫助中小企業度過寒冬

2018年被稱為創業陣亡率特別高的一年&#xff0c;相關報道稱有近20%的創業團隊面臨“后續融資跟不上&#xff0c;可能死在春天來臨之前”的窘境。經濟不景氣的當下&#xff0c;上下游資金不足&#xff0c;信貸機構沒錢&#xff0c;風投業捉襟見肘。實際今年3月份開始&#xff0…

[ 轉載 ] Java面試精選【Java基礎第一部分】

http://www.cnblogs.com/hnlshzx/p/3491587.html 轉載于:https://www.cnblogs.com/ILoke-Yang/p/8137326.html

html如何自動調整邊框大小,html – Chrome與大小調整:顯示中的邊框:表格

我正在使用display&#xff1a;table做一個小的2窗格布局.對于間距(也來自背景圖像),我使用填充.因為我需要孩子們有一個確切的寬度&#xff1a;50&#xff05;來自可用空間(考慮到父div的填充),我使用Box-sizing&#xff1a;border-Box.這在Opera中運行良好,但在Chrome中,框大…

淺析C# Dictionary實現原理

一、前言二、理論知識1、Hash 算法2、Hash 桶算法3、解決沖突算法三、Dictionary 實現1. Entry 結構體2. 其它關鍵私有變量3. Dictionary - Add 操作4. Dictionary - Find 操作5. Dictionary - Remove 操作6. Dictionary - Resize 操作(擴容)7. Dictionary - 再談 Add 操作8. C…

對特朗普獲勝感到意外? 那你是被社交媒體迷惑了

北京時間11月10日消息&#xff0c;據外媒報道&#xff0c;昨天曠日持久的美國總統選戰終于告一段落&#xff0c;特朗普的獲勝讓民調徹底成了一張廢紙&#xff0c;而早就在Facebook上提前歡慶希拉里勝利的人則徹底蒙圈了&#xff0c;就連萬里之外的中國吃瓜群眾們也開始追著許多…

貓晚流量再創記錄,阿里云直播方案護航優酷2500萬用戶體驗

2019獨角獸企業重金招聘Python工程師標準>>> 對“剁手黨而言&#xff0c;天貓雙11早已經超越了簡單的“買買買”&#xff0c;更是一場邊看邊玩的狂歡盛宴。今年的天貓雙11狂歡夜晚會&#xff08;簡稱“貓晚”&#xff09;在上海舉辦&#xff0c;這臺兼具年輕潮流與國…

python實現二叉樹和它的七種遍歷

介紹&#xff1a; 樹是數據結構中非常重要的一種&#xff0c;主要的用途是用來提高查找效率&#xff0c;對于要重復查找的情況效果更佳&#xff0c;如二叉排序樹、FP-樹。另外可以用來提高編碼效率&#xff0c;如哈弗曼樹。 代碼&#xff1a; 用python實現樹的構造和幾種遍歷算…

.NET性能系列文章二:Newtonsoft.Json vs System.Text.Json

微軟終于追上了&#xff1f;圖片來自 Glenn Carstens-Peters[1]Unsplash[2]歡迎來到.NET 性能系列的另一章。這個系列的特點是對.NET 世界中許多不同的主題進行研究、基準和比較。正如標題所說的那樣&#xff0c;重點在于使用最新的.NET7 的性能。你將看到哪種方法是實現特定主…

android gpu平板 推薦,性能強的不像話,最強安卓平板華為平板M6上手

原標題&#xff1a;性能強的不像話&#xff0c;最強安卓平板華為平板M6上手你為什么買平板電腦&#xff1f;當這一問題問出以后&#xff0c;許多朋友的表情都很微妙&#xff0c;隨后大概率的回答則相當統一&#xff1a;"我買平板干嘛&#xff1f;"。其實得到這樣一個…

【Python】HackBack(獲取暴力破解服務器密碼的IP來源)

1、前言 又在0x00sec上翻到好東東。 https://0x00sec.org/t/python-hackback-updated/882 帖子里的腳本會得到那些暴力服務器密碼失敗的IP和用戶名&#xff0c;并且使用shodan api做一個溯源定位。 #!/usr/bin/python3.4 import re import urllib.request import json log_path…