天天看點

servlet 接收request發送過來的多元數組_servlet詳解

一、什麼是servlet?

處理請求和發送響應的過程是由一種叫做Servlet的程式來完成的,并且Servlet是為了解決實作動态頁面而衍生的東西。了解這個的前提是了解一些http協定的東西,并且知道B/S模式(浏覽器/伺服器)。

B/S:浏覽器/伺服器。 浏覽器通過網址來通路伺服器,比如通路百度,在浏覽器中輸入http://www.baidu.com,這個時候浏覽器就會顯示百度的首頁,那麼這個具體的過程,步驟是怎樣的呢?這個就了解一下http請求和響應了

servlet 接收request發送過來的多元數組_servlet詳解

請求,響應:通過給的連結應該可以知道這兩個具體的内容

二、tomcat和servlet的關系

Tomcat 是Web應用伺服器,是一個Servlet/JSP容器. Tomcat 作為Servlet容器,負責處理客戶請求,把請求傳送給Servlet,并将Servlet的響應傳送回給客戶.而Servlet是一種運作在支援Java語言的伺服器上的元件. Servlet最常見的用途是擴充Java Web伺服器功能,提供非常安全的,可移植的,易于使用的CGI替代品.

從http協定中的請求和響應可以得知,浏覽器發出的請求是一個請求文本,而浏覽器接收到的也應該是一個響應文本。但是在上面這個圖中,并不知道是如何轉變的,隻知道浏覽器發送過來的請求也就是request,我們響應回去的就用response。忽略了其中的細節,現在就來探究一下。

servlet 接收request發送過來的多元數組_servlet詳解

①:Tomcat将http請求文本接收并解析,然後封裝成HttpServletRequest類型的request對象,所有的HTTP頭資料讀可以通過request對象調用對應的方法查詢到。

②:Tomcat同時會要響應的資訊封裝為HttpServletResponse類型的response對象,通過設定response屬性就可以控制要輸出到浏覽器的内容,然後将response交給tomcat,tomcat就會将其變成響應文本的格式發送給浏覽器

Java Servlet API 是Servlet容器(tomcat)和servlet之間的接口,它定義了serlvet的各種方法,還定義了Servlet容器傳送給Servlet的對象類,其中最重要的就是ServletRequest和ServletResponse。是以說我們在編寫servlet時,需要實作Servlet接口,按照其規範進行操作。

三、編寫Servlet

在前面,我們已經知道了servlet是什麼,為什麼需要servlet?(為了實作動态網頁,而不是顯示靜态網頁,具體情況可以百度查查),tomcat和servlet的關系?等問題。現在來手動編寫一個Servlet。

3.1、手動編寫servlet。

1、建立一個MyServlet繼承HttpServlet,重寫doGet和doPost方法,也就是看請求的方式是get還是post,然後用不同的處理方式來處理請求,

servlet 接收request發送過來的多元數組_servlet詳解

2、在web.xml中配置MyServlet,為什麼需要配置?讓浏覽器發出的請求知道到達哪個servlet,也就是讓tomcat将封裝好的request找到對應的servlet讓其使用。

配置四個東西。

servlet 接收request發送過來的多元數組_servlet詳解

配置之後,浏覽器是如何通過我們配置的資訊來找到對應的servlet的。

servlet 接收request發送過來的多元數組_servlet詳解

按照步驟,首先浏覽器通過http://localhost:8080/test01/MyServlet來找到web.xml中的url-pattern,這就是第一步,比對到了url-pattern後,就會找到第二步servlet的名字MyServlet,知道了名字,就可以通過servlet-name找到第三步,到了第三步,也就能夠知道servlet的位置了。然後到其中找到對應的處理方式進行處理。

3、實驗,驗證上面配置成功。

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

3.2、利用向導建立MyServlet

這個就相對簡單了,web.xml不用我們手動配置,工具直接幫我們自動配置了

1、右擊項目,在new選項中有直接建立servlet的選項

2、配置MyServlet類中的資訊

servlet 接收request發送過來的多元數組_servlet詳解

3、配置web.xml中的servlet資訊

servlet 接收request發送過來的多元數組_servlet詳解

