介
在 Go 語言中,如果一個函數或者方法需要返回任何錯誤,通常會使用 error 接口類型作為返回類型。在標準庫中,所有返回了錯誤信息的函數和方法使用的都是這個接口。例如,下面是 http 包中 Get 方法的聲明:
清單 1.1
http://golang.org/pkg/net/http/#Client.Get
在 清單 1.1 的代碼中,Get 方法的第二個返回參數是一個 error 接口類型的值。要處理函數或者方法返回的錯誤值,首先需要檢查這個值是否為 nil:
清單 1.2
在 清單 1.2 的代碼中,調用了 Get 方法,方法的返回值賦給了兩個局部變量,然后用變量 err 和 nil 進行了比較,如果這個值不是 nil,則說明發生了錯誤。
由于我們處理錯誤值時用的是接口,所以需要定義一個實現了這個接口的具體類型。標準庫已經為我們定義了一個叫做 errorString 的結構,并且實現了 error 接口。在這篇文章里,我們會介紹 error 接口和 errorString 結構的實現以及如何使用。
Error 接口和 errorString 結構
Go 語言為我們直接提供了 error 接口的聲明:
清單 1.3
http://golang.org/pkg/builtin/#error
在 清單 1.3 的代碼中,我們看到了 error 接口只聲明了一個叫做 Error 的方法,這個方法返回一個 string。所以,一個類型只要實現了 Error 方法也就實現了 error 接口,就可以作為 error 接口類型的實例來使用。如果你對 Go 語言中的接口還不太熟悉的話,可以參考我的另一篇文章 接口、方法以及嵌入類型
同時,標準庫也聲明了一個叫做 errorString 的結構,我們可以在 errors 包中找到它的代碼:
清單 1.4
在 清單 1.4 的代碼中,我們可以看到 errorString 結構只聲明了一個 string 類型的字段 s。這個類型連同它唯一的字段都是非公開的,也就是說我們不能直接訪問這個類型或者其中的字段。要了解更多 Go 語言中關于 非公開標識符的內容,可以參考這篇文章 Go 語言中的 公開 / 非公開 標識符。
errorString 結構實現了 error 接口
清單 1.5
http://golang.org/src/pkg/errors/errors.go
在 清單 1.5 的代碼中,errorString 是以指針接受者的方式來實現 error 接口的。也就是說,只有 errorString 結構的指針才可以作為 error 接口實例來使用。而且由于 errorString 類型和它的字段都是非公開的,所以我們不能進行類型檢測或者類型轉化。我們唯一可以做的就是調用它的 Error 方法。
在標準庫中,errorString 是作為 error 接口實例來使用的最常用的具體錯誤類型。現在我們已經知道了這些類型的定義,接下來我們就來學習一下標準庫提供了哪些方式,通過 errorString 結構來創建 error 接口的實例。
創建 Error 實例
標準庫提供了兩種創建 errorString 指針實例,并作為 error 接口實例來使用的方法。如果你需要返回的錯誤信息只是一個簡單的字符串,沒有特殊的格式要求,那么 errors 包中的 New 函數就是你需要的:
清單 1.6
清單 1.6 的代碼中,展示了 errors 包中的 New 函數的典型使用方式。在這個例子中,通過調用 New 函數,我們聲明并且初始化了一個 error 接口的實例。下面我們來看一下 New 函數的聲明和實現:
清單 1.7
http://golang.org/src/pkg/errors/errors.go
在 清單 1.7 列出的的 New 函數的聲明中,我們可以看到函數接收一個 string 類型的參數,返回一個 error 接口的實例。在函數的實現部分,創建了一個 errorString 結構的指針。然后在返回語句中,編譯器創建了一個 error 接口實例并且和這個 errorString 結構的指針進行了綁定來滿足函數對返回值的要求。這樣 errorString 結構的指針就成了返回的 error 接口實例的具體類型了。
如果你需要返回的錯誤信息需要格式化,可以使用 fmt 包中的 Errorf 函數
清單 1.8
清單 1.8 的代碼中,展示了 Errorf 函數的典型用法。如果你對 fmt 包中的其它格式化函數比較熟悉,那么你會發現這個函數的用法和其它格式化函數的用法是一樣的。同樣的,我們通過調用 Errorf,聲明并且初始化了一個 error 接口的實例。
下面我們來看一下 Errorf 函數的聲明和實現:
清單 1.9
http://golang.org/src/pkg/fmt/print.go
在 清單 1.9 列出的 Errorf 函數的聲明部分,我們看到了 error 接口類型又一次的被用作返回類型。在函數的實現部分,用 errors 包中的 New 函數為格式化后的錯誤信息創建了一個 error 接口的實例。所以,不管你用 errors 包還是 fmt 包來創建 error 接口實例,底層都是一個 errorString 結構的指針。
我們已經知道了用 errorString 類型指針來創建 error 接口實例的兩種不同的方法,接下來,讓我們的來看一下標準庫是如何對 API 調用返回的不同錯誤值進行區分提供支持的。
比較錯誤值
和其它標準庫一樣,bufio 包使用 errors 包中的 New 函數創建包級別的 error 接口變量:
清單 1.10
http://golang.org/src/pkg/bufio/bufio.go
清單 1.10 的代碼中,bufio 包聲明并且初始化了 4 個包級別的 error 接口變量。注意每個變量名都是以 Err 開頭的,這是 Go 語言中的命名規范。困為這些變量聲明為了 error 接口類型,我們就可以用 這些變量來對從 bufio 包中不同 API 的調用返回的錯誤值進行識別。
清單 1.11
在 清單 1.11 的代碼中,通過 ufio.Reader 指針類型的變量 b, 調用了 Peek 方法。Peek 方法可能返回 ErrNegativeCount 或者 ErrBufferFull 這兩個錯誤變量中的一個。由于這些變量是公開的,所以我們就可以通過這些變量來判斷具體返回的是哪個錯誤。這些變量成了包的錯誤處理 API 的一部分。
假設 bufio 包沒有聲明這些 error 類型的變量,我們就不得不通過比較錯誤信息來判斷發生的是什么錯誤:
清單 1.12
清單 1.12 中的代碼中有兩個問題,一:對 Error() 的調用 ,會創建一個錯誤信息的拷貝,然后在 switch 語句中使用,二:如果包的作者作者更改了錯誤信息,這段代碼就不能正常工作了。
io 包是另一個為了可能返回的錯誤聲明 error 類型變量的例子:
清單 1.13
http://golang.org/src/pkg/io/io.go
清單 1.13 的代碼顯示了 io 包聲明了 6 個包級別的 error 類型變量。對包中函數的調用如果返回了第三個 error 類型變量 EOF,則說明沒有更多的輸入了。調用這個包中的函數后,常常需要把返回的錯誤值與 EOF 變量進行比較。
下面是 io 包中 ReadAtLeast 方法的實現代碼。
清單 1.14
http://golang.org/src/pkg/io/io.go
清單 1.14 列出的 ReadAtLeast 的實現代碼中,展示了如何使用這些變量。注意 ErrShortBuffer 和 ErrUnexpectedEOF 是如何作為返回值來使用的。也需要注意函數是如何用變量 err 與 EOF 進行比較的。和我們之前自己寫的代碼中的做法是一樣的。
在實現我們自己的函數庫的時候,可以考慮這種為包中函數可能返回的錯誤創建 error 變量的模式。這樣可以提供一個處理包中錯誤的 API ,并且保持錯誤處理的一致性。
為什么不用命名類型
大家可能會問,為什么 Go 語言不把 errroString 設計為一個命名類型?
讓我們看一下用命名類型來實現和用結構類型實現有什么區別。
清單 1.15
http://play.golang.org/p/uZPi4XKMF9
清單 1.15 中的代碼展示了如果把 erroString 作為一個命名類型來使用會遇到的問題。程序的第 9 行聲明了一個以 string 為基礎類型的命名類型 errorString。然后在第 12 行,為這個命名類型實現了 error 接口。為了模仿 errors 包中的 New 方法,在第 17 行為這個命名類型實現了 New 方法。
接著在第 21 和 22 行,聲明并初始化了兩個 error 類型變量。變量 ErrNamedType 是用 New 函數初始化的,而變量 ErrStructType 是用 errors.New 函數初始化的。最后在主函數里,我們把這兩個變量分別同用同樣的方法創建的變量進行了比較。
當你運行程序的時候,輸出的結果會比較有趣。
第 25 行的條件語句為真,而第 29 行的條件語句為假。使用命名類型時,我們可以用同樣的錯誤信息創建 error 接口實例,并且它們是相等的。這個問題和我們在 清單 1.12 中遇到的問題一樣。我們可以用相同的錯誤信息創建本地的 error 類型變量,并和包中聲明的 error 類型變量進行比較。但是如果包的作者更改了錯誤信息,我們的代碼就不能正常工作了。
當 errorString 是一個結構類型時,也可能出現同樣的問題。讓我們看一下用值接收者的方式來實現 error 接口會發生什么:
清單 1.16
http://play.golang.org/p/EMWPT-tWp4
清單 1.16 的代碼中,我們用值接收者的方式為類型 errorString 實現了 error 接口。這次我們遇到了和 清單 1.15 中使用命名類型時同樣的問題。當我們比較接口實例時,實際比較的是底層的具體實例(具體的錯誤信息)。
由于標準庫為 errorString 結構實現 error 接口時用的是指針接收者。所以 errors.New 方法必須返回一個指針實例。這個實例就是與 error 接口實例綁定的那個。并且每次都是不一樣的。在這些情況中,比較的是指針而不是底層具體的錯誤信息。
結論
這篇文章中,我們介紹了 error 接口是什么以及它是如何與 errorString 結構協同工作的。在 Go 語言中,通常用 errors.New 和 fmt.Errorf 來創建 error 接口實例,并且強烈推薦使用它們。通常來說一個簡單的錯誤信息加上一些基本的格式化,就是我們處理錯誤時需要的一切。
我們也學習了標準庫為了讓我們區分包中函數調用 返回的不同錯誤類型,而聲明一些 error 類型變量的模式。標準庫中的許多包都聲明并且公開了這些 error 類型的變量,通過這些變量,足夠讓我們區分包中函數返回的不同錯誤類型。
可能我們有時候需要創建自定義錯誤類型。這是我們會在 第二部分 里介紹的內容。目前,用標準庫提供的錯誤處理機制,按例子中的用法使用就可以了。
后續更新 Go 語言中的錯誤處理 - 第二部分,請關注
via: https://www.ardanlabs.com/blog/2014/10/error-handling-in-go-part-i.html
作者:William Kennedy 譯者:jettyhan 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
介
在 第一部分 中,我們學習了 error 接口以及標準庫是如何通過 errors 包來創建 error 接口值的。我們也學習了如何使用 error 接口值,通過這些值來判斷是否發生了錯誤。最后,我們學習了一些標準庫是如何通過導出 error 接口變量來幫助我們確定發生錯誤的具體類型。
在 Go 語言中什么時候應該使用自定義錯誤類型是比較難把握的。大部分情況下,error 包提供的 error 接口值對于報告和處理錯誤已經足夠了。但有時候,調用者可能希望知道錯誤發生時一些額外的上下文信息。在我看來,這種情況下就應該使用自定義錯誤類型。
在這篇文章里,我們將要學習自定義錯誤類型和標準庫中兩處使用自定義錯誤類型的實例。每個實例都提供了一個使用自定義錯誤類型的有趣的視角。之后我們會學習如何通過返回的 error 接口值確定具體的自定義錯誤類型以及獲取存儲在其中的指針信息,通過這些額外的信息怎樣能幫助我們做出更加合適的錯誤處理決定。
net 包
net 包中聲明了一個叫做 OpError 的自定義錯誤類型。指向這個結構的指針一般存儲在 error 接口值中返回給調用者。net 包內的許多函數和方法都用到了這個錯誤類型。
清單 1.1
http://golang.org/src/pkg/net/dial.go
清單 1.1 列出的是 net 包中 Listen 函數的實現代碼。我們可以看到,在第 4 行和第 13 行, 創建了 OpError 這個錯誤類型,并在返回語句中以 error 接口的方式返回給了調用者。由于 OpError 指針實現了 error 接口,所以它可以以 error 接口值返回。需要注意的是,在第 9 行和 11 行,對 ListenTCP 和 ListenUnix 函數的調用 ,同樣也可以通過 error 接口返回 OpError 的指針。
接下來,我們看一下 OpError 的聲明
清單 1.2
http://golang.org/pkg/net/#OpError
清單 1.2 顯示的是 OpError 結構的聲明。前三個字段提供了錯誤發生時相關網絡操作的上下文信息。第 17 行聲明了一個 error 接口類型。這個字段包含了實際發生的錯誤,通常情況下,這個值的具體類型是一個 errorString 的指針。
另一個需要注意的是自定義錯誤類型的命名規范,在 Go 語言中自定義錯誤類型通常以 Error 結尾。以后我們會在其它包中再次看到這樣的命名
接下來,我們看一下 OpError 對 error 接口的實現。
清單 1.3
http://golang.org/src/pkg/net/net.go
清單 1.3 中列出的是 error 接口的實現代碼,展示了如何用與錯誤發生時相關的信息構建建一個更加具體的錯誤信息。把上下文信息與錯誤綁定在一起可以提供額外的信息來幫助調用者做出更加合理的錯誤處理選擇。
JSON 包
json 包提供了 JSON 格式與 Go 原生格式的相互轉化的功能。所有可能產生的錯誤都是在內部生成的。維護與錯誤相關的上下文信息對于這個包是比較難的。json 包中有許多自定義錯誤類型,這些不同的錯誤類型可以被同一個函數或者方法返回。
讓我們看一下其中的一個自定義錯誤類型
清單 1.4
http://golang.org/src/pkg/encoding/json/decode.go
清單 1.4 列出了 UnmarshalTypeError 結構的聲明和對 error 接口的實現。這個自定義類型是用來說明發生了一個從 JSON 值到具體 Go 原生類型的轉化錯誤。這個結構包含 2 個字段,一個是第 4 行聲明的 Value,它包含了用于轉換的 JSON 數據,另一個是第 5 行聲明的 Type,它包含了將要轉化為的 Go 類型。第 8 行對 error 接口的實現中,用相關的上下文信息構建了一個合理的錯誤信息。
在這個例子里,根據錯誤類型的名稱就可以看出發生了什么錯誤,這個類型叫做 UnmarshalTypeError,這正是這個自定義錯誤類型發生時的上下文環境。當發生的錯誤與轉化失敗有關時,這個結構的指針就存儲在 error 接口中返回。
當調用 unmarshal 時傳入了一個非法的參數時,一個指向 InvalidUnmarshalError 的指針會存儲在 error 接口中返回。
清單 1.5
http://golang.org/src/pkg/encoding/json/decode.go
清單 1.5 列出了 InvalidUnmarshalError 的聲明和對 error 接口的實現。同樣的,類型名稱就明確了錯誤發生時的上下文信息。內部維護的狀態可以用來構建合適的錯誤信息,從而幫助調用者做出更加合理的錯誤處理選擇。
具體類型識別
在 net 包 Unmarshal 函數的例子中,隨 error 接口返回的錯誤可能是 UnmarshalTypeError, InvalidUnmarshalError 或者 errorString 中的一個。
清單 1.6
http://golang.org/src/pkg/encoding/json/decode.go
清單 1.6 顯示了對 Unmarshal 的調用返回的 error 接口中,是如何包含不同的具體錯誤類型指針的。在第 27 行中,unmarshal 方法返回了 InvalidUnmarshalError 的指針, 第 34 行,decodeState 變量中的 savedError 被返回,這個字段可能指向好幾個不同的具體錯誤類型。
我們已經知道 JSON 包是用自定義錯誤類型做為錯誤發生時的上下文信息的,那我們如何識別包含在 error 接口中的具體錯誤類型,從而做出更加合理的錯誤處理選擇呢?
讓我們從一個使 Unmarshal 函數的調用返回一個包含 UnmarshalTypeError: 自定義類型錯誤的程序開始。
清單 1.7
http://play.golang.org/p/FVFo8mJLBV
清單 1.7 是一個嘗試調用 unmarshal 把一段 JSON 文檔轉化為 Go 類型的例子,第 15 行的 JSON 文檔包含一個 name 字段,其中包含一個 bill 的字符串值。由于 user 類型中的 Name 字段在第 9 行被聲明為了 integer, 所以對 Unmarshal 的調用返回一個具體的錯誤類型 UnmarshalTypeError。
現在我們稍微修改一下 表 1.7 中的代碼,使 UNmarshal 的調用通過 error 接口返回不同的錯誤。
清單 1.8
http://play.golang.org/p/n8dQFeHYVp
清單 1.8 中的代碼在 表 1.7 的基礎上做了一些改動。在第 15 行,我們把傳給 Unmarshal 函數的參數換成了 u ,而不是之前它的地址。這個變化會使對 UNmarshal 函數的調用返回一個包含 InvalidUnmarshalError 具體錯誤的 error 接口值。
然后是在程序的第 17 行到第 24 行,添加了些有趣的代碼:
清單 1.9
第 17 行添加了一個 switch 語句來識別存儲在 error 接口中的具體錯誤類型。注意關鍵字 type 用在接口變量時的語法。同時我們也可以取得存儲在具體錯類型的的值,并在每個分支語句中使用這些值。
第 18 行和第 20 行的分支語句檢測具體的錯誤類型,然后執行相應的錯誤處理邏輯。這是識別存儲在 error 接口的具體錯誤類型的典型方式。
結論
返回的 error 接口值應該包含對調用者有影響的,錯誤發生時作用域內一些具體信息。它必須包含足夠的信息以便讓調用者做出合理的選擇,通常來說一個簡單的字符串信息就夠了,不過有時需要的會更多。
我們在 net 包中看到了一個使用實例:它聲明了一個自定義錯誤類型,用來封裝原始的 errro 類型和一些相關的上下文信息。在 JSON 包中,我們看到了如何用自定義錯誤類型在提供上下文信息和相關的狀態。在這兩個例子中,維護錯誤發生時的相關上下文信息是一個決定性因素
如果 errors 包中中 error 類型可以提供足夠的上下文信息,就用它。整個標準庫中到處用到了它, 通常這個就是你需要的。如果需要給調用者提供額外的信息來幫助他們做出更別合理的錯誤物理選擇,從標準庫代碼中找一些線索,然后創建你自己的自定義錯誤類型。
via: https://www.ardanlabs.com/blog/2014/11/error-handling-in-go-part-ii.html
作者:William Kennedy 譯者:jettyhan 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
者 | 沉默王二
責編 | Carol
頭圖 | CSDN下載自視覺中國
先說一句哈,自從在 B 站開始刷視頻后,我就覺得要學的內容實在是太多了。這篇“服務器軟件大掃盲”就是我看了羊哥的一期視頻后有感而發的,比如說 Web 服務器、HTTP 服務器、應用服務器這三個概念,我是見過很多次,但如果你非要我說出它們之間的區別的話,我只好啞口無言。
還有,我自己用過的 Tomcat、Nginx、Apache、Jetty、Undertow,它們之間有什么優缺點,嗯......繼續啞口無言。可能有很多小伙伴和我一樣,用過,但具體的差別還真的說不上來,所以我打算借這個機會來和大家一起學習下。
(我就是課代表,我驕傲)
先來說 Web 服務器,它一般指的是網站服務器,可以向瀏覽器(PC端或者移動端)等 Web 客戶端提供服務,供請求數據或者下載數據。服務器使用 HTTP (超文本傳輸協議)和客戶端瀏覽器進行通信,因此我們也把 Web 服務器稱作為 HTTP 服務器。
再來說應用服務器,它是一種軟件框架,提供一個應用程序運行的環境。通常用于為應用程序提供安全、數據、事務支持、負載平衡大型分布式系統管理等服務。
在我看來,Web 服務器和應用服務器之間的界限已經非常模糊,后者更高級一點,就好像公司與企業這兩個名詞之間的差別。
常見的 Web 服務器軟件包括 Nginx、Apache、IIS,常見的應用服務器軟件包括 WebLogic、JBoss,前者更輕量級,后者更重量級。
接下來,我們就來嘮嘮常見的一些服務器軟件。
就我的程序生涯來看,Tomcat 用的算是最多了,沒有之一。如果 Tomcat 安裝成功的話,可以在本地的瀏覽器中訪問 http://127.0.0.1:8080 來展示它的默認首頁,見下圖。
Tomcat 是由 Apache 軟件基金會屬下 Jakarta 項目開發的 Servlet 容器,實現了對 Servlet 和 JavaServer Page(JSP)的支持,并提供了作為 Web 服務器的一些特有功能。
JSP 是由 Sun Microsystems 公司主導建立的一種動態網頁技術標準。JSP 可以響應客戶端發送的請求,并根據請求內容動態地生成 HTML、XML 或其他格式文檔的 Web 網頁,然后返回給請求者。
JSP 以 Java 語言作為腳本語言,為用戶的 HTTP 請求提供服務,并能與服務器上的其它 Java 程序共同處理復雜的業務需求。我是一名三線城市的 Java 程序員,免不了要開發一些小型網站,這也就是為什么我用 Tomcat 最多的原因。
Nginx 是一款輕量級的 Web 服務器、也支持反向代理,由于它的內存占用少,啟動極快,高并發能力強,所以在互聯網項目中廣泛應用。
關于 Nginx,比較令人遺憾的一件事是,它的作者伊戈爾·賽索耶夫進了監獄。
Nginx 在官方測試的結果中,能夠支持五萬個并行連接,國內比較有名的公司,比如說百度、京東、新浪、網易、騰訊、淘寶等都在使用。
不知道你有沒有聽過虛擬主機的概念,就是在 Web 服務里有一個獨立的網站站點,這個站點對應獨立的域名(也可能是IP 或端口),具有獨立的程序及資源,可以獨立地對外提供服務供用戶訪問。
虛擬主機有三種類型:基于域名的虛擬主機、基于端口的虛擬主機、基于 IP 的虛擬主機。
Nginx 可以使用一個 server{}
標簽來標識一個虛擬主機,一個 Web 服務里可以有多個虛擬主機標簽對,即可以同時支持多個虛擬主機站點。這一點,非常的實用。
最開始的時候,我以為 Apache 就是 Tomcat,傻傻分不清楚。后來知道它們完全不同,logo 就不同(說什么大實話)。
Apache 一般是指 Apache HTTP Server,是 Apache 軟件基金會(和 Tomcat 同屬一家基金會,因此容易混淆)下的一個網頁服務器軟件。由于其跨平臺和安全性,被廣泛使用,是最流行的 Web 服務器軟件之一。它快速、可靠并且可通過簡單的 API 擴展。
我是在服務器上安裝 WordPress 的時候用到了 Apache,當時并不知道有 LAMP 的存在,所以安裝的過程中吃了很多苦,關鍵是最后沒有安裝成功,大寫的尷尬。
最后還是在青銅群里的一個群友的遠程幫助下才完成安裝的,他是搞 PHP 的。LAMP 就是他告訴我的,安裝起來非常的傻瓜式,非常適合我這種對命令行有抗拒心理的程序員。
LAMP 是指一組運行動態網站或者服務器的自由軟件名稱首字母縮寫:
Linux,操作系統(一般服務器軟件都安裝在 Linux 上,性能極佳)
Apache,網頁服務器(就是 Apache HTTP Server)
MariaDB 或 MySQL,數據庫管理系統
PHP、Perl 或 Python,腳本語言
這些軟件配合起來使用的時候,極具活力,它的變體還有很多,另外一個比較有名的就是 LNMP,用 Nginx 代替 Apache。
Jetty 和 Tomcat 有很多相似之處,比如說可以為 JSP 和 Servlet 提供運行時環境。Jetty 是 Java 語言編寫的,它的 API 以一組 JAR 包的形式發布。
與 Tomcat 相比,Jetty 可以同時處理大量鏈接并且長時間的保持這些鏈接,例如,一些 Web 聊天應用非常適合用 Jetty 服務器,比如說淘寶的 Web 版旺旺。
Jetty 的架構比較簡單,它有一個基本數據模型,這個數據模型就是 Handler,所有可以被擴展的組件都可以作為一個 Handler,添加到 Server 中,Jetty 就是幫我們管理這些 Handler 的。
Undertow 是一個用 Java 編寫的、靈活的、高性能的 Web 服務器,提供基于 NIO 的阻塞和非阻塞 API。
Undertow 可以嵌入到應用程序中或獨立運行,只需幾行代碼,非常容易上手。下面這段代碼是官網提供的一個使用 Async IO 的簡單 Hello World 服務器示例:
public class HelloWorldServer {
public static void main(final String[] args) {
Undertow server=Undertow.builder
.addHttpListener(8080, "localhost")
.setHandler(new HttpHandler {
@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender.send("Hello World");
}
}).build;
server.start;
}
}
直接運行后,在瀏覽器中地址欄中輸入 http://localhost:8080
就可以訪問到了。是不是感覺非常輕巧?
如果有小伙伴使用過 JFinal 開發過小型網站的話,對 Undertow 應該不會陌生,因為 JFinal 的默認容器已經切換到了 Undertow。
JFinal 是基于 Java 語言的極速 WEB + ORM 框架,其核心設計目標是開發迅速、代碼量少、學習簡單、功能強大、輕量級、易擴展、Restful。
至于其他的一些企業級服務器軟件,我個人沒有用過,就不細說了。
JBoss,紅帽子收購過,后更名為 WildFly。
WebLogic,甲骨文出品。
WebSphere,IBM 公司出品。
相信小伙伴們看了出品方,就知道這些服務器軟件足夠的重量級,都是大佬,都是大佬。
聲明:本文為作者投稿,版權歸其個人所有。
?Flash 已死,Deno 當立?
?OceanBase 十年:一群追夢人的成長史
?2 年 6 個月 11 天,外包到阿里的修仙之路!| 原力計劃
?服務器軟件大掃盲!
?絕悟之后再超神,騰訊30篇論文入選AI頂會ACL
?中本聰并沒有出現,那真相是?
*請認真填寫需求信息,我們會在24小時內與您取得聯系。