《ASP.NET Core 6框架揭秘》實例演示[02]:基于路由、MVC和gRPC的應用開發

ASP.NET Core可以視為一種底層框架,它為我們構建出了基于管道的請求處理模型,這個管道由一個服務器和多個中間件構成,而與路由相關的EndpointRoutingMiddleware和EndpointMiddleware是兩個最為重要的中間件。MVC和gRPC開發框架就建立在路由基礎上。本篇提供了四個實例用來演示如何利用路由、MVC和gRPC來開發API/APP。[本文節選《ASP.NET Core 6框架揭秘》第1章]

[113]路由的應用(源代碼)
[114]開發MVC API(源代碼)
[115]開發MVC APP(源代碼)
[116]開發gRPC API(源代碼)

[113]路由的應用

ASP.NET Core的路由是由EndpointRoutingMiddleware和EndpointMiddleware這兩個中間件實現的,在所有預定義的中間件類中,這應該算是最重要的兩個中間件了,因為不僅僅是MVC和gRPC框架建立在路由系統之上,后面介紹的Dapr.NET針對發布訂閱和Actor編程模式也是如此。如下面的代碼片段所示,我們在利用WebApplicationBuilder將代表承載應用的WebApplication對象構建出來之后,并沒有注冊任何的中間件,而是調用它的MapGet擴展方法注冊了一個指向路徑“/greet”的路由終結點(Endpoint)。該終結點的處理器是一個指向Greet方法的委托,意味著請求路徑為“/greet”的GET請求會路由到這個終結點,并最終調用這個方法進行處理。

using?App;
var?builder?=?WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGreeter,?Greeter>().Configure<GreetingOptions>(builder.Configuration.GetSection("greeting"));
var?app?=?builder.Build();
app.MapGet("/greet",?Greet);
app.Run();static?string?Greet(IGreeter?greeter)?=>?greeter.Greet(DateTimeOffset.Now);

ASP.NET Core的路由系統的強大之處在于,我們可以使用任何類型的委托作為注冊終結點的處理器,路由系統在調用處理器方法之前會“智能地”提取相應的數據初始化每一個參數。當方法執行之后,它還會針對我們具體返回的對象來對請求實施響應。對于我們提供的Greet方法來說,路由系統在調用它之前會利用依賴注入容器提供作為參數的IGreeter對象。由于返回的是一個字符串,文本經過編碼后會直接作為響應的主體內容, 響應的內容類型(Content-Type)最終會被設置為“text/plain”。程序啟動之后,如果我們利用瀏覽器請求“/greet”這個路徑,針對當前時間解析出來的問候語會以圖1的形式呈現出來。

e9fbbb2b27ee5e3a714c91f0c2b712b0.jpeg
圖1 采用路由返回的問候

[114]開發MVC API

我們直接將上面演示的程序改寫成MVC應用。MVC應用以Controller為核心,所有的請求總是指向定義在某個Controller類型中的某個Action方法。當應用接收到請求之后,會激活對應的Controller對象,并通過執行對應的Action方法來處理該請求。按照約定,合法的Controller類型必須是以“Controller”作為后綴命名的公共實例類型。我們一般會讓定義的Controller類型派生自Controller基類以“借用”一些有用的API,但這不是必須的,比如下面定義的GreetingController就沒有指定基類。

public?class?GreetingController
{[HttpGet("/greet")]????public?string?Greet([FromServices]?IGreeter?greeter)?=>?greeter.Greet(DateTimeOffset.Now);
}

由于MVC框架是建立在路由系統之上的,定義在Controller類型中的Action方法最終會轉換成一個或者多個注冊到指定路徑模板的終結點。對于定義在GreetingController類型中的Action方法Greet來說,我們通過標注的HttpGetAttrbute特性不僅為對應的路由終結點定義了針對HTTP方法的約束(該終結點僅限于處理GET請求),還同時指定了綁定的請求路徑(“/greet”)。

依賴的服務可以直接注入到Controller類型中。具體來說,它支持兩種注入形式,一種是注入到構造函數中,另一種則是直接注入到Action方法中。對于方法注入,對應參數上必須標注一個FromServiceAttribute特性。我們IGreeter對象就是采用這種方式注入注入到Greet方法中的。和路由系統針對返回對象的處理方式一樣,MVC框架針對Action方法的返回值也會根據其類型進行針對性的處理。Greet方法直接返回的字符串會直接作為響應的主體內容,響應的內容類型(Content-Type)會被設置為“text/plain”。

