天天看點

圖解 & 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

“眨眼間,離上一篇寫技術博文時隔1個月。怕自己真的生疏了,都是備案太慢惹得。哈哈,繼續high~ ”

圖解 & 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

http伺服器是web伺服器的一種,也是開發最常見的,自然還有其他方式進行資訊互動,比如ftp檔案伺服器…

web伺服器是可以向送出請求的浏覽器提供文檔的程式。其核心過程為 連接配接過程 — 請求過程 — 應答過程 — 關閉連接配接

這讓我想到了tomcat架構的一張圖:

圖解 & 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

如圖,tomcat 包含了核心服務子產品:connector連接配接子產品 和 container 容器。tomcat server 核心是一個 servlet/jsp container。對每一個http請求,過程如下

— 擷取連接配接 — servlet來分析請求(httpservletrequest) — 調用其service方法,進行業務處理 — 産生相應的響應(httpservletresponse) — 關閉連接配接

如圖:

圖解 & 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

藍色線指向過程是請求,綠色線指向過程是響應過程。也就是上面web伺服器核心過程:“連接配接過程 — 請求過程 — 應答過程 — 關閉連接配接”

什麼是servlet?(每次都會不停的問自己,這是什麼“what”?緊接着應該是什麼用“how”吧)

“servlet 是運作在web伺服器的java小程式。servlet可以擷取并針對web用戶端的請求作出響應。一般情況下,通過http,即超文本傳輸協定,進行傳輸通信。” <a href="http://www.bysocket.com/?p=518#">?</a> 1 <code>a servlet is a small java program that runs within a web server. servlets receive and respond to requests from web clients, usually across http, the hypertext transfer protocol.</code>

是以,servlet 是web伺服器核心工作的抽象。它不單單隻是實作httpservlet,可能實作有ftpservlet(這個我猜的)等。相對較多的web開發,知道的肯定是httpservlet。

補充,在servlet規範是這樣寫道的:

serlvet是基于java技術的web元件,容器托管的,用于生産動态内容。它也是基于平台無關的java類格式,被編譯為平台無關的位元組碼,可以被基于java技術的web server動态加載并運作。這裡容器,有時候也稱為servlet 引擎。
“httpservlet 提供了一個能被繼承後建立一個适應web網站的http servlet的抽象類。” <code>provides an abstract class to be subclassed to create an http servlet suitable for a web site.</code>

光說不練假把式,練一個“hello,servlet/jsp world!”:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

<code>import</code> <code>java.io.ioexception;</code>

<code>import</code> <code>java.io.printwriter;</code>

<code>import</code> <code>javax.servlet.servletexception;</code>

<code>import</code> <code>javax.servlet.annotation.webservlet;</code>

<code>import</code> <code>javax.servlet.http.httpservlet;</code>

<code>import</code> <code>javax.servlet.http.httpservletrequest;</code>

<code>import</code> <code>javax.servlet.http.httpservletresponse;</code>

<code>/*</code>

<code> </code><code>* copyright [2015] [jeff lee]</code>

<code> </code><code>*</code>

<code> </code><code>* licensed under the apache license, version 2.0 (the "license");</code>

<code> </code><code>* you may not use this file except in compliance with the license.</code>

<code> </code><code>* you may obtain a copy of the license at</code>

<code> </code><code>* unless required by applicable law or agreed to in writing, software</code>

<code> </code><code>* distributed under the license is distributed on an "as is" basis,</code>

<code> </code><code>* without warranties or conditions of any kind, either express or implied.</code>

<code> </code><code>* see the license for the specific language governing permissions and</code>

<code> </code><code>* limitations under the license.</code>

<code> </code><code>*/</code>