4、檢視MyServle01類中的代碼和web.xml,其中的配置跟手動的配置是一樣的,隻是用圖形化界面,讓我們更友善的建立servlet而産生的。

3.3、詳解建立servlet的原理

1、servlet的生命周期是什麼?

2、為什麼建立的servlet是繼承自httpServlet,而不是直接實作Servlet接口?

3、servlet的生命周期中,可以看出,執行的是service方法,為什麼我們就隻需要寫doGet和doPost方法呢?

等這一系列的問題,我們都應該知道,而不應該就單純的知道如何配置和使用servlet?上面的問題,一一來解答。

1、servlet的生命周期是什麼?

伺服器啟動時(web.xml中配置load-on-startup=1,預設為0)或者第一次請求該servlet時,就會初始化一個Servlet對象,也就是會執行初始化方法init(ServletConfig conf)

該servlet對象去處理所有用戶端請求,在service(ServletRequest req,ServletResponse res)方法中執行

最後伺服器關閉時,才會銷毀這個servlet對象,執行destroy()方法。

servlet 接收request發送過來的多元數組_servlet詳解

2、為什麼建立的servlet是繼承自httpServlet,而不是直接實作Servlet接口?

3、servlet的生命周期中,可以看出,執行的是service方法,為什麼我們就隻需要寫doGet和doPost方法呢?

檢視源碼,httpServlet的繼承結構。

httpServlet繼承GenericServlet。懂的人立馬就應該知道,GenericServlet(通用Servlet)的作用是什麼?大概的就是将實作Servlet接口的方法,簡化編寫servlet的步驟。具體下面詳解

servlet 接收request發送過來的多元數組_servlet詳解

GenericServlet的繼承結構,實作了Servlet接口和ServletConfig接口,

servlet 接收request發送過來的多元數組_servlet詳解

Servlet接口内容

servlet 接收request發送過來的多元數組_servlet詳解

從這裡可以看到,Servlet生命周期的三個關鍵方法,init、service、destroy。還有另外兩個方法,一個getServletConfig()方法來擷取ServletConfig對象,ServletConfig對象可以擷取到Servlet的一些資訊,ServletName、ServletContext、InitParameter、InitParameterNames、通過檢視ServletConfig這個接口就可以知道

ServletConfig接口内容

servlet 接收request發送過來的多元數組_servlet詳解

其中ServletContext對象是servlet上下文對象,功能有很多,獲得了ServletContext對象,就能擷取大部分我們需要的資訊,比如擷取servlet的路徑,等方法。

到此,就知道了Servlet接口中的内容和作用,總結起來就是,三個生命周期運作的方法,擷取ServletConfig,而通過ServletConfig又可以擷取到ServletContext。而GenericServlet實作了Servlet接口後,也就說明我們可以直接繼承GenericServlet,就可以使用上面我們所介紹Servlet接口中的那幾個方法了,能拿到ServletConfig,也可以拿到ServletContext,不過那樣太麻煩,不能直接擷取ServletContext,是以GenericServlet除了實作Servlet接口外,還實作了ServletConfig接口,那樣,就可以直接擷取ServletContext了。

GenericServlet類的内容詳解

servlet 接收request發送過來的多元數組_servlet詳解

看上圖,用紅色框框起來的就是實作Servlet和ServletConfig接口所實作的方法,有9個,這很正常,但是我們可以發現,init方法有兩個,一個是帶有參數ServletConfig的,一個有無參的方法,為什麼這樣設計?這裡需要知道其中做了什麼事情,來看看這兩個方法分别做了什麼事?

init(ServletConfig config)

servlet 接收request發送過來的多元數組_servlet詳解

init()

servlet 接收request發送過來的多元數組_servlet詳解

一個成員變量config

servlet 接收request發送過來的多元數組_servlet詳解

