CGI、JSP與Servlet、SpringMVC之間的區別與聯繫

CGI

概述:

https://baike.baidu.com/item/CGI/607810?fr=aladdin

https://zhuanlan.zhihu.com/p/25013398

CGI(Common Gateway Interface)通用網關接口,是外部擴展應用程序 Web 服務器交互的一個標準接口。服務器端與客戶端進行交互的常見方式多,CGI 技術就是其中之一。

根據CGI標準,編寫外部擴展應用程序,可以(1)對客戶端瀏覽器輸入的數據進行處理(2)完成客戶端與服務器的交互操作

CGI規範定義了Web服務器如何向擴展應用程序發送消息,在收到擴展應用程序的信息後又如何進行處理等內容。(請求響應的過程)

對於許多靜態的HTML網頁無法實現的功能,通過 CGI可以實現,比如表單的處理、對數據庫的訪問、搜索引擎、基於Web的數據庫訪問等等。(實現動態網頁)

CGI執行以下主要任務:

(1)Web 客戶端的瀏覽器將URL的第一部分解碼與Web服務器相連。

(2)Web 瀏覽器將URL的其餘部分提供給服務器。

(3)Web 服務器將URL轉換成路徑和文件名。

(4)Web 服務器發送 HTML 和別的組成請求頁面的文件給客戶。一旦頁面內容傳送完,這個連接自動斷開。

(5)在客戶端,HTML腳本提示用戶做動作或輸入。當用戶響應後,客戶請求Web服務器建立一個新的連接。

(6)Web 服務器把這些信息和別的進程變量傳送給由HTML以URL的形式指定CGI程序。

(7)CGI 根據輸入作出響應,把響應結果傳送給 Web 服務器。

(8)Web 服務器把響應的數據傳給客戶,完成後關閉連接。

腳本(script)並不一定就是腳本語言編寫的。腳本描述的是一類程序的特徵:爲了完成某一任務,用程序實現批量執行一組常用邏輯的組合。凡是符合這一特徵的程序都可稱作腳本。當然,時至今日,腳本語言所編寫的程序都可以稱之爲腳本程序,並且其內部邏輯也早已變得並不簡單。

網關:更形象的叫法是“協議翻譯機”。通常與網關輸入輸出兩端通信使用的是不同的協議。即一方是HTTP協議,另一方可能是其他協議,比如企業內部的自定義協議。CGI程序既是如此。

Interface:API(應用程序接口)的I是它,被譯作“接口”。UI(用戶界面)的I也是它,被譯作“界面”。實際他們是同樣的意思。

接口,確切而言是“接口協議”,所謂協議,既是通信雙方或多方都共識並遵守的一套規則。例如:

  • TCP/IP這類二進制協議,協議內容的描述是某某字節是幹嘛滴,其取值範圍是什麼,不同取值又是什麼含義。
  • HTTP協議是字符協議,這類協議內容的描述就是第一行是啥,第二行是啥……,應該出現啥單詞,表示啥意思。

 

訪問流程:

Web服務器在接收到用戶瀏覽器的HTTP請求,比如請求如下URL:

http://guodongxiaren.me/cgi-bin/helloworld.cgi

輸入:

此時在Web服務器調用helloworld.cgi之前,會把各類HTTP請求中的信息以環境變量的方式寫入OS。CGI程序本質是OS上一個普通的可執行程序,它通過語言本身庫函數來獲取環境變量,從而獲得數據輸入。

除環境變量外,另外一個CGI程序獲取數據的方式就是標準輸入(stdin)。如post請求一個CGI的URL,那麼POST的數據,CGI是通過標準輸入來獲取到的。

輸出:

CGI如何構造出數據(比如HTML頁面)返回給瀏覽器呢?其實CGI向標準輸出寫入數據即可。比如printf、cout、System.out.println、print、echo等。因爲Web服務器已經做了重定向,將標準輸出重定向給Web服務器的與瀏覽器連接的socket(套接字,具體IP)。

CGI不僅要輸出一段HTML代碼,還要輸出HTTP協議的響應部分,因此HTTP響應報頭也要自己標準輸出出來。

cout<<"Content-Type:text/html\n\n"<<endl;  

CGI編寫Web程序雖然看似解析組裝等操作十分繁瑣,但其實都有很多第三方的封裝來簡化這些操作,高級語言的標準庫基本都已經做了封裝,而針對C++則有一個還不錯的第三方庫Cgicc。

 

CGI的缺點:

(1)每次HTTP請求CGI,Web服務器都有啓動一個新的進程去執行這個CGI程序,即頗具Unix特色的fork-and-execute。當用戶請求量大的時候,這個fork-and-execute的操作會嚴重拖慢Web服務器的性能。

       FastCGI(簡稱FCGI)技術應運而生。簡單來說,其本質就是一個常駐內存的進程池技術,由調度器負責將傳遞過來的CGI請求發送給處理CGI的handler進程來處理。在一個請求處理完成之後,該處理進程不銷燬,繼續等待下一個請求的到來。

       資源池是後臺性能優化中的常見套路。Java發明的Servlet技術也是一種常駐內存的網關通信技術,只不過它採用的是多線程而非進程。

(2)缺乏URL路由的功能,基本上一個CGI都是獨立提供給外界訪問,一個CGI就是獨立的可執行程序。不僅CGI的URL比較醜陋,而且容易暴露真實路徑。

        CGI一般只做上層目錄的路由,而這隻能交給Web服務器去配置。比如:http://app/hello.cgi 的app目錄在物理OS的什麼位置可通過Apache去配置。雖然理論上講CGI程序也可以實現http://app/hello.cgi/abc/def 這種形式的路由。但是基本上沒人這樣做。

 