<code>/**</code>

<code> </code><code>* @author jeff lee</code>

<code> </code><code>* @since 2015-6-25 19:46:45</code>

<code> </code><code>*  hellowrold案例</code>

<code>@webservlet</code><code>(urlpatterns =</code><code>"/helloworld.html"</code><code>)</code>

<code>public</code> <code>class</code> <code>helloworldservlett</code><code>extends</code> <code>httpservlet{</code>

<code>    </code> 

<code>    </code><code>private</code> <code>static</code> <code>final</code> <code>long</code> <code>serialversionuid = 1l;</code>

<code>    </code><code>@override</code>

<code>    </code><code>protected</code> <code>void</code> <code>doget(httpservletrequest req, httpservletresponse resp)</code>

<code>            </code><code>throws</code> <code>servletexception, ioexception{</code>

<code>        </code><code>// 擷取輸出列印對象</code>

<code>        </code><code>printwriter out = resp.getwriter();</code>

<code>        </code><code>out.println(</code><code>"hello,servlet/jsp world!"</code><code>);</code>

<code>    </code><code>}</code>

<code>}</code>

右鍵該helloworldservlett.java檔案 — run as — run on server — 選擇tomcat伺服器 — finish即可

圖解 &amp; 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結
圖解 &amp; 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

等待片刻,你可看到網頁上如下輸出。這就是用戶端從httpservlet擷取到的響應:

圖解 &amp; 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結
休息一下吧~ 看看小廣告:

<code>@webservlet(urlpatterns = "/helloworld.html")</code>

@webservlet 注解用于聲明一個httpservlet的配置。其中,urlpatters = “/helloworld.html”,urlpatterns複數形式,說明至少一個url必須被申明。它和另一個value必須存在一個,但不能同時存在。如果要比對多個url路徑的話,如下:

<code>@webservlet(urlpatterns = { "/helloworld01.html", "/helloworld02.html" }</code>

下面有個@override,重寫了父類httpservlet的doget方法。我們先看看父類httpservlet。httpservlet是一個抽象類,它提供了以下方法:

— doget  , 服務于 htpp get 請求 — dopost , 服務于 http post 請求 — doput  , 服務于 http put 請求 — dodelete,服務于 http delete 請求 …
圖解 &amp; 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

對于不同的請求,httpservlet的子類必須相應的實作至少一個方法,通常來說,會是其中一個,這樣代碼比較清晰。那父類的doget方法做了什麼工作呢?

<code>protected void doget(httpservletrequest req, httpservletresponse resp)</code>

<code>        </code><code>throws servletexception, ioexception</code>

<code>    </code><code>{</code>

<code>        </code><code>string protocol = req.getprotocol();</code>

<code>        </code><code>string msg = lstrings.getstring("http.method_get_not_supported");</code>

<code>        </code><code>if (protocol.endswith("1.1")) {</code>

<code>            </code><code>resp.senderror(httpservletresponse.sc_method_not_allowed, msg);</code>

<code>        </code><code>} else {</code>

<code>            </code><code>resp.senderror(httpservletresponse.sc_bad_request, msg);</code>

<code>        </code><code>}</code>

這裡就簡單的擷取了下http協定及http local資訊,然後可以協定是否是1.1,做出分别是405或者400http狀态碼的響應。

回到helloworldservlett.java 這裡:

<code>@override</code>

<code>        </code><code>throws servletexception, ioexception {</code>

<code>    </code><code>// 擷取輸出列印對象</code>

<code>    </code><code>printwriter out = resp.getwriter();</code>

<code>    </code><code>out.println("hello,servlet/jsp world!");</code>

表示該helloworldservlett會接受http get請求,并oom到httpservletrequest,并執行裡面的邏輯代碼和傳回響應。 這裡從httpservletresponse對象中擷取到輸出列印對象printwriter,然後輸出了“hello,servlet/jsp world!”。

完畢!哦還有一點補充補充補充:

print,這裡還好一句話。如果列印個table會很麻煩,是以有一個jsp的東西出現了,是servlet的html化身。

又回到這個簡單的 get servlet代碼:

<code>public class helloworldservlett extends httpservlet{</code>

<code>    </code><code>private static final long serialversionuid = 1l;</code>

<code>    </code><code>protected void doget(httpservletrequest req, httpservletresponse resp)</code>

<code>            </code><code>throws servletexception, ioexception{</code>

<code>        </code><code>out.println("hello,servlet/jsp world!");</code>

這過程總結如下:

— 從浏覽器(client)擷取連接配接”/helloworld.html” — tomcat connector子產品将請求(request)傳遞給 container子產品 — container 子產品會做以下事情 —— 分析htpp請求資訊,組裝成httpservletrequest對象 —— 建立新的httpservletresponse對象 —— 根據路由配置,搜尋相應的servlet,并建立一個線程用于處理本次請求。此時線程會将上面request和response對象的索引,傳遞給servlet — 新線程中的servlet處理邏輯 — 線程結束後,通過httpservletresponse對象的printwriter,傳回浏覽器一個資訊

過程圖如下:

圖解 &amp; 深入淺出 JavaWeb:Servlet必會必知一、Web伺服器二、Tomcat 簡單說幾句三、我第一個Servlet三、分析源碼五、深入Servlet 具體過程六、小結

藍色線指向過程是請求,綠色線指向過程是響應過程,橙色線指向過程是内部處理過程。

有些面試題會這樣問:

servlet是線程安全的嗎? 不是,一個servlet實作類隻會有一個執行個體對象,多個線程是可能會通路同一個servlet執行個體對象的,線程安全問題都是由全局變量及靜态變量引起的。

是以,servlet對象執行個體化是在以第一次請求此servlet時,如果通路後,執行個體對象存在記憶體中,隻會在伺服器停止時,它才會消失。它不會随着各個線程結束而結束。是以下次通路servlet時,servlet container會搜尋相應的servlet,如果不存在,container建立相應的servlet。這也是我們想要的結果。

再來個惡心的面試題:

servlet是單例嗎? 不一定是,在一個serveltname情況下是的。在多個servletname比對到一個servlet類時,該servlet不是單例。

發現這一部落格寫的太多,回頭一看。可以寫成三個文章了。言歸正傳本文要點如下

1、簡單介紹web伺服器 及 tomcat容器 2、第一個sevlet的開發及使用 3、深入源碼及api介紹使用 4、總結一次請求及響應的真實過程 5、歡迎點選我的部落格及github — 部落格提供rss訂閱哦