在完成了針對GreetingController類型的定義之后,我們需要對入口程序進行如下的修改。如代碼片段所示,在完成了針對IGreeter服務的注冊和針對GreetingOptions配置選項的設置之后,我們調用同一個IServiceCollection對象的AddControllers擴展方法注冊了與Controller相關服務的注冊。在WebApplication對象被構建出來后,我們調用了它的MapControllers擴展方法將定義在所有Controller類型中的Action方法映射為對應的終結點。程序啟動之后,如果我們利用瀏覽器請求“/greet”這個路徑,我們依然會得到如圖1的所示的輸出結果。

using?App;
var?builder?=?WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGreeter,?Greeter>().Configure<GreetingOptions>(builder.Configuration.GetSection("greeting")).AddControllers();
var?app?=?builder.Build();
app.MapControllers();
app.Run();

[115]開發MVC APP

上面改造的MVC程序并沒有涉及到視圖,請求的響應內容是由Action方法直接提供的,現在我們利用視圖來呈現最終響應的內容。由于上個例子調用IServiceCollection接口的AddControllers擴展方法只會注冊Controller相關的服務,現在我們得將其換成AddControllersWithViews方法。顧名思義,新的擴展方法會將視圖相關的服務添加進來。

using?App;
var?builder?=?WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IGreeter,?Greeter>().Configure<GreetingOptions>(builder.Configuration.GetSection("greeting")).AddControllersWithViews();
var?app?=?builder.Build();
app.MapControllers();
app.Run();

我們對GreetinigController進行了改造。如下面的代碼片段所示,我們讓它繼承Controller這個基類。Action方法Greet的返回類型改為IActionResult接口,具體返回的是通過View方法創建的代表默認視圖(針對當前Action方法)的ViewResult對象。在Action方法返回之前,它還利用對ViewBag的設置將當前時間傳遞到呈現的視圖中。

public?class?GreetingController?:?Controller
{[HttpGet("/greet")]????public?IActionResult?Greet(){ViewBag.Time?=?DateTimeOffset.Now;????????return?View();}
}

ASP.NET Core MVC采用Razior視圖引擎,視圖被定義成一個后綴名為.cshtml的文件,這是一個按照Razor語法編寫的靜態HTML和動態C#代碼動態交織的文本文件。由于上面為了呈現試圖調用的View方法沒有指定任何參數,所以視圖引擎會根據當前Controller的名稱(“Greeting”)和Action的名稱(“Greet”)去定位定義目標視圖的.cshtml文件。為了迎合默認的視圖定位規則,我們需要采用Action的名稱來命名創建的視圖文件(Greet.cshtml),并將其添加到“Views/Greeting”目錄下。

@using?App
@inject?IGreeter?Greeter;
<html><head><title>Greeting</title></head><body><p>@Greeter.Greet((DateTimeOffset)ViewBag.Time)</p></body>
</html>

