后端應用程序的工作原理
成功運行一個簡單的后端應用程序后,接下來介紹后端應用程序的工作原理。
一個Java后端應用程序要想運行起來需要兩步,第一步是搭建Web應用服務器,為后端應用程序提供運行環(huán)境,第二步是把后端應用程序放到Web應用服務器上。
相應地,后端應用軟件的工作原理我們也分為兩部分來介紹。一部分是Web應用服務器運行后端應用程序,介紹Web應用服務器與后端應用程序的關系;另一部分是后端應用程序處理接口請求,介紹后端應用程序與接口請求端(如網(wǎng)頁、App等)的關系。在介紹這兩部分內(nèi)容之前,我們先介紹一下Java程序的運行原理。
注意:本小節(jié)默認以Tomcat作為Web應用服務器軟件,以Java作為編程語言,以Spring Boot作為基礎框架。在介紹原理時會省略很多內(nèi)部細節(jié),我們只需要大體了解即可。
◆1.Java程序運行原理
編譯型語言通過專門的編譯器,一次性地將源代碼編譯成可執(zhí)行文件(機器碼),可執(zhí)行文件可直接運行在特定的平臺上。由于可執(zhí)行文件(機器碼)是根據(jù)特定平臺編譯而成的,所以運行效率較高,但是不能跨平臺使用。比較流行的編譯型語言有C和C++等。
解析型語言不需要編譯,但是在每次運行的時候都需要解析器把源碼翻譯成機器碼,即每個運行程序的機器都需要安裝一個解析器,解析器會根據(jù)自身平臺把源碼翻譯成對應的機器碼。解析型語言具有跨平臺性,但是運行效率不高(每次運行都需要翻譯成機器碼)。比較流行的解析型語言有Python、Ruby和JavaScript等。
編譯型語言和解析型語言的對比如圖4.29所示。
圖4.29 編譯型語言與解析型語言
而Java比較特別一些,Java既是編譯型語言,又是解析型語言,因為Java既需要編譯器又需要解析器。Java具備跨平臺特性的同時,也比傳統(tǒng)的解析型語言運行效率要高。Java編寫的源碼經(jīng)過編譯器編譯之后,轉(zhuǎn)換成.class文件(字節(jié)碼,一種Java獨有的源碼與機器碼之間的格式)。這些.class文件中的字節(jié)碼在運行時需要解析器把字節(jié)碼翻譯成機器碼才能運行。Java的編譯運行過程如圖4.30所示。
注意:一般情況下,Java源碼編譯輸出的是.jar文件,而.class文件是.jar文件的主要部分。這里為了講解方便,省去了對.jar文件的描述。
圖4.30 Java編譯運行過程
Java的編譯器和解析器就是在4.1.2小節(jié)搭建Web應用服務器中提到的JDK,想要編譯或者運行Java程序都需要安裝JDK。JDK的內(nèi)部結構如圖4.31所示,它包含一些開發(fā)工具和JRE(Java Runtime Environment,運行環(huán)境),其中開發(fā)工具里有編譯器,而JRE是運行Java程序的環(huán)境。JRE包含JVM(JavaVirtual Machine,Java虛擬機)和一些基礎類庫,其中JVM包含解析器,負責翻譯字節(jié)碼等工作,而基礎庫類是Java調(diào)用操作系統(tǒng)功能的橋梁。
注意:如果只需要運行Java程序,那么可以單獨安裝JRE。JDK 9版本發(fā)布以后,不再提供單獨的JRE安裝包。由于引入了新技術,JDK 9及后續(xù)版本的內(nèi)部也沒有了JRE(可以手動生成),而JVM是仍然存在的。這是因為JRE在運行Java程序時會加載所有的基礎類庫,這樣比較損耗資源,而JDK 9及后續(xù)版本在運行程序時是按需要加載基礎類庫的。
圖4.31 JDK內(nèi)部結構
2.Web應用服務器運行后端應用程序
本小節(jié)以Tomcat作為Web應用服務器軟件進行說明。Tomcat本身是一個Java程序,啟動Tomcat服務相當于啟動一個Java程序。那么,Tomcat是怎么運行后端應用程序的?一個Java程序怎么運行另外一個Java程序呢?
首先,在Tomcat中運行的后端應用程序是.war文件而不是.jar文件。.war文件與.jar文件不同,.war文件是Web模塊,其內(nèi)部除了編譯好的.class文件、依賴包和配置文件以外,還可以包含網(wǎng)頁資源(HTML、CSS文件等)和JSP動態(tài)網(wǎng)頁等。.war文件一般需要依賴Tomcat等Web應用服務器軟件才能運行。
以4.1.3小節(jié)構造一個簡單的后端應用程序中的demo.war為例,Tomcat運行demo.war其實不是一個Java程序運行另外一個Java程序的關系,而是一個Java程序使用編譯好的.class文件的關系。更具體地說,當demo.war放到Tomcat的webapps文件夾中后,Tomcat會自動把demo.war解壓成demo目錄。解壓完成后,Tomcat會對demo進行解析并加載相關的.class文件。當接收到請求時,Tomcat會調(diào)用對應的接口函數(shù)(TestController.java文件中的方法,見代碼4.11),經(jīng)由這些代碼處理后再將結果返回。Tomcat運行后端應用程序的工作原理如圖4.32所示。
說明:Tomcat加載并引用.class文件利用了Java的反射機制。一般情況下,Java程序引用類文件只能在編寫代碼時通過import引用其他類文件,而Java反射機制是允許在運行狀態(tài)中通過給定類的名字加載指定類文件的。
Tomcat是通過圖4.21中ServletInitializer這個固定類名加載相關文件的。
圖4.32 Tomcat運行后端應用程序的工作原理
最后值得一提的是,Tomcat運行后端應用程序的工作原理其實是非常復雜的,特別是對相關文件加載的機制,本小節(jié)只對其做了最簡單的陳述,有興趣的讀者可以通過官方文檔和開源代碼進行更深入的研究。
◆3.后端應用程序處理接口請求
發(fā)送一個請求至少需要明確4個部分:請求的URL、請求方式、請求數(shù)據(jù)的格式和請求數(shù)據(jù)。以4.1.3小節(jié)構造一個簡單的后端應用程序中的接口一為例,以Postman為測試工具,發(fā)送請求的設置如圖4.33所示。
圖4.33 接口一請求的設置
注意:當請求方式為GET時,則請求數(shù)據(jù)一般只能寫在URL里,如4.1.3小節(jié)構造一個簡單的后端應用程序中的接口二。
由圖4.33中請求的URL可知,請求是基于HTTP發(fā)送的。HTTP的通信過程如圖4.34所示,其中,不是每次請求都會做一次連接的建立與斷開,存在多次請求會共用一個連接通道的情況,這與HTTP版本和相關設置有關。
注意:接口請求一般是使用HTTP或HTTPS。HTTP是TCP/IP的應用層協(xié)議,也就是說,HTTP其實只是在TCP/IP之上做了規(guī)則限定和封裝,其底層技術還是TCP/IP的相關技術。而HTTPS只是在HTTP的基礎上做了通信加密,暫且不對其進行介紹。
圖4.34 HTTP通信過程
在圖4.33所示的請求例子中,客戶端會以URL的IP地址和端口(127.0.0.1:8080)與Web應用服務器建立連接。建立連接之后,客戶端會把剩下的信息(URL剩下的部分、請求方式、請求數(shù)據(jù)的格式、請求數(shù)據(jù))按照規(guī)則放到報文里,再把報文發(fā)送到Web應用服務器上。發(fā)送的報文如代碼4.14所示。其中,報文由三部分組成,分別是請求行、報文頭信息和報文體。
·請求行:是報文的第一行,其由三部分組成,分別是請求方法、請求URL剩余的部分(除協(xié)議、IP地址、端口外)和HTTP版本。
·報文頭信息:其范圍是報文的第二行到空行。報文頭可以設置多個屬性,其作用是記錄相關的請求信息。其中,Conten-Type屬性對應的是請求數(shù)據(jù)的格式。
·報文體:其范圍是空行到最后,對應的是請求數(shù)據(jù)。需要注意的是,當請求方式為GET時,一般不使用報文體。因此4.1.3小節(jié)中的接口二的請求參數(shù)只能寫在URL中。
代碼4.14接口一的請求報文
POST /demo/test/test HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: text/plain
{
"language":"chinese",
"text":"你好,世界"
}
當Web應用服務器接收到請求的報文后,會對報文進行解析并轉(zhuǎn)換成對應的Java對象。Web應用服務器會根據(jù)報文的請求行(POST/demo/test/test)找到對應的后端應用程序并調(diào)用相應的處理函數(shù)。
其中,請求行(POST/demo/test/test)會被分成兩段(/demo和POST/test/test)處理,Web應用服務器會根據(jù)第一段(/demo)內(nèi)容找到對應的后端應用程序,demo對應的是demo.war文件名。Web應用服務器會根據(jù)第二段(POST/test/test)內(nèi)容調(diào)用后端應用程序?qū)奶幚砗瘮?shù),后端應用程序?qū)臉擞浫绱a4.15所示,其中,@RequestMapping("/test")標記了Controller的路徑,@RequestMapping(value="/test",method=RequestMethod.POST)標記了對應方法的路徑和請求方式,函數(shù)create()的參數(shù)String requestParam會被自動注入請求的數(shù)據(jù)(報文體)中。
說明:Java中以@開頭的是Java注解,也稱為Java標注,其相當于一個標簽。@Request-Mapping、@Controller是Java Servlet標準中定義的注解。
代碼4.15接口一的代碼
…
@Controller
@RequestMapping("/test")
…
@RequestMapping(value="/test",method = RequestMethod.POST)
public JSONObject create(@RequestBody String requestParam) {
…
}
…
當代碼4.15的處理函數(shù)被執(zhí)行完畢之后,會把結果返回給Web應用服務器,Web應用服務器會把返回的Java對象轉(zhuǎn)換成HTTP報文,再把報文發(fā)送給客戶端。返回的報文如代碼4.16所示。其中,報文由三部分組成,分別是狀態(tài)行、報文頭信息和報文體。
圖4.35 接口一返回的結果
·狀態(tài)行:是報文的第一行,其由三部分組成,分別是HTTP版本、狀態(tài)碼和狀態(tài)碼描述。狀態(tài)碼及其信息一般是由Web應用服務器自動填充的,如狀態(tài)碼為200,即為成功,狀態(tài)碼為404,即為無法尋找對應資源等。當然,后端應用程序也可以對其進行修改。
·報文頭信息:其范圍是報文的第二行到空行。報文頭可以設置多個屬性,作用是記錄相關的請求信息。其中,Conten-Type屬性對應的是請求數(shù)據(jù)的格式。后端應用程序也可以添加一些自定義的屬性。
·報文體:其范圍是空行到最后,對應的是后端應用程序的處理函數(shù)返回的結果。
代碼4.16接口一返回的報文
HTTP/1.1 200 OK
Date: Tue, 31 Mar 2020 10:59:51 GMT
Content-Type: application/json
{"message":"你好,世界"}
以上介紹了后端應用程序的工作原理,當然這只是一些表面的認識,還有很多內(nèi)容沒有鋪開陳述。這是因為在實際項目開發(fā)過程中,無論是HTTP請求還是Web應用服務器軟件,都是現(xiàn)成的工具,我們多是去使用它們而不是去改造它們,因此對原理的了解不需要完全透徹,具體的細節(jié)可以等問題出現(xiàn)時再去了解。
-
Web
+關注
關注
2文章
1253瀏覽量
69057 -
服務器
+關注
關注
12文章
8701瀏覽量
84549 -
JAVA
+關注
關注
19文章
2943瀏覽量
104101 -
后端
+關注
關注
0文章
31瀏覽量
2180
發(fā)布評論請先 登錄
相關推薦
評論