web開發學習筆記:web容器、JSP簡述和編寫設置第一個Servlet

本篇文章是對自己學習的一個總結,主要學習資料是JSP&Servlet學習筆記(第三版),林信良著,清華大學出版社出版。


Web容器

  • 容器簡述

對於Java程序而言,JVM是操作系統。.java文件會被編譯成.class文件,.class文件對於JVM而言,就是可執行文件。Java程序基本上只認得一種操作系統,就是JVM。

一開始編寫Servlet/JSP程序時就要認識到容器的概念。List,Set這類Collection也是一種容器,用來持有保存對象的集合對象。對於Servlet/JSP來說,容器的概念更廣,它不僅持有對象,還負責對象的生命週期和相關服務的連接。

具體來說,容器就是一個寫在JVM上的程序,不同類型的容器負責不同的工作。在編寫Servlet時,會接觸到HttpServletRequest和HttpServletResponse等對象,這些對象就是Java對象。想想看,HTTP這樣的文本通信協議,其攜帶的信息是String類型的。這些信息是不會自己變成各種Java對象,其中的這些剖析和轉換是容器幫我們完成的。

抽象來說,web容器可以看成是運行Servlet/JSP的HTTP服務器。沒有Web容器的話,我們就是用HTTP服務器來交互信息。但HTTP服務器傳來的只是String類型的信息,我們想要使用Java語言來開發網頁,還要自己用JavaSE處理原始的HTTP數據的話,那也太麻煩了。Java爲了方便,就制定了web容器規範,也就是接口。各大廠商負責實現這些接口,而我們不需要知道怎麼實現的,由哪些廠商實現的,我們只需要調用接口就能得到我們想要的東西來進行網頁開發。

所以啊,web容器本質上就是加了一層處理的HTTP服務器。

從請求到Servlet的處理過程如下(省略網絡物理層和數據鏈路層的協議)

  1. 瀏覽器對服務器發送請求,服務器收到請求,使用HTTP協議將請求內容發送給容器。
  2. web容器會接卸HTTP請求內容,創建各種對象(比如HttpServletRequest、HttpServletResponse、HttpSession等)。
  3. 一個web容器內有多個Servlet,web容器根據請求的URI決定使用哪個Servlet來處理請求(開發人員定義Servet和URI的映射關係)。
  4. Servlet根據請求對象(HttpServletRequest)的信息來決定做什麼,然後通過創建(HttpServletResponse)來響應。
  5. 服務器再根據HttpServletResponse轉換成HTTP響應傳回給瀏覽器。

以上就是一個請求的簡要流程,我們能看出,真正負責處理請求和創建響應信息的是Servlet

最後再整理一下。web容器是JVM上的一個程序,當請求到來時,web容器會爲每個請求分配一個線程來處理每個線程就是一個Servlet。

 

  • Web容器具體做了什麼

我們已經知道Web容器會將String的HTTP信息轉換成Java對象,下面就講講到底是如何轉換的。

瀏覽器發出請求來到HTTP服務器,HTTP服務器會將請求交給容器來處理。容器會創建一個代表着這次請求的HttpServletRequest對象,並將請求的相關信息存儲在這個對象中,比如請求的來源地址,請求用的瀏覽器是什麼瀏覽器,瀏覽器是版本等等。

同時,容器還會創建一個HttpServletResponse對象,裏面存放着對本次請求的響應信息,稍後是要對瀏覽器進行響應的。因爲HTTP是無狀態的協議,所以每次請求都會創建新的HttpServletRequest和HttpServletResponse對象,請求完成後都會銷燬他們。當然,這些都是由Web容器幫我們完成的,我們可以不用關心。

如果我們在Java文檔中查詢HttpServletResquest和HttpServletResponse兩個對象的話,會發現他們都是接口。就像我上面說的,Java只制訂規範,實現交給廠商。想要知道HttpServletResponse的具體實現,我們現在使用Tomcat的話,就應該去看Tomcat的文檔。

關於HttpServletRequest的具體用法可以看這篇文章,

關於HttpServletResponse的具體用法可以看這文章

 


Servlet和JSP

上面一直在討論Servlet,沒說涉及到JSP。實際上,Servlet和JSP是一體兩面的,JSP最終還是會被web容器轉換成Servlet的.java源文件,再編譯成.class文件,然後再加載容器。所以JSP最終還是以Servlet的形式在運轉。所以上面一直在說Servlet,因爲要了解JSP,就必須對Servlet有一定的瞭解。

Servlet和JSP本質上是用一種東西,JSP能寫出來的東西,使用Servlet也能達到同樣的效果,那爲什麼還弄一個JSP呢?那是因爲JSP的寫法在比較適合寫頁面。相信使用過Servlet寫頁面和JSP寫頁面的之後,這點就會有很深的體會

但是現在處於商業性考慮和前端技術的興起,JSP已經不是寫頁面的主要選擇。儘管如此,現在還是有很多應用程序是基於JSP編寫的,有JSP的基礎的話,使用其他的頁面技術就會變得容易上手。

 

 

 

 

 