getServletConfig(

servlet 接收request發送過來的多元數組_servlet詳解

通過這幾個方法一起來講解,首先看init(ServletConfig config)方法,因為隻有init(ServletConfig config)中帶有ServletConfig對象,為了友善能夠在其他地方也能直接使用ServletConfig對象,而不僅僅局限在init(ServletConfig config)方法中,是以建立一個私有的成員變量config,在init(ServletConfig config)方法中就将其指派給config,然後通過getServletConfig()方法就能夠擷取ServletConfig對象了,這個可以了解,但是在init(ServletConfig config)中,158行,還調用了一個init()方法,并且這個init()方法是空的,什麼讀沒有,這是為什麼呢?這個原因是為了防止一件事情,當我們需要在init方法中做一點别的事情,我們想到的方法就是繼承GenericServlet并且重寫了init(ServletConfig config)方法,這樣依賴,就破壞了原本在GenericServlet類中init(ServletConfig config)寫的代碼了,也就是在GenericServlet類中的成員變量config會一直是null,無法得到指派,因為被重寫了,就不會在執行GenericServlet中init(ServletConfig config)方法中的代碼。要想指派,就必須在重寫的init(ServletConfig config)方法中調用父類的init(ServletConfig config)方法,也就是super.init(ServletConfig config),這樣一來,就很不友善,怕有時候會忘了寫這句代碼,是以在GenericServlet類中增加一個init()方法,以後需要在init方法中需要初始化别的資料,隻需要重寫init()這個方法,而不需要去覆寫init(ServletConfig config)這個方法,這樣設計,就好很多,不用在管init(ServletConfig config)這個其中的内容了。也不用出現其他的問題。

service(ServletRequest req, ServletResponse res)

servlet 接收request發送過來的多元數組_servlet詳解

一個抽象方法,說明在GenericServlet類中并沒有實作該内容,那麼我們想到的是,在它上面肯定還有一層,也就是還有一個子類繼承它,實作該方法,要是讓我們自己寫的Servlet繼承GenericServlet,需要自己寫service方法,那豈不是累死,并且我們可以看到,service方法中的參數還是ServletRequest,ServletResponse。并沒有跟http相關對象挂鈎,是以我們接着往下面看。

HttpServlet類詳解

繼承了GenericServlet類,通過我們上面的推測,這個類主要的功能肯定是實作service方法的各種細節和設計。并且通過類名可以知道,該類就跟http挂鈎了。

servlet 接收request發送過來的多元數組_servlet詳解

關注service(HttpServletRequest req, HttpServletResponse resp)方法和service(ServletRequest req, ServletResponse res)方法。

service(ServletRequest req, ServletResponse res)方法

servlet 接收request發送過來的多元數組_servlet詳解

該方法中就做一件事情,就是将ServletRequest和ServletResponse這兩個對象強轉為HttpServletRequest和HttpServletResponse對象。為什麼能這樣轉?

首先要知道req、res是什麼類型,通過列印System.out.println(req),可以知道,req實際上的類型是org.apache.catalina.connector.RequestFacade Tomcat中的源碼。

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

通過圖可以得知,req的繼承結構:RequestFacade、httpServletRequest、ServletRequest,我們知道本身req是ServletRequest,那麼從繼承結構上看,它也可以看成HttpServletRequest,也可以看成ServletRequest,是以強轉為HttpServletRequest是可以的,如果不明白,我舉個例子,ArrayList、List、Object 這個,Object obj = new ArrayList(); List list = new ArrayList(); 一個ArrayList對象可以看成List對象, 也可以看成一個Object對象,現在obj是不是可以堪稱List對象呢?答案是可以的,因為obj就是ArrayList對象,既然是ArrayList對象,那麼就可以看成是List對象。一樣的道理,RequestFacade 對應 ArrayList、httpServleRequest對應 List、 ServletRequest 對應 Object。

轉換為httpServletRequest和HttpServletResponse對象之後,在調用service(HttpServletRequest req, HttpServletResponse resp)方法。

service(HttpServletRequest req, HttpServletResponse resp)

這個方法就是判斷浏覽器過來的請求方式是哪種,每種的處理方式不一樣,我們常用的就是get,post,并且,我們處理的方式可能有很多的内容,是以,在該方法内會将get,post等其他5種請求方式提取出來,變成單個的方法,然後我們需要編寫servlet時,就可以直接重寫doGet或者doPost方法就行了,而不是重寫service方法,更加有針對性。是以這裡就回到了我們上面編寫servlet時的情況,繼承httpServlet,而隻要重寫兩個方法,一個doGet,一個doPost,其實就是service方法會調用這兩個方法中的一個(看請求方式)。是以也就解答了我們一開始提的問題3。

四、幾個重點的對象。ServletConfig、ServletContext,request、response

講解四大類,ServletConfig對象,ServletContext對象、request對象,response對象

ServletConfig對象

擷取途徑:getServletConfig();

功能:上面大概提及了一下,能得到四個東西,

servlet 接收request發送過來的多元數組_servlet詳解

getServletName(); //擷取servlet的名稱,也就是我們在web.xml中配置的servlet-name

getServletContext(); //擷取ServletContext對象,該對象的作用看下面講解

getInitParameter(String); //擷取在servlet中初始化參數的值。這裡注意與全局初始化參數的區分。這個擷取的隻是在該servlet下的初始化參數

servlet 接收request發送過來的多元數組_servlet詳解

getInitParameterNames(); //擷取在Servlet中所有初始化參數的名字,也就是key值,可以通過key值,來找到各個初始化參數的value值。注意傳回的是枚舉類型

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

注意:在上面我們所分析的源碼過程中,我們就知道,其實可以不用先獲得ServletConfig,然後在擷取其各種參數,可以直接使用其方法,比如上面我們用的ServletConfig().getServletName();可以直接寫成getServletName();而不用在先擷取ServletConfig();了,原因就是在GenericServlet中,已經幫我們擷取了這些資料,我們隻需要直接拿就行。

ServletContext對象

擷取途徑:getServletContext(); 、getServletConfig().getServletContext(); //這兩種擷取方式的差別就跟上面的解釋一樣,第一種是直接拿,在GenericServlet中已經幫我們用getServletConfig().getServletContext();拿到了ServletContext。我們隻需要直接擷取就行了,第二種就相當于我們自己在擷取一遍,兩種讀是一樣的。

功能:tomcat為每個web項目都建立一個ServletContext執行個體,tomcat在啟動時建立,伺服器關閉時銷毀,在一個web項目中共享資料,管理web項目資源,為整個web配置公共資訊等,通俗點講,就是一個web項目,就存在一個ServletContext執行個體,每個Servlet讀可以通路到它。

1、web項目中共享資料,getAttribute(String name)、setAttribute(String name, Object obj)、removeAttribute(String name)

setAttribute(String name, Object obj) 在web項目範圍記憶體放内容,以便讓在web項目中所有的servlet讀能通路到

getAttribute(String name) 通過指定名稱獲得内容

removeAttribute(String name) 通過指定名稱移除内容

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

2、整個web項目初始化參數 //這個就是全局初始化參數,每個Servlet中都能擷取到該初始化值

getInitPatameter(String name) //通過指定名稱擷取初始化值

getInitParameterNames() //獲得枚舉類型

web.xml 配置 整個web項目的初始化

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

3、擷取web項目資源

3.1擷取web項目下指定資源的路徑:getServletContext().getRealPath("/WEB-INF/web.xml")

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

3.2擷取web項目下指定資源的内容,傳回的是位元組輸入流。InputStream getResourceAsStream(java.lang.String path)

前提知識:需要了解流。不知道的可以去看看IO流總結的文章

servlet 接收request發送過來的多元數組_servlet詳解

輸出内容截圖一部分

servlet 接收request發送過來的多元數組_servlet詳解

4、getResourcePaths(java.lang.String path) 指定路徑下的所有内容。

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

5還有很多别的方法,暫時用到的就這幾個了,以後需要在用的,就檢視源碼,看API。

request對象

我們知道,request就是将請求文本封裝而成的對象,是以通過request能獲得請求文本中的所有内容,請求頭、請求體、請求行 。

servlet 接收request發送過來的多元數組_servlet詳解

1、請求行内容的擷取。

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

2請求頭的擷取

随便百度一個東西,然後檢視的請求頭,包括以下這些内容,稍作了解。

servlet 接收request發送過來的多元數組_servlet詳解

String getHeader(java.lang.String name) 獲得指定頭内容String【】

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

long getDateHeader(java.lang.String name) 獲得指定頭内容Date

int getIntHeader(java.lang.String name) 獲得指定頭内容int

Enumeration getHeaders(java.lang.String name) 獲得指定名稱所有内容

3請求體的擷取 -- 請求參數的擷取

分兩種,一種get請求,一種post請求

get請求參數:http://localhost:8080/test01/MyServlet?username=jack&password=1234

post請求參數: <form method="post"><input type="text" name="username">

String request.getParameter(String) 獲得指定名稱,一個請求參數值。

String[] request.getParameterValues(String) 獲得指定名稱,所有請求參數值。例如:checkbox、select等

Map<String , String[]> request.getParameterMap() 獲得所有的請求參數

4請求轉發

request.getRequestDispatcher(String path).forward(request,response); //path:轉發後跳轉的頁面,這裡不管用不用"/"開頭,都是以web項目根開始,因為這是請求轉發,請求轉發隻局限與在同一個web項目下使用,是以這裡一直都是從web項目根下開始的,

web項目根:

開發:G:Workspacestest01WebRoot..

運作時:D:javatomcatapache-tomcat-7.0.53webappstest01..

web站點根:

運作時:D:javatomcatapache-tomcat-7.0.53webapps..

從這裡可以看出,web項目根就是從該web項目名開始,是以我們請求轉發時,隻需要接着項目名後面需要通路的路徑寫就行了,

特點:浏覽器中url不會改變,也就是浏覽器不知道伺服器做了什麼,是伺服器幫我們跳轉頁面的,并且在轉發後的頁面,能夠繼續使用原先的request,因為是原先的request,是以request域中的屬性都可以繼續擷取到。

response對象

servlet 接收request發送過來的多元數組_servlet詳解

常用的一個方法:response.setHeader(java.lang.String name, java.lang.String value) 設定指定的頭,一般常用。

例如:設定每隔3秒就自動重新整理一次,

response.setHeader("Refresh",3);

servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解
servlet 接收request發送過來的多元數組_servlet詳解

這樣可以看到現在時間的秒數,會發現每隔三秒就會自動重新整理一次頁面。

這個最重要的一個就是重定向,其他的一些操作都被封裝到response對象中了,重點講解重定向

重定向(頁面跳轉)

方式一:手動方案

response.setStatus(302); //狀态碼302就代表重定向

response.setHeader("location","http://www.baidu.com");

方式二:使用封裝好的,通過response.sendRedirect("http://www.baidu.com");

特點:伺服器告訴浏覽器要跳轉的頁面,是浏覽器主動去跳轉的頁面,浏覽器知道,也浏覽器的位址欄中url會變,是浏覽器重新發起一個請求到另外一個頁面,是以request是重新發起的,跟請求轉發不一樣。

注意:response.sendRedirect(path); //

第一種:response.sendRedirect("/test01/MyServlet01"); //使用了"/"開頭,說明是從web站點根開始,是以需要寫test01/MyServlet01

第二種:response.sendRedirect("MyServlet01"); //沒有使用"/"開頭,說明是從web項目根開始,那麼就無需寫test01了。

重定向沒有任何局限,可以重定向web項目内的任何路徑,也可以通路别的web項目中的路徑,并且這裡就用"/"區分開來,如果使用了"/"開頭,就說明我要重新開始定位了,不通路剛才的web項目,自己寫項目名,如果沒有使用"/"開始,那麼就知道是通路剛才那個web項目下的servlet,就可以省略項目名了。就是這樣來差別。

五、總結

這一章節篇幅較長,不過理清很多知識點

1、什麼是servlet?如果編寫servlet?

2、分析了servlet的部分源碼,知道了其中的一些設計巧妙的東西,比如,本來編寫servlet是能看到其生命周期的,但是在其設計下,我們隻關注doGet和doPost方法,為什麼能這樣呢?就可以通過源碼中得知。

3、servlet的生命周期,web.xml的配置

4、servlet中的ServletConfig對象,ServletContext對象,request對象,response對象的詳細講解。包括其中的一些常用的方法。