上面這個代碼片段就是添加的視圖文件(Views/Greeting/Greet.cshtml)的內容。總體來說,這是一個HTML文檔,除了在主體部分呈現的問候語文本(前置的@字符定義動態執行的C#表達式)是根據指定時間動態解析出來的,其他內容則均為靜態的HTML。我們借助@inject指令將依賴的IGreeter對象以屬性的形式注入進來,并且將屬性名稱設置為Greeter,所以我們可以在視圖中直接調用它的Greet方法得到呈現的問候語。調用Greet方法指定的時間是GreetingController利用ViewBag傳遞過來的,所以我們可以直接利用它將其提取出來。程序啟動之后,如果我們利用瀏覽器請求“/greet”這個路徑,雖然瀏覽器也會呈現出相同的文本(如圖2所示),但是響應的內容是完全不同的。之前響應的僅僅是內容類型為“text/plain”的單純文本,現在響應則是一份完整的HTML文檔,內容類型為“text/html”。

693769f8e2feb88491ee9a8b94697968.jpeg
圖2 以試圖形式返回的問候

[116]開發gRPC API

雖然Vistual Studio提供了創建gRPC的項目模板,該模板提供的腳手架會自動為我們創建一系列的初始文件,同時也會對項目做一些初始設置,但這反而是筆者不想要的,至少是不希望在這里使用這個模板。和前面一樣,我們希望演示的實例只包含最本質和必要的元素,所以我們選擇在一個空的解決方案上構建gRPC應用。

e731a0916709d3796bc881608aa5fb82.png
圖3 gRPC解決方案

如圖3所示,我們在一個空的解決方案上添加了三個項目。Proto是一個空的類庫項目,我們將會使用它來存放標準的Proto Buffers消息和gRPC服務的定義;Server是一個空的ASP.NET Core應用,gRPC服務的實現類型就放在這里,它同時也是承載gRPC服務的應用。Client是一個控制臺程序,我們用它來模擬調用gRPC服務的客戶端。gRPC是語言中立的遠程調用框架,gRPC服務契約使用到的數據類型都采用標準的定義方式。具體來說,gRPC傳輸的數據采用Proto Buffers協議進行序列化,Proto Buffers采用高效緊湊的二進制編碼。我們將用于定義數據類型和服務的Proto Buffers文件定義在Proto項目中,在這之前我們需要為這個空的類庫項目添加針對“Grpc.AspNetCore”這個NuGet包的引用。

不再使用簡單的“Hello World”,現在我們為演示的gPRC服務指定另一種稍微“復雜”一點的應用場景——用它來完成簡單的加、減、乘、除運算。我們在Proto項目中添加一個名為Calculator.proto的文本文件,并在其中以如下的形式將Calculator這個rGPC服務定義出來。如代碼片段所示,這個服務包含四個操作,它們的輸入和輸出都被定義成Proto Buffers消息。作為輸入的InputMessage消息包含兩個整型的數據成員(表示運算的兩個操作數)。返回的OutpuMessage消息除了通過result表示計算結果外,還具有status和error兩個成員,前者表示計算狀態(成功還是失敗),后者提供計算失敗時的錯誤消息。

syntax?=?"proto3";
option?csharp_namespace?=?"App";service?Calculator?{rpc?Add?(InputMessage)?returns?(OutpuMessage);rpc?Substract?(InputMessage)?returns?(OutpuMessage);rpc?Multiply?(InputMessage)?returns?(OutpuMessage);rpc?Divide?(InputMessage)?returns?(OutpuMessage);}message?InputMessage?{int32?x?=?1;int32?y?=?2;}message?OutpuMessage?{int32?status?=?1;int32?result?=?2;string?error?=?3;}

創建的Calculator.proto文件無法直接使用,我們需要利用內置的代碼生成器將它轉換成.cs代碼。具體的作為很簡單,我們只需要在Visual Studio的解決方案窗口中右鍵選擇這個文件,打開如圖4所示的屬性對話框。我們在Build Action下拉列表中選擇“Protobuf compiler”選項,同時在gRPC Stub Classes下拉列表中選擇“Client and Server”。

3720dbc6c9cca5e8f45f4502b411dc8a.png
圖4 Calculator.proto文件屬性對話框

做了這樣的設置之后,在任何時對Calculator.proto文件所作的改變都將觸發代碼的自動生成,具體生成的.cs文件會自動保存在obj目錄下。由于在gRPC Stub Classes下拉列表中選擇了“Client and Server”選項,所以它不僅會生成服務端用來定義服務實現類型的Stub類,還會生成客戶端用來調用服務的Stub類。上面以可視化形式所作的設置最終會體現在項目文件(Proto.csproj)上,所以我們直接修改此文件也可以達到相同的目的,如下所示的就是這個文件的完整內容。

<Project?Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net6.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><None?Remove="Calculator.proto"?/></ItemGroup><ItemGroup><PackageReference?Include="Grpc.AspNetCore"?Version="2.40.0"?/></ItemGroup><ItemGroup><Protobuf?Include="Calculator.proto"?/></ItemGroup>
</Project>

Proto項目中的Calculator.proto文件僅僅是按照標準的形式定義的“服務契約”,我們需要在Server項目中定義具體的實現類型。在添加了針對Proto項目的引用之后,我們定義了如下這個名為CalculatorService的gRPC服務實現類型。如代碼片段所示,我們讓CalculatorService類型繼承自一個內嵌于Calculator中的CalculatorBase類型,這個Calculator類型就是根據Calculator.proto生成的一個類型。

public?class?CalculatorService?:?Calculator.CalculatorBase
{private?readonly?ILogger?_logger;public?CalculatorService(ILogger<CalculatorService>?logger)?=>?_logger?=?logger;public?override?Task<OutpuMessage>?Add(InputMessage?request,??ServerCallContext?context)?=>?InvokeAsync((op1,?op2)?=>?op1?+?op2,?request);public?override?Task<OutpuMessage>?Substract(InputMessage?request,????ServerCallContext?context)?=>?InvokeAsync((op1,?op2)?=>?op1?-?op2,?request);public?override?Task<OutpuMessage>?Multiply(InputMessage?request,?????ServerCallContext?context)?=>?InvokeAsync((op1,?op2)?=>?op1?*?op2,?request);public?override?Task<OutpuMessage>?Divide(InputMessage?request,?????ServerCallContext?context)?=>?InvokeAsync((op1,?op2)?=>?op1?/?op2,?request);private?Task<OutpuMessage>?InvokeAsync(Func<int,?int,?int>?calculate,?????InputMessage?input){OutpuMessage?output;try{output?=?new?OutpuMessage?{?Status?=?0,?Result?=?calculate(input.X,?input.Y)?};}catch?(Exception?ex){_logger.LogError(ex,?"Calculation?error.");output?=?new?OutpuMessage?{?Status?=?1,?Error?=?ex.ToString()?};}return?Task.FromResult(output);}
}

Calculator.proto文件為Calcultor服務定義的四個操作會轉換成CalculatorBase類型中對應的虛方法,我們按照上面的方式重寫了它們。在完成了針對gRPC服務實現類型的定義之后,我們需要對承載它的入口程序定義編寫如下的代碼。由于gRPC采用HTTP2傳輸協議,所以在利用WebApplicationBuilder的WebHost屬性得到對應的IWebHostBuilder對象,我們調用其ConfigureKestrel擴展方法讓默認注冊的Kestrel服務器監聽的終結點默認采用HTTP2協議。gRPC相關的服務通過調用IServiceCollection接口的AddGrpc擴展方法進行注冊。由于gRPC也是建立在路由系統之上的,定義在服務中的每個操作最終也會轉換成相應的路由終結點,這些終結點的生成和注冊是通過調用WebApplication對象的MapGrpcService<TService>擴展方法完成的。

using?App;
using?Microsoft.AspNetCore.Server.Kestrel.Core;
var?builder?=?WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(kestrel?=>?kestrel.ConfigureEndpointDefaults(?endpoint?=>?endpoint.Protocols?=??HttpProtocols.Http2));
builder.Services.AddGrpc();
var?app?=?builder.Build();
app.MapGrpcService<CalculatorService>();
app.Run();

Calculator.proto文件生成的代碼包含用來調用對應gRPC服務的Stub類,所以模擬客戶端的Client項目也需要添加對Proto項目的引用。在此之后,我們可以編寫如下的程序調用gRPC服務完成四種基本的數學運算。

using?App;using?Grpc.Core;using?Grpc.Net.Client;using?var?channel?=?GrpcChannel.ForAddress("http://localhost:5000");var?client?=?new?Calculator.CalculatorClient(channel);var?inputMessage?=?new?InputMessage?{?X?=?1,?Y?=?0?};await?InvokeAsync(input?=>?client.AddAsync(input),?inputMessage,?"+");await?InvokeAsync(input?=>?client.SubstractAsync(input),?inputMessage,?"-");await?InvokeAsync(input?=>?client.MultiplyAsync(input),?inputMessage,?"*");await?InvokeAsync(input?=>?client.DivideAsync(input),?inputMessage,?"/");static?async?Task?InvokeAsync(Func<InputMessage,?AsyncUnaryCall<OutpuMessage>>?invoker,??InputMessage?input,?string?@operator){var?output?=?await?invoker(input);if?(output.Status?==?0){Console.WriteLine($"{input.X}{@operator}{input.Y}={output.Result}");}else{Console.WriteLine(output.Error);}}

如上面的代碼片段所示,我們通過調用GrpcChannel類型的靜態方法ForAddress針對gRPC服務的地址“http://localhost:5000”創建了一個GrpcChannel對象,該對象表示與服務進行通信的“信道(Channel)”。我們利用它創建了一個CalculatorClient對象作為調用gRPC服務的客戶端或者代理,CalculatorClient類型同樣是內嵌在生成的Calculator類型中。最終我們利用這個代理完成了針對四種基本運算的服務調用,具體的gRPC調用實現在InvokeAsync這個本地方法中。接下來我們以命令行的方式先后啟動Server和Client應用,客戶端和服務端控制臺上會呈現出如圖5所示的輸出結果。由于我們傳入的參數分別為1和0,所以除了除法運算,其它三此調用都會返回成功的結果,針對除法的調用則會將錯誤信息呈現出來。由于CalculatorService進行了異常處理,并且將異常信息以日志的形式記錄了下來,所以錯誤信息也輸出到了服務端的控制臺上。

94c762fd4cd7b85b36d360b5ffd15f3f.png

圖5 gRPC應用的承載與調用

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

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

相關文章

什么是 JWT -- JSON WEB TOKEN

什么是JWT Json web token (JWT), 是為了在網絡應用環境間傳遞聲明而執行的一種基于JSON的開放標準&#xff08;(RFC 7519).該token被設計為緊湊且安全的&#xff0c;特別適用于分布式站點的單點登錄&#xff08;SSO&#xff09;場景。JWT的聲明一般被用來在身份提供者和服務提…

Re-installation failed due to different application signatures.

問題&#xff1a; 在虛擬設備上運行程序時提示安裝失敗。 [2010-08-08 00:38:30 - myApp] Re-installation failed due to different application signatures. [2010-08-08 00:38:30 - myApp] You must perform a full uninstall of the application. WARNING: This will remo…

【ArcGIS微課1000例】0024:ArcGIS如何連接文件夾、設認工作目錄、默認地理數據庫、相對路徑與絕對路徑?

ArcGIS軟件在初次安裝完成或者為了工作的方便,通常需要連接到指定的文件夾、設置默認工作路徑,默認地理數據庫、相對路徑與絕對路徑等。 文章目錄 1. 文件夾連接2. 默認工作目錄3. 默認地理數據庫4. 相對路徑與絕對路徑1. 文件夾連接 在初次安裝完ArcGIS時,默認沒有文件夾連…

shell 用環境變量的值修改properties文件

假設有如下屬性文件 demo.properties user.nametest user.password123456 ............................... 需求&#xff1a;先需要通過shell 腳本將 user.name 和 user.password 的value值替換為實際需要的用戶名和密碼&#xff0c; 將可以通過如下方式實現&#xff1a; sed …

【Spring Cloud】Redis緩存接入監控、運維平臺CacheCloud

CacheCloud CacheCloud提供一個Redis云管理平臺&#xff1a;實現多種類型(Redis Standalone、Redis Sentinel、Redis Cluster)自動部署、解決Redis實例碎片化現象、提供完善統計、監控、運維功能、減少運維成本和誤操作&#xff0c;提高機器的利用率&#xff0c;提供靈活的伸縮…

[Win10應用開發] 使用 Windows 推送服務 (WNS)

前言 Windows 推送服務&#xff08;WNS&#xff09;也是 Win10 通知機制中的一種&#xff0c;今天與大家一起學習一下有關WNS的相關知識。使用 Windows 推送服務的前提是你需要有一個微軟開發者賬號&#xff0c;這樣才能得到一些合法的密鑰信息用于與WNS服務器完成通訊操作。 …

Windows 11 新版 25158 推送!全新搜索框和圖標、小組件動態內容和通知標記

面向 Dev 頻道的 Windows 預覽體驗成員&#xff0c;微軟現已推送 Windows 11 預覽版 Build 25158。主要變化1.微軟宣布為 Windows 11 搜索引入全新視覺體驗&#xff0c;由搜索框或重新設計的搜索圖標呈現。目前該功能僅向部分 Windows 預覽體驗成員推出&#xff0c;將在未來向所…

Python之路【第一篇】:環境搭建

虛擬機安裝 下載VMwareWorkstation以及centos,安裝完VMwareWorkstation&#xff0c;創建一個虛擬機&#xff0c;然后在新創建的虛擬機上運行centos linux環境搭建 公司開發使用linux的原因&#xff1a;穩定、安全、開源 在虛擬機中使用centos這個版本&#xff0c;作為服務器端的…

【BIM入門實戰】Revit創建地形的幾種方法及優缺點

Revit在體量和場地選項卡的【地形表面】工具可以創建三維地形,有三種方法:放置點、指定點文件和導入實例文件、傾斜攝影點云技術和InfraWorks地形生成。 文章目錄 1. 放置點2. 指定點文件3. 導入實例文件4. 傾斜攝影點云技術5. InfraWorks地形生成1. 放置點 放置點功能位于體…

2024年起重機司機(限門式起重機)證考試題庫及起重機司機(限門式起重機)試題解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2024年起重機司機(限門式起重機)證考試題庫及起重機司機(限門式起重機)試題解析是安全生產模擬考試一點通結合&#xff08;安監局&#xff09;特種作業人員操作證考試大綱和&#xff08;質檢局&#xff09;特種設備作…

微服務架構下的統一身份認證和授權

一、預備知識 本文討論基于微服務架構下的身份認證和用戶授權的技術方案&#xff0c;在閱讀之前&#xff0c;最好先熟悉并理解以下幾個知識點&#xff1a; 微服務架構相關概念&#xff1a;服務注冊、服務發現、API 網關身份認證和用戶授權&#xff1a;SSO、CAS、OAuth2.0、JW…

使用vh來制作高度自適應頁面和元素垂直居中

為什么80%的碼農都做不了架構師&#xff1f;>>> vh單位 vh是CSS3中的一個長度單位&#xff0c;其值為&#xff1a;100vh 視窗高度。即如果窗口高度為500px&#xff0c;那么 1vh 5px。具體的值會隨著瀏覽器視窗高度的改變而實時改變&#xff0c;因此可以利用這個單…

傳智168期JavaEE struts2杜宏 day32~day33(2017年2月15日23:27:09)

struts2學習完畢&#xff0c;寒假學習效率還不錯。 筆記鏈接 鏈接&#xff1a;http://pan.baidu.com/s/1boBJLVp 密碼&#xff1a;wwl4轉載于:https://www.cnblogs.com/huangtao1996/p/6403886.html

GitLab的安裝、配置、使用

前言上周去參與“中國數字經濟創新發展大會”了&#xff0c;然后又忙新項目的事情&#xff0c;博客又有一段時間沒有更新&#xff0c;今天周一事情比較少&#xff0c;立刻開始寫文&#xff0c;最近有挺多值得記錄的東西~進入正文&#xff0c;最近我們搭了個Gitlab&#xff0c;并…

【BIM入門實戰】Navisworks2018簡體中文安裝教程(附安裝包下載)

Navisworks是Autodesk公司開發的一款三維模型可視化軟件,它以輕量化的運行方式進行BIM成果的后期處理及整合,是一款非常實用的軟件。基于Navisworks,項目的參建方可以在施工前進行模擬施工,以達到減少返工、縮短工期、提供經濟效益的目的。 Navisworks同時支持4D和5D模擬,…

微軟 Windows11 Build 22000.71 更新(KB5004252)發布

微軟推出了一個全新的娛樂小工具。這一部件允許用戶查看 Microsoft Store 中可用的新電影和精選電影。選擇一部電影會引導用戶到 Microsoft Store 查看有關該影片的更多信息。 7 月 16 日消息 今日凌晨&#xff0c;微軟宣布向預覽體驗計劃用戶發布 Windows 11 Build22000.71 更…

Python入門教程之Python保留字符大全

Python中的保留字不能用作常數或變數&#xff0c;或任何其他標識符名稱。所有 Python 的關鍵字只包含小寫字母。 andexecnotassertfinallyorbreakforpassclassfromprintcontinueglobalraisedefifreturndelimporttryelifinwhileelseiswithexceptlambdayield轉載于:https://blog.…

Linux操作系統基礎解析之(五)——grep命令家族及正則表達式初識

grep號稱文本處理三劍客之一&#xff0c;雖然說是三劍客中功能最少也是最簡單的&#xff0c;但仍然不能小覷。 grep的全稱為&#xff1a;Global search REgular expression and Print out the line&#xff0c;即&#xff1a;全面查找正則表達式并將匹配的行顯示出來。 那么這…

Ubuntu16.04換源

Ubuntu16.04換源 轉載于:https://www.cnblogs.com/xielisen/p/6404607.html

【BIM入門實戰】Revit模型導入到第三方軟件方法匯總

本文以案例的方式,匯總展示了Revit模型導入到ArcGIS Pro、3ds max、Navisworks、Lumion、InfraWorks等的方法。 文章目錄 1. Revit導入ArcGIS Pro2. Revit導入3ds Max3. Revit導入Navisworks4. Revit導入Lumion5. Revit導入InfraWorks1. Revit導入ArcGIS Pro ArcGIS Pro2.8可…