Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲美女在线播放,久久久国产99久久国产一,日韩精品一区二区三区在线观看

          整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          開(kāi)發(fā)者怎樣才能寫(xiě)出好的 API?

          開(kāi)發(fā)者怎樣才能寫(xiě)出好的 API?

          文最初發(fā)表于STX Next博客網(wǎng)站,經(jīng)原作者 Sebastian Buczyński 同意由 InfoQ 中文站翻譯分享。

          現(xiàn)在,每個(gè)人都在關(guān)注 API。API 最早開(kāi)始流行于大約 20 年前,2000 年,Roy Fielding 在他的博士論文中首次提出了 REST 這個(gè)術(shù)語(yǔ)。同年,Amazon、Salesforce 和 eBay 向全世界的開(kāi)發(fā)者介紹了他們的 API,永遠(yuǎn)改變了我們構(gòu)建軟件的方式。

          在 REST 之前,Roy Fielding 論文中的原則被稱為“HTTP 對(duì)象模型”,隨后你會(huì)明白這為何非常重要。

          隨著閱讀的深入,你還會(huì)看到如何確定你的 API 是否成熟,好 API 的主要品質(zhì)是什么以及為何在構(gòu)建 API 的時(shí)候,要注重適應(yīng)性。

          RESTful 架構(gòu)基礎(chǔ)

          REST 代表表述性狀態(tài)轉(zhuǎn)移(Representational State Transfer),由 Roy Fielding 在他的博士論文中定義,長(zhǎng)期以來(lái),它就是服務(wù) API 的圣杯。它并不是構(gòu)建 API 的唯一方式,但是由于它的流行,即便是非開(kāi)發(fā)人員也知道這種標(biāo)準(zhǔn)。

          RESTful 軟件有如下六種特點(diǎn):

          1. 客戶端-服務(wù)器端架構(gòu)
          2. 無(wú)狀態(tài)
          3. 可緩存
          4. 分層系統(tǒng)
          5. 按需編碼(可選)
          6. 統(tǒng)一接口

          但是,對(duì)日常使用來(lái)說(shuō),這過(guò)于理論化了。我們需要更具操作性的東西,這也就是 API 成熟度模型。

          Richardson 成熟度模型

          該模型是由 Leonard Richardson 提出的,它將 RESTful 開(kāi)發(fā)原則結(jié)合成四個(gè)簡(jiǎn)單易行的步驟。

          在模型中的位置越高,就越接近 Roy Fielding 所定義的 RESTful 原始理念。

          Level 0:POX(Plain Old XML)的泥沼

          Level 0 的 API 是一組簡(jiǎn)單 XML 或 JSON 的描述。在前文中,我曾經(jīng)說(shuō)過(guò)在 Fielding 的論文之前,RESTful 原則被稱為“HTTP 對(duì)象模型”。

          這是因?yàn)?HTTP 是 RESTful 開(kāi)發(fā)中最重要的組成部分。REST 要盡可能多地使用 HTTP 固有屬性中的理念。

          在 Level 0,沒(méi)有使用任何這樣的東西。我們只是構(gòu)建自己的協(xié)議并把它作為一個(gè)專有層。這種架構(gòu)被稱為遠(yuǎn)程過(guò)程調(diào)用(Remote Procedure Call,RPC),適用于遠(yuǎn)程過(guò)程/命令。

          通常我們會(huì)有一個(gè)端點(diǎn),可以對(duì)它進(jìn)行調(diào)用以獲取一堆 XML。在這方面,一個(gè)典型的例子就是 SOAP 協(xié)議:

          另外一個(gè)很好的例子就是 Slack API。它有些多樣化,有多個(gè)端點(diǎn),但依然是 RPC 風(fēng)格的 API。它暴露了 Slack 的各種功能,中間沒(méi)有附加任何特性。如下的代碼展示了如何向一個(gè)特定的通道發(fā)送消息:

          雖然按照 Richardson 的模型,這是一個(gè) Level 0 的 API,但是這并不意味著它是不好的。只要它是可用的,并且恰當(dāng)?shù)胤?wù)于業(yè)務(wù)需求,那它就是很棒的 API。

          Level 1:資源

          為了構(gòu)建 Level 1 的 API,我們需要找出系統(tǒng)中的名詞并將它們通過(guò)不同的 URL 暴露出來(lái),如下面的樣例所示:

          其中,“/api/books”能讓我訪問(wèn)一個(gè)通用的圖書(shū)目錄,“/api/profile”能夠讓我訪問(wèn)這些書(shū)的作者的基本信息。為了獲取某個(gè)資源的第一個(gè)特定實(shí)例,我可以在 URL 中添加 ID(或其他引用)。

          在 URL 中還可以嵌套資源,這展示了它們是以層級(jí)結(jié)構(gòu)的形式組織的。

          回到 Slack 的樣例,如下展示了按照 Level 1 API,它們會(huì)是什么樣子的:

          現(xiàn)在,URL 發(fā)生了變化,從原先的“/api/chat.postMessage”變成了現(xiàn)在的“/api/channels/general/messages”。

          信息中“channel”部分從請(qǐng)求體轉(zhuǎn)移到了 URL 中。從字面就能看出,通過(guò)使用這個(gè) URL,我們可以預(yù)期有條消息發(fā)布到了“general”通道上。

          Level 2:HTTP 動(dòng)作

          Level 2 利用 HTTP 動(dòng)作(verb)來(lái)添加更多的含義和意圖。在這方面可用的動(dòng)作比較多,我這里只用到一個(gè)基礎(chǔ)的子集:PUT / DELETE / GET / POST。

          借助這些動(dòng)作,我們可以預(yù)期包含它們的 URL 有不同的行為:

          • POST:創(chuàng)建新數(shù)據(jù)
          • PUT:更新現(xiàn)有的數(shù)據(jù)
          • DELETE:移除數(shù)據(jù)
          • GET:查找特定 id 的數(shù)據(jù)輸出,獲取某個(gè)資源(或整個(gè)集合)

          以上面提到的“/api/books”為例:

          那這里的“安全”和“冪等”又是什么意思呢?

          “安全”的方法指的是永遠(yuǎn)不會(huì)改變數(shù)據(jù)的方法。REST 建議 GET 方法只能用來(lái)獲取數(shù)據(jù),所以在上面的集合中,它是唯一一個(gè)安全的方法。不管你調(diào)用多少次基于 REST 的 GET 方法,它永遠(yuǎn)不會(huì)改變數(shù)據(jù)庫(kù)中的任何東西。但是,這并不是該動(dòng)作的固有特性,而是關(guān)系到你該如何實(shí)現(xiàn)它,所以我們需要確保它是這樣運(yùn)行的。所有其他的方法都會(huì)以不同的方式改變數(shù)據(jù),不能隨意使用。在 REST 中,GET 方法既是安全的,又是冪等的。

          “冪等”的方法指的是多次使用不會(huì)產(chǎn)生不同結(jié)果的方法。按照 REST,DELETE 方法應(yīng)該是冪等的,如果刪除了某個(gè)資源,然后針對(duì)相同的資源再次調(diào)用 DELETE,它不會(huì)改變?nèi)魏螙|西。資源應(yīng)該早就已經(jīng)消失了。在 REST 規(guī)范中,POST 是唯一一個(gè)非冪等的方法,所以我們可以對(duì)相同的資源多次調(diào)用 POST 方法,這樣我們會(huì)得到重復(fù)的資源。

          我們重新看一下 Slack 樣例,如果我們使用 HTTP 動(dòng)作來(lái)進(jìn)行更多的操作會(huì)是什么樣子:

          我們可以使用 POST 方法發(fā)送消息到通用的通道,我們也可以使用 GET 方法從通用通道獲取消息。我們還可以使用 DELETE 方法和特定的 ID 刪除消息,這里比較有意思的一點(diǎn)在于,消息并不是與特定通道關(guān)聯(lián)的,所以我可以設(shè)計(jì)一個(gè)單獨(dú)的 API 來(lái)刪除資源。這個(gè)例子表明,設(shè)計(jì) API 并不總是那么簡(jiǎn)單,這方面有很多可選項(xiàng)和權(quán)衡。

          Level 3:HATEOAS

          還記得純文字、沒(méi)有任何圖像的電腦游戲嗎?我們只能看到一些文本,描述了你在哪里,以及接下來(lái)能干什么。為了取得進(jìn)展,我們必須要輸入自己的選擇。在一定程度上來(lái)講,HATEOAS 就是做這件事情的。

          HATEOAS 指的是“超媒體作為應(yīng)用狀態(tài)引擎(Hypermedia as the Engine of Application State)”。

          有了 HATEOAS 之后,當(dāng)其他人使用你的 API 的時(shí)候,他們就能看到通過(guò) API 還能做哪些其他的事情。HATEOAS 回答了“從這里出發(fā),我還能去哪里?”的問(wèn)題。

          但這還不是所有的內(nèi)容。HATEOAS 還可以對(duì)數(shù)據(jù)關(guān)系進(jìn)行建模。我們可能會(huì)有一個(gè)關(guān)于圖書(shū)的資源,并且在 URL 中沒(méi)有將作者信息嵌套進(jìn)來(lái),但是我們可以包含它們的鏈接,如果有人對(duì)作者感興趣的話,那么他們可以訪問(wèn)這些鏈接并探索相關(guān)的數(shù)據(jù)。

          HATEOAS 不像其他成熟度模型的等級(jí)那樣流行,但是有些開(kāi)發(fā)人員確實(shí)在使用它。其中一個(gè)樣例就是 Jira,如下是它們的搜索 API 的響應(yīng):

          他們將鏈接嵌入到了其他我們可以探索的資源中,以及該 issue 的狀態(tài)過(guò)渡列表。

          另外一個(gè)使用 HATEOAS 的樣例是 Artsy。他們的 API 嚴(yán)重依賴 HATEOAS,并且還使用了 JSON Plus 調(diào)用規(guī)范,按照該規(guī)范強(qiáng)制要求使用一種特殊的約定來(lái)構(gòu)建鏈接。下面是一個(gè)分頁(yè)的例子,這是使用 HATEOAS 最酷的樣例之一:

          我們可以提供到下一頁(yè)、上一頁(yè)、第一頁(yè)和最后一頁(yè)的鏈接,還可以按照需要添加其他頁(yè)面的鏈接。這樣簡(jiǎn)化了 API 的消費(fèi),因?yàn)檫@樣不需要在客戶端添加 URL 的解析邏輯,也不需要追加頁(yè)碼的方法。我們只需要在客戶端使用已經(jīng)實(shí)現(xiàn)結(jié)構(gòu)化的鏈接就可以了。

          好的 API 由什么組成

          我們已經(jīng)介紹完了 Richardson 模型,但這并不是實(shí)現(xiàn)好的 API 的全部?jī)?nèi)容。其他重要的品質(zhì)還有什么呢?

          錯(cuò)誤/異常處理

          我對(duì)自己使用的 API 的基本期望之一就是,需要有一種明確的方式來(lái)判斷是否有錯(cuò)誤或異常。我想要知道請(qǐng)求是否得到了處理。

          HTTP 有一種簡(jiǎn)單的方式來(lái)實(shí)現(xiàn)這一點(diǎn):HTTP 狀態(tài)碼。

          管理狀態(tài)碼的基本規(guī)則是:

          • 2xx 代表一切正常
          • 3xx 代表你想要找的公主在另外一個(gè)城堡,也就是你要找的資源在其他的地方
          • 4xx 代表客戶端做錯(cuò)了某些事情
          • 5xx 代表服務(wù)器端失敗

          我們的 API 至少要提供 4xx 和 5xx 狀態(tài)碼。有時(shí)候,5xx 是自動(dòng)生成的。例如,客戶端發(fā)送了一些內(nèi)容到服務(wù)器端,但是這非法的請(qǐng)求,而我們的校驗(yàn)是有缺陷的,從而導(dǎo)致這個(gè)問(wèn)題繼續(xù)在代碼中執(zhí)行了下去,最終導(dǎo)致出現(xiàn)了異常,這樣就會(huì)返回一個(gè) 5xx 的狀態(tài)碼。

          如果你想要承諾使用特定的狀態(tài)碼,那么你會(huì)遇到“哪種狀態(tài)碼最適合當(dāng)前情況?”的問(wèn)題。這樣的問(wèn)題并不總是那么容易回答,我推薦你去閱讀聲明這些狀態(tài)碼的 RFC,它們給出了比其他來(lái)源更廣泛的解釋,并且告訴了你何時(shí)使用這些狀態(tài)碼更合適等。幸運(yùn)的是,網(wǎng)上有些資源可以幫助我們做出選擇,比如Mozilla的HTTP狀態(tài)碼指南。

          文檔

          優(yōu)秀的 API 必須要有優(yōu)秀的文檔。在文檔方面,最大的問(wèn)題在于,隨著 API 的發(fā)展需要找人同步更新文檔。有個(gè)更好的方案是不脫離代碼自更新文檔。

          例如,注釋與代碼的脫節(jié)。當(dāng)代碼發(fā)生變化的時(shí)候,注釋依然保持不變,這樣的話,注釋就過(guò)時(shí)了。這甚至?xí)雀揪蜎](méi)有任何注釋更糟糕,因?yàn)樵陔S后的一段時(shí)間內(nèi),它們會(huì)提供錯(cuò)誤的信息。注釋不會(huì)自動(dòng)更新,所以開(kāi)發(fā)人員需要記得在維護(hù)代碼的時(shí)候同時(shí)維護(hù)它們。

          自更新的文檔工具可以解決這個(gè)問(wèn)題。在這方面,一個(gè)流行的工具就是 Swagger,它是基于 OpenAPI 構(gòu)建的工具,可以很容易地描述你的 API。

          Swagger 很酷的一點(diǎn)在于它是可執(zhí)行的,所以如果你嘗試修改 API,能立即看到它的作用和變化。

          為了給 Swagger 添加自動(dòng)更新功能,我們需要使用其他的插件和工具。在 Python 中,有針對(duì)大多數(shù)主流框架的插件。它們能生成 API 請(qǐng)求該如何組織的描述,并定義數(shù)據(jù)的輸入和輸出。

          如果你不想要使用 Swagger,而是想使用更簡(jiǎn)單的工具,那該怎么辦呢?有個(gè)流行的替代方案是Slate。

          還有一些值得推薦的中間方案,如widdershins和api2html的組合,它允許我們從 Swagger 的定義中生成類似 Slate 的文檔。

          緩存

          在有些系統(tǒng)中,緩存可能并不是什么大問(wèn)題。這樣的系統(tǒng)可能沒(méi)有很多的數(shù)據(jù)可供緩存,所有的數(shù)據(jù)都在不斷地發(fā)生變化,或者系統(tǒng)根本沒(méi)有很大的流量。

          但是,在大多數(shù)情況下,緩存對(duì)于良好的性能至關(guān)重要。它與 RESTful API 密切相關(guān),因?yàn)?HTTP 協(xié)議在緩存方面做了很多事情,比如 HTTP 頭信息允許我們控制緩存的行為。

          你可能想要在客戶端緩存東西,或者如果有注冊(cè)表或值存儲(chǔ)的話,那么你可能想要在應(yīng)用程序中緩存數(shù)據(jù)。但是,HTTP 讓我們能夠基本上免費(fèi)就可以獲得一個(gè)很好的緩存,所以如果可能的話,請(qǐng)不要錯(cuò)過(guò)這個(gè)免費(fèi)的午餐。

          同時(shí),因?yàn)榫彺媸?HTTP 規(guī)范的一部分,所以很多涉及 HTTP 的技術(shù)都知道如何進(jìn)行緩存:瀏覽器原生支持緩存,客戶端和服務(wù)器之間的中間技術(shù)也是如此。

          API 設(shè)計(jì)的演化

          構(gòu)建 API 以及現(xiàn)代軟件最重要的部分就是適應(yīng)性。如果沒(méi)有適應(yīng)性,開(kāi)發(fā)就會(huì)變慢,在合理的時(shí)間發(fā)布特性就會(huì)變得更加困難,當(dāng)面對(duì)最后截止時(shí)間的時(shí)候更是如此。

          “軟件架構(gòu)”在不同的上下文語(yǔ)境中有不同的含義,不過(guò)我們現(xiàn)在采用這個(gè)定義:

          軟件架構(gòu)一種行為/藝術(shù),能夠避免會(huì)阻礙未來(lái)變化的決策。

          記住了這一點(diǎn),在設(shè)計(jì)軟件的時(shí)候,當(dāng)你必須要在具有相似優(yōu)點(diǎn)的方案中做出選擇時(shí),你應(yīng)該始終選擇更多考慮到未來(lái)的方案。

          好的實(shí)踐并不是萬(wàn)能的。按照正確的方式構(gòu)建錯(cuò)誤的東西并不是你想要的結(jié)果。最好采取一種成長(zhǎng)的心態(tài),接受變化是不可避免的,尤其是如果你的項(xiàng)目要持續(xù)發(fā)展的話更是如此。

          要想讓你的 API 更具適應(yīng)性,其中很關(guān)鍵的一點(diǎn)就是保持盡可能薄的 API 層,真正的復(fù)雜性應(yīng)該往下層轉(zhuǎn)移。

          API 不應(yīng)該限定實(shí)現(xiàn)

          公開(kāi)的 API 發(fā)布之后,它就已經(jīng)完成了,是不可改變的,你就不能再去觸碰它了。如果你已經(jīng)有了一個(gè)設(shè)計(jì)古怪的 API,除了接受現(xiàn)狀之外,還能做些什么呢?

          你應(yīng)該不斷尋找簡(jiǎn)化實(shí)現(xiàn)的方法。有時(shí)候,你可以通過(guò)一個(gè)特定的 HTTP 頭信息來(lái)控制 API 響應(yīng)的格式,相對(duì)于構(gòu)建另外一個(gè)叫做 v2 的新 API,這是一種更簡(jiǎn)單的解決方案。

          API 只是另外一層的抽象。它們不應(yīng)該決定如何實(shí)現(xiàn),為了避免這種問(wèn)題,我們可以采用如下幾種開(kāi)發(fā)模式。

          API 網(wǎng)關(guān)

          這是一種類似于門(mén)面的開(kāi)發(fā)模式。如果你要把一個(gè)單體結(jié)構(gòu)拆分為一組微服務(wù),并且希望向外部暴露一些功能的話,那么你只需要構(gòu)建一個(gè)類似門(mén)面的 API 網(wǎng)關(guān)。

          它將為不同的微服務(wù)提供一個(gè)統(tǒng)一的接口(這些微服務(wù)可能有不同的 API,使用不同的錯(cuò)誤格式等等)。

          適用于前端的后端

          如果你必須要構(gòu)建一個(gè) API 來(lái)滿足一堆不同的客戶端的話,那么這可能會(huì)非常困難。針對(duì)某個(gè)客戶端所作出的決策可能會(huì)影響其他客戶端的功能。

          按照適用于前端的后端(backend for frontend)理念,如果你有不同的客戶端,它們喜歡不同形式的 API,比如移動(dòng)應(yīng)用可能會(huì)喜歡使用 GraphQL,那么就單獨(dú)為它們構(gòu)建吧。

          只有當(dāng)你的 API 是一層抽象,并且這個(gè)抽象層很薄的時(shí)候,這種方式才有效。如果它與你的數(shù)據(jù)庫(kù)耦合,或者太大,具有太多的邏輯,那么就無(wú)法這樣做了。

          GraphQL 與 RESTful

          很多人都在熱炒 GraphQL。它是一項(xiàng)新興的技術(shù),但是已經(jīng)有了很多粉絲,以至于有些開(kāi)發(fā)者聲稱它將取代 REST。

          盡管 GraphQL 比 RESTful 要新的多,但是它們有很多相似之處。GraphQL 最大的不足之處在于它的緩存,它必須要在客戶端或應(yīng)用程序中實(shí)現(xiàn)。現(xiàn)在,有內(nèi)置的實(shí)現(xiàn)了緩存功能的客戶端庫(kù)(比如Apollo),但是這仍然要比使用 HTTP 提供的幾乎免費(fèi)的緩存功能要困難。

          從技術(shù)講,GraphQL 位于 Richardson 模型的 Level 0 層級(jí),但是它具有良好 API 的特質(zhì)。我們可能無(wú)法同時(shí)使用多個(gè) HTTP 的功能,但是 GraphQL 的出現(xiàn)就是解決這一問(wèn)題的。

          GraphQL 的殺手锏就是聚合不同的 API,并將它們作為一個(gè) GraphQL API 暴露出來(lái)。


          GraphQL 在處理數(shù)據(jù)抓取不足和數(shù)據(jù)過(guò)量抓取方面有很好的效果,而這些問(wèn)題是 REST API 很難進(jìn)行管理的。這兩個(gè)問(wèn)題都與性能有關(guān),如果數(shù)據(jù)抓取不足,那說(shuō)明你沒(méi)有高效地使用 API,所以必須要進(jìn)行大量的調(diào)用。如果數(shù)據(jù)過(guò)量抓取的話,那么 API 調(diào)用的數(shù)據(jù)傳輸會(huì)比必要的數(shù)據(jù)傳輸更大,這是對(duì)帶寬的一種浪費(fèi)。

          小結(jié)

          借助 REST 與 GraphQL 的比較,我們能夠總結(jié)出一個(gè)好的 API 最重要的品質(zhì)。

          好的 API 的特性

          我們需要一個(gè)清晰的數(shù)據(jù)表述方式:RESTful 以資源的方式提供了表述。我們需要有一種方式顯示有哪些可用的操作:RESTful 通過(guò)組合資源和 HTTP 動(dòng)作實(shí)現(xiàn)這一點(diǎn)。我們需要有一種方式來(lái)確認(rèn)是否存在錯(cuò)誤/異常:HTTP 狀態(tài)碼可以實(shí)現(xiàn)這一點(diǎn),可能還會(huì)包含闡述它們的響應(yīng)信息。最好能夠提供 API 發(fā)現(xiàn)和導(dǎo)航的功能:在 RESTful 中,HATEOAS 負(fù)責(zé)實(shí)現(xiàn)這一點(diǎn)。有好的文檔是非常重要的:在這方面,可執(zhí)行、自更新的文檔可以解決這個(gè)問(wèn)題,這超出了 RESTful 規(guī)范的范圍。最后,但同樣重要的是,優(yōu)秀的 API 應(yīng)該具有緩存功能,除非你的特定情況認(rèn)為它是不必要的。

          REST 和 GraphQL 之間最大的區(qū)別是它們處理緩存性的方式。當(dāng)我們使用 REST 方式構(gòu)建 API 的時(shí)候,我們基本上可以免費(fèi)獲得 HTTP 的緩存功能。如果選擇 GraphQL 的話,你需要自行負(fù)責(zé)為客戶端或應(yīng)用程序添加緩存。

          原文鏈接:

          https://www.stxnext.com/blog/how-to-build-a-good-api-that-wont-embarrass-you

          延伸閱讀:

          4種主流的API架構(gòu)風(fēng)格對(duì)比-InfoQ

          關(guān)注我并轉(zhuǎn)發(fā)此篇文章,即可獲得學(xué)習(xí)資料~若想了解更多,也可移步InfoQ官網(wǎng),獲取InfoQ最新資訊~

          Excel VBA中可以引用Excel工作表函數(shù),也可以引用Excel VBA函數(shù),還可以引用用戶自己定義的函數(shù)或過(guò)程。除此以外,還可以調(diào)用Windows API。

          Windows API包括幾千個(gè)可調(diào)用的函數(shù),這些函數(shù)是Windows提供給應(yīng)用程序與操作系統(tǒng)的接口,他們猶如“積木塊”一樣,可以搭建出各種界面豐富,功能靈活的應(yīng)用程序。它們大致可以分為以下幾個(gè)大類:

          	基本服務(wù);
          	組件服務(wù);
          	用戶界面服務(wù);
          	圖形多媒體服務(wù);
          	消息和協(xié)作;
          	網(wǎng)絡(luò);
          	Web服務(wù)。
          

          Windows API使用 .lib 文件。.lib 文件也就是庫(kù)文件,分為靜態(tài)庫(kù)文件和動(dòng)態(tài)庫(kù)文件(DLL)

          靜態(tài)鏈接就是把靜態(tài)鏈接庫(kù)中的函數(shù)直接復(fù)制到程序中,成為程序的一部分。

          動(dòng)態(tài)鏈接是指在程序運(yùn)行時(shí)將已駐留在內(nèi)存中的動(dòng)態(tài)鏈接庫(kù)中的函數(shù)在需要時(shí)鏈接起來(lái)一起運(yùn)行。

          API 的 dll 在 windows 系統(tǒng)的 system32 目錄下, 圖形界面相關(guān)的 API 在 USER32.dll 里,進(jìn)程、文件之類的操作在 kernel32.dll 里。MSDN 的每個(gè)函數(shù)都會(huì)說(shuō)明它在哪個(gè)頭文件, 哪個(gè) lib, 哪個(gè) dll 里的。

          動(dòng)態(tài)鏈接庫(kù)中的函數(shù)可以被VBA調(diào)用,下面就以一個(gè)實(shí)例來(lái)說(shuō)明。

          在kernel32.dll中有一個(gè) GetSystemDirectory()函數(shù),可以到到Windows的系統(tǒng)路徑。以下就是通過(guò)一個(gè)過(guò)程來(lái)調(diào)用這個(gè)函數(shù)的實(shí)例:

          Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" _
          (ByVal lpBuffer As String, ByVal nSize As Long) As Long
           Sub info()
          Dim sPath As String * 260, lLen As Long
          lLen=GetSystemDirectory(sPath, 260)
          Text3=Left(sPath, lLen)
          VBA.MsgBox (Text3)
          End Sub
          

          效果如下:

          1 調(diào)用API操作流程

          1.1查詢?nèi)绾蝹鬟f參數(shù)到DLL函數(shù)的Declare語(yǔ)句格式

          為了調(diào)用Windows API中的函數(shù),需要描述這些可用的函數(shù)的文檔規(guī)范,如何在VBA中聲明這些函數(shù),以及如何調(diào)用它們。下面是兩個(gè)有用的資源:

          I 可以使用API Viewer加載宏查找和復(fù)制需要的Declare語(yǔ)句。可以在下面的站點(diǎn)下載API聲明查看器:

          http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html

          登錄以下頁(yè)面后在以下點(diǎn)擊下載:

          安裝后打開(kāi)需要的文件:

          即可查看可以使用的API及聲明:

          II Microsoft Platform SDK,包含復(fù)雜的Windows API文檔。可以在下面的地址中查看:http://www.office-cn.net/t/api/index.html?apihelp.htm

          可以使用的API函數(shù)類別:

          1.2 使用Declare語(yǔ)句

          在從VBA中調(diào)用DLL里的函數(shù)之前,必須為VBA提供在哪里找到函數(shù)以及如何調(diào)用該函數(shù)的信息:

          Declare語(yǔ)句是一個(gè)定義,告訴VBA在哪里找到特定的DLL函數(shù)以及如何調(diào)用該函數(shù)。在代碼中添加Declare語(yǔ)句最簡(jiǎn)單的辦法是使用API Viewer加載宏,其中包含Windows API中大多數(shù)函數(shù)的Declare語(yǔ)句,也包含一些函數(shù)所需要的常量和類型定義。

          Declare語(yǔ)句聲明的形式如下:

          [Public|Private]Declare Sub name Lib "libname" [Alias "aliasname"][([arglist])]
          [Public|Private]Declare Function name Lib "libname" [Alias "aliasname"] [([arglist])] [As type]
          

          下面是GetTempPath函數(shù)的Declare語(yǔ)句的示例,該函數(shù)返回Windows臨時(shí)文件夾的路徑(默認(rèn)為C:\Windows\Temp):

          Private Declare Function GetTempPath Lib "kernel32" _
          Alias "GetTempPathA" (ByVal nBufferLength As Long, _
          ByVal lpBuffer As String) As Long
          

          I 關(guān)鍵字Declare告訴VBA在工程中要包含的DLL函數(shù)的定義。在標(biāo)準(zhǔn)模塊中的Declare語(yǔ)句可以是公共的或私有的,取決于你希望API函數(shù)僅用于單個(gè)模塊還是整個(gè)工程。在類模塊中,Declare語(yǔ)句必須是私有的。

          II 在關(guān)鍵字Function之后是函數(shù)的名字,具體地說(shuō),是從VBA中調(diào)用該函數(shù)時(shí)使用的名字。這個(gè)名字可以與API函數(shù)本身的名字相同,也可以在Declare語(yǔ)句中使用關(guān)鍵字Alias指定打算在VBA中通過(guò)不同的名字(別名)調(diào)用該函數(shù)。

          III 在上面的示例中,在DLL中API函數(shù)的名字是GetTempPathA,從VBA中調(diào)用該函數(shù)時(shí)使用的名字是GetTempPath。注意,DLL函數(shù)的實(shí)際名字出現(xiàn)在關(guān)鍵字Alias之后,同時(shí)也注意到GetTempPath是Win32API.txt文件用于該函數(shù)的別名(有充分必要使用別名),但你可以將其改變?yōu)槿魏文阆胍拿帧?/p>

          IV 關(guān)鍵字Lib指定包含函數(shù)的DLL。

          1.3 在過(guò)程中調(diào)用API函數(shù)。

          2 實(shí)例應(yīng)用場(chǎng)景

          有如下任務(wù):判斷一個(gè)文件框如果內(nèi)容為空,則顯示一個(gè)提示文本框進(jìn)行提示,并在3秒后自動(dòng)消息。

          我們知道,VBA提供以下代碼的提示對(duì)話框,但它需要用戶自己點(diǎn)擊關(guān)閉按鈕才可以關(guān)閉,不能滿足我們的需要。

          MsgBox ("提示:編號(hào)不能為空!")

          2.1 插入用戶窗體,并添加兩個(gè)文本框,如下:

          2.2 在VBE中插入模塊,并添加以下代碼:

          Private Declare Function MsgBoxTimeout Lib "user32" _
           Alias "MessageBoxTimeoutA" ( _
           ByVal hwnd As Long, _
           ByVal lpText As String, _
           ByVal lpCaption As String, _
           ByVal wType As VbMsgBoxStyle, _
           ByVal wlange As Long, _
           ByVal dwTimeout As Long) _
          As Long
          Sub PopupMsgbox(Optional prompt As String="OK", Optional title As String="友情提示", Optional seconds As Long=300)
          MsgBoxTimeOut 0, prompt, title, 64, 0, seconds
          End Sub
          

          2.3 為文本框添加事件代碼:

          Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
          If TextBox1.Value="" Then
          'MsgBox ("提示:編號(hào)不能為空!")
          PopupMsgbox "編號(hào)不能為空!", "提示", 1500 '1.5秒后提示窗口自動(dòng)關(guān)閉
          End If
          End Sub
          

          2.4 當(dāng)文本框?yàn)榭眨髽?biāo)光標(biāo)點(diǎn)擊到文本框以外的其它位置時(shí),就會(huì)彈出提示對(duì)話框,并在1.5秒后自動(dòng)關(guān)閉,如下:

          MsgBoxTimeout()是一個(gè)未公開(kāi)的 API 函數(shù)。

          此函數(shù)的參數(shù)如下:

          • hwnd:消息框擁有者窗口的句柄,可以設(shè)為 0
          • lpText:消息框顯示內(nèi)容,類似于 MsgBox 函數(shù)的第一個(gè)參數(shù) Prompt
          • lpCaption:消息框標(biāo)題,類似于 MsgBox 函數(shù)的第三個(gè)參數(shù) Caption
          • wType:消息框類型,類似于 MsgBox 函數(shù)的第二個(gè)參數(shù) Buttons
          • wlange:函數(shù)擴(kuò)展,一般取 0
          • dwTimeout:消息框延遲關(guān)閉時(shí)間,單位為毫秒

          總結(jié)上例使用API的流程:

          I Declare MsgBoxTimeOut

          II 定義PopupMsgbox過(guò)程,在此過(guò)程中調(diào)用了MsgBoxTimeOut

          III 在其他過(guò)程中調(diào)用PopupMsgbox()

          也可以聲明后直接調(diào)用:

          Dim i As Long
          i=MsgBoxTimeout(0, "編號(hào)不能為空!", "提示", vbYesNo, 0, 1500)
          

          -End-

          束驗(yàn)證 DOM 方法

          PropertyDescription
          checkValidity()如果 input 元素中的數(shù)據(jù)是合法的返回 true,否則返回 false。
          setCustomValidity()設(shè)置 input 元素的 validationMessage 屬性,用于自定義錯(cuò)誤提示信息的方法。使用 setCustomValidity 設(shè)置了自定義提示后,validity.customError 就會(huì)變成true,則 checkValidity 總是會(huì)返回false。如果要重新判斷需要取消自定義提示,方式如下:
          setCustomValidity('') setCustomValidity(null) setCustomValidity(undefined)

          以下實(shí)例如果輸入信息不合法,則返回錯(cuò)誤信息:

          checkValidity() 方法

          <inputid="id1"type="number"min="100"max="300"required><buttononclick="myFunction()">驗(yàn)證</button><pid="demo"></p><script>

          functionmyFunction(){varinpObj=document.getElementById("id1"); if(inpObj.checkValidity()==false){document.getElementById("demo").innerHTML=inpObj.validationMessage; }}

          </script>


          主站蜘蛛池模板: 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 国产精品污WWW一区二区三区| 国产一区二区在线看| 久久99精品一区二区三区| 国产一区二区好的精华液| 在线精品国产一区二区三区 | 精品国产福利第一区二区三区| 精品少妇人妻AV一区二区| 亚洲午夜电影一区二区三区| 日本不卡免费新一区二区三区| 91久久精一区二区三区大全| 波多野结衣一区二区三区88| 亚洲一区电影在线观看| 蜜臀AV一区二区| 久久久精品人妻一区二区三区四| 色噜噜AV亚洲色一区二区| 丝袜美腿高跟呻吟高潮一区| 国产视频一区二区在线观看| 国产一区二区在线观看| 亚洲AV无码国产一区二区三区 | 国产高清在线精品一区| 精品视频一区二区三三区四区| 久夜色精品国产一区二区三区| 久久一区二区三区免费| 日韩人妻无码一区二区三区久久99 | 亚洲福利视频一区二区| 中文字幕一区二区三区在线播放 | 国产精品一区二区久久精品| 亚洲狠狠狠一区二区三区| 国产福利微拍精品一区二区| 无码aⅴ精品一区二区三区| 日本香蕉一区二区三区| 久久se精品一区精品二区国产 | 国产乱码一区二区三区四| 亚洲日韩AV一区二区三区中文| 亚州AV综合色区无码一区| 日韩AV无码一区二区三区不卡| 国产激情一区二区三区 | 色窝窝无码一区二区三区成人网站 | 日韩精品中文字幕视频一区 | 久久一区二区精品综合|