使用Idea創建第一個Servlet

這次使用的web容器是Tomcat 8。操作系統是mac os。

在tomcat的官網https://tomcat.apache.org/download-80.cgi下載core下的tar.gz,然後將壓縮文件解壓後放在/Library目錄之下。

打開idea,file->new->project,然後選擇左側欄的maven,然後從maven中選擇maven-arthetype-webapp

之後再新的新的選擇框中填上下圖的信息,然後一直選擇next直到finish

然後再下圖的位置選擇add configuration對項目配置

點擊新彈出的頁面的左上角的加號,選擇tamcat server -> local。

之後選擇配置Application server,之後配置tomcat home。找到剛纔安裝的tomcat位置,選擇tomcat即可

之後在deployment下點擊左下角的加號,選擇Aritifact,選擇冒號後爲war exploded的。

點擊完成。

然後在主頁面選擇file -> project structure,在module模塊選擇模塊的java版本,選擇java8,如下圖所示

接下來就可以開始寫一個簡單的Servlet。

項目建立以後,項目的目錄結構如左圖所示在此基礎上我們的java代碼一般是寫在main下的java包下,所以我們就新建一個java包,然後右鍵點擊java包,mark directory as -> source root。最後結果如右圖所示

              

在java包下建立如下的包,然後點擊demo右鍵,new -> create new servlet,name設爲Hello,Hello就是我們的Servlet,實際效果如下所示

 

 

 


關於HttpServlet架構的簡單介紹

大部分的Servlet就像上面的Hello結構一樣。繼承了HttpServlet後,需要實現doPost和doGet兩個方法。網頁使用Get方式請求這個Servlet就調用doGet方法,使用Post方式請求即調用doPost方法。想要知道爲什麼會得到這樣的效果,就要從HttpServlet的架構說起。下圖是相關API的架構圖(圖片了來自於JSP&Servlet學習筆記)

首先是Servlet接口。這個接口定義了Servlet的基本行爲,看看它的方法,與生命週期相關的init(),destroy();提供服務時要調用的service()方法等。

GenericServlet先不介紹。然後我們看HttpServlet,那些doGet,doPost方法分別對應着請求方式是Get,Post,Head時的處理方式。當請求來到這個Servlet,Servlet是調用service方法,service方法的大致流程如下。

//獲得本次請求的請求方式
String method = req.getMethod
if(method.equals(METHOD_GET)){
    //略
    doGet();
    //略
}
if(method.equals(METHOD_POST)){
    //略
    doPost();
    //略
}
···

所以,判斷瀏覽器的請求方式是在service()這個方法裏進行判斷,這也基本上就是service()做的所有事情。我們要想根據不同的請求方式定義不同的邏輯,只需要複寫對應的doXXX()方法即可,不要輕易複寫service()方法,會打亂原有邏輯。

 

 


Servlet和請求地址的映射方式

  • 使用@WebServlet

一個web容器裏有多個servlet,不同的servlet有不同的功能。瀏覽器輸入地址就是一次請求,就要有一個servlet來處理這個請求。那如何確定這個請求是由哪個servlet處理就是servlet如何與地址進行映射。

假如瀏覽器輸入的地址是localhost:8080/servletlearning_war_exploded/Hello,

localhost:8080是主機名和端口號,servletlearning_war_exploded是上下文,可以在idea中的Edit Configurations中設置

在deployment中設置Application Context即可

然後剩下/Hello。我們就是靠最後的這個/Hello來確定哪個Servlet處理這個請求。

在上面的Hello類中,有一個註解@WebServlet。改變該註解的name值,就可以改變地址的映射關係。

或者省略name,寫成@WebServlet("/Hello)也有同樣的效果,注意要加上斜槓,並且區分大小寫。

 

@WebServlet有很多的設置方式,這些方式有很強大的效果。

  1. 以" / "開頭,以" /* "結尾的URI。比如@WebServlet("/guest/*")。請求除去環境路徑的部分,所有以"/guest"開頭的地址都交給該Servlet處理。比如/guest/text.view和/guest/test/t/a.view。
  2. 以" *. " + 類型名的URI,比如@WebServlet("*.view"),這代表所有的以.view結尾的請求,都交給該Servlet處理。
  3. 空字符串,比如@WebServlet(""),這就相當於根目錄

以上的設置方式衝突是,以最具體的,範圍最小的那個爲準。

  • 使用web.xml

Servlet 3.0之後纔可以使用註解來映射Servlet,在此之前都是使用web.xml文件來寫映射。新建項目後,系統會爲我們自動見一個web.xml文件,文件在這裏

我們可以將裏面的內容寫成下面的樣子,能達到使用註解的效果

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>Hello</servlet-name>
        <servlet-class>servletlearning.demo.Hello</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/Hello</url-pattern>
    </servlet-mapping>
</web-app>

servlet的類和地址通過servlet-name確定映射關係。

web.xml的優先級是高於註解的,當web.xml和註解的映射有衝突時,以web.xml的爲準。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

​​​​​​​

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