CGI的未來發展:

CGI可以直接吐出一個html網頁,也可以進行各種計算、邏輯處理任務。但隨着各類web前後端技術的發展,以及大數據、高併發的Server使用場景越來越多。現代的CGI的用法,在發生變化。越來越多的任務從後端轉移到前端,前端頁面利用強大的JS承擔起更多的責任

CGI一般不再用於直接返回html頁面,同時將複雜的計算、IO任務下沉到後端(後端可以進一步進行路由轉發,實現負載均衡)。使CGI作爲前後端之間的中間層。CGI的職能是完成基本的鑑權以及數據交換。

Restful風格API的出現,讓CGI獲得了續命。CGI解析前端請求,再轉發給對應後端;然後從後端取回數據,給前端返回XML或JSON。然後前端JS利用XML/JSON中的數據來進行填充。可以繪製出豐富的界面或用作他用。JS可以使用Ajax技術來向後臺CGI發起數據請求。Ajax完成的是不需要刷新整個頁面就可以加載後端數據(比如從數據庫中取出)。

除了FCGI外,還有SCGI(Simple CGI),也是作爲CGI的替代協議而產生的,但他與FCGI更像,SCGI在每次完成HTTP應答之後都立即關閉HTTP連接。這個簡單的協議更符合Restful API的理念需要。

 

Servlet

https://blog.csdn.net/qq_19782019/article/details/80292110

https://www.cnblogs.com/xdp-gacl/p/3760336.html

https://www.jianshu.com/p/406a09136a18

Java Servlet 是運行在 Web 服務器應用服務器上的程序,它是作爲來自 【Web 瀏覽器或其他 HTTP 客戶端的請求】和 【HTTP 服務器上的數據庫或應用程序】之間的中間層

  Servlet運行於支持Java的應用服務器中。從實現上講,Servlet可以響應任何類型的請求,但絕大多數情況下Servlet只用來擴展基於HTTP協議Web服務器

使用 Servlet,可以收集來自網頁表單的用戶輸入,呈現來自數據庫或者其他源的記錄,還可以動態創建網頁。

Servlet是什麼?

  • 一個Java類,運行在Servlet容器中(Tomcat)
  • 負責接收請求
  • 調用Service處理數據
  • 負責響應數據

Servlet程序是由WEB服務器調用,web服務器收到客戶端的Servlet訪問請求後:

  • ①Web服務器首先檢查是否已經裝載並創建了該Servlet的實例對象。如果是,則直接執行第④步,否則,執行第②步。
  • ②裝載並創建該Servlet的一個實例對象。
  • ③調用Servlet實例對象的init()方法。
  • ④創建一個用於封裝HTTP請求消息的HttpServletRequest對象一個代表HTTP響應消息的HttpServletResponse對象,然後調用Servlet的service()方法並將請求和響應對象作爲參數傳遞進去。
  • ⑤WEB應用程序被停止或重新啓動之前,Servlet引擎將卸載Servlet,並在卸載之前調用Servlet的destroy()方法。

WEB容器接收到以.jsp爲擴展名的URL的訪問請求時,它將把該請求交給JSP引擎去處理。Tomcat中的JSP引擎就是一個Servlet程序,它負責解釋和執行JSP頁面。
每個JSP 頁面在第一次被訪問時,JSP引擎將它翻譯成一個Servlet源程序,接着再把這個Servlet源程序編譯成Servlet的class類文件,然後再由WEB容器像調用普通Servlet程序一樣的方式來裝載和解釋執行這個由JSP頁面翻譯成的Servlet程序。

Java Servlet 通常情況下與使用 CGI(Common Gateway Interface,公共網關接口)實現的程序可以達到異曲同工的效果。

相比於 CGI,Servlet 有以下幾點優勢:

  • 性能明顯更好。
  • Servlet 在 Web 服務器的地址空間內執行。這樣它就沒有必要再創建一個單獨的進程來處理每個客戶端請求。
  • Servlet 是獨立於平臺的,因爲它們是用 Java 編寫的。
  • 服務器上的 Java 安全管理器執行了一系列限制,以保護服務器計算機上的資源。因此,Servlet 是可信的。
  • Java 類庫的全部功能對 Servlet 來說都是可用的。它可以通過 sockets 和 RMI 機制與 applets、數據庫或其他軟件進行交互。

Servlet 執行以下主要任務:

  • 讀取客戶端(瀏覽器)發送的顯式的數據。這包括網頁上的 HTML 表單,或者也可以是來自 applet 或自定義的 HTTP 客戶端程序的表單
  • 讀取客戶端(瀏覽器)發送的隱式的 HTTP 請求數據。這包括 cookies、媒體類型和瀏覽器能理解的壓縮格式等等。
  • 處理數據並生成結果。這個過程可能需要訪問數據庫執行 RMI CORBA 調用,調用 Web 服務,或者直接計算得出對應的響應
  • 發送顯式的數據(即文檔)到客戶端(瀏覽器)。該文檔的格式可以是多種多樣的,包括文本文件(HTML 或 XML)二進制文件(GIF 圖像)、Excel 等。
  • 發送隱式的 HTTP 響應到客戶端(瀏覽器)。這包括告訴瀏覽器或其他客戶端被返回的文檔類型(例如 HTML)設置 cookies 緩存參數,以及其他類似的任務。

 

SpringMVC

Spring MVC (SpringBoot)其實就是基於tomcat等這些web容器對我們的CS請求能做更多的事情,如校驗,攔截(AOP思想),後期渲染等等,好讓我們專注於業務的開發。
Springmvc的核心是一個DispatcherServlet,負責請求的解析,攔截,轉發,響應等等。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章