web開發學習筆記:web應用中URI的組成結構

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


 

這篇文章裏提過,Servlet本質上是一個Java對象。http(超文本協議)請求一定是要經過HTTP服務器處理的,而超文本協議的內容基本都是文本字符串的形式(如下圖)

http協議的各種信息包含在這樣的一個結構體當中。如果我們只是用JavaSE來處理http請求,這當然可以實現,但是也可以想象工作過程有多繁瑣。同時http是無狀態的協議,直接使用JavaSE處理http請求的話,我們還得負責對象的生命週期管理。

上面只是簡單說了http直接用JavaSE處理的話又多麻煩,事實上繁瑣的點不止是這些。

幸運的是,我們有容器技術。容器是運行在http服務器之上的。容器接收到http請求,然後替我們整理其中的信息並轉換成一個個Java對象,這樣我們就可以使用這些對象的getXXX()方法很快捷地獲取到我們想要的信息。同時容器也幫我們管理着這些對象的生命週期。

綜上所述,容器讓我們開發web時能專注於處理信息而不是解析信息。

http服務器與容器處理請求過程

 

容器將http請求信息和響應信息轉換成了Java對象,這兩個對象分別是HttpServletRequest和HttpServletResponse。而負責處理請求的對象是HttpServlet。Java規定了這個對象的關係,關係如下圖所示

從繼承架構上看,HttpServlet繼承Servlet。這樣的設計是因爲當初設計Servlet時,是希望Servlet不止是應用在Http之中,所以關於網絡的的基本規範是定義在Servlet中,而關於Http的相關行爲則是定義在HttpServlet。

同時Servlet和HttpServlet的依賴對象也是基於上面所述的原因設計成如今的繼承架構。ServletRequest和ServletResponse定義了請求和響應的普遍行爲,而HttpServletRequest和HttpServletResponse定義了Http相關的請求和響應。

下面說一下HttpServletRequest和HttpServletResponse。

 


HttpServletRequest

通過HttpServletRequest可以獲取到很多信息,包括網頁傳到服務器的參數,網頁本身配置信息(比如瀏覽器信息)。下面簡單講解一下獲取這些數據的方法

  • 獲取請求參數

獲取請求參數的方法可以看Orcale的文檔,主要就是這幾個方法。

getAttrbute等系列方法和getParameter等系列方法。兩者的區別就是前者用於處理對象,而後者用於處理鍵值對。

 

  • 獲取請求標頭

獲取請求標頭主要就是下面的這三個方法

getHeader(),getHeaders(),getHeaderNames()。三者的用法看API文檔即可。

值得一說的是,getHeaderNames()這個方法,獲取所有的Header Name。和請求參數中的getAttributeNames一樣,這個方法返回類型的是Enumeration

Enumeraiton類比較古老,該方法已經被Iterator取代。

這裏就簡單介紹一下Enumeration的用法。

我們可以用Collections.list()來將Enumeration轉換爲ArrayList來使用,比如下面的代碼。

Collecitons.list(request.getHeaderNames())
    .foreach(name -> (
        System.out.print(name + request.getHeader(name));

 

另外,如果請求標頭的值是int型或Date型,那麼還可以用getIntHeader()和getDateHeader方法直接獲取到int或Date的值。但如果標頭值無法轉換成對應類型的話,會拋出異常。

 

下面說說,處理標頭時,常見的一些問題。

 

  • 參數編碼

在中文世界裏,計算機總是會遇到編碼問題。網頁若使用UTR-8傳中文,而容器卻使用其他字符集接收中文,那就很可能出現亂碼問題。總之,網頁使用的字符集和容器使用的字符集不一致的話,就可能出現亂碼問題。

http協議中,關於使用的字符集信息是存儲在標頭content-type之中,比如。當然,content-type標頭作爲MIME類型,它不止是指明瞭http中body的編碼方法,也指明瞭當前網絡資源屬於什麼型(text,html等)。這裏我們只是先強調content-type中設置編碼方式。

HttpServletRequest中有獲取到編碼方式可以有下面三種方法

  1. getContentType():獲取到的不止是編碼方式,
  2. getHeader("content-type"):和getContentType一樣。
  3. getCharacterEncoding():直接獲取到編碼方式。

因爲content-type中包含的不止是編碼方式的信息,所以如果我們只想要處理編碼方式的話,最好還是直接使用getCharacterEncoding()方法最好。

文檔中關於getCharacterEncoding()的描述如下所示

從描述中可以看出,如果網頁沒有在content-type中指明字符編碼信息的話,getCharacterEncoding()會返回null(content-type沒有指明的話,使用getContentType()也是會返回null)。下面是網頁沒有指明編碼方式的情況下的實驗結果。

 

 

 

 

 

 

 

 

 

 

 

 

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