HttpServletRequest對象
HttpServletRequest對象
我們都知道瀏覽器通過http協議與Tomcat(web服務器)通信時,會生成兩個對象,一個是HttpServletRequest對象,一個是HttpServletResponse對象。它們是一對數據封裝對象,前者封裝客戶端的請求頭,後者封裝服務器的響應頭。而在這裏要介紹的是HttpServletRequest對象,HttpServletRequest實際上是個接口,是Java所定制的接口,這個接口是由開發web服務器的人員去做實現的。
可以看一下HttpServletRequest的源碼:
我們可以看看Tomcat中實現這個接口的兩個類:
Request類:
RequestFacade類:
可以看到以上這兩個類都各自實現了HttpServletRequest接口,但實際上這個兩個類是有關聯的,具體的代碼實現其實是由Request類完成的,而RequestFacade類只是作為一個轉發的存在。而且從類的名稱上也可以看得出來,Facade是外觀、正面的意思,所以這是一個外觀類,而在這個RequestFacade類後面的真正實現類是Request。可以想象成RequestFacade是Request的前端、門面,Request則是RequestFacade的後臺、後端。
看一下RequestFacade的構造器和部分代碼就知道了:
再來看看RequestFacade的部分代碼:
而且這個類的代碼行數也不到一千行:
下面再來看看Request類的代碼:
可以看到getContextPath這個方法是在Request類上實現的,並且因為實現代碼在這個類裏,所以代碼行數比RequestFacade類多:
示意圖:
從上圖可以看到HttpServletRequest接口和Request、RequestFacade實現類之間構成了一個模式,這個設計模式就是外觀模式。外觀模式為子系統中的一組接口提供了一個一致的界面,這個界面就是RequestFacade,並且定義了一個高層接口這個接口就是HttpServletRequest,這個接口使得這一子系統更加容易使用。
外觀模式好處在於隱藏了系統的復雜性,並向客戶端提供了一個客戶端可以訪問系統的接口(HttpServletRequest)。這種類型的設計模式屬於結構型模式,它向現有的系統添加一個接口,來隱藏系統的復雜性,這個模式實現了子系統與客戶端之間的松耦合關系。所以我們都是通過HttpServletRequest接口對象去調用方法的,而實現類和界面類都隱藏在背後,而且這兩個類也不是Java實現的,而是開發web服務器的人員實現的(Java的尿性一貫如此)。
關於對象池:
HttpServletRequest和HttpServletResponse對象是存放在一個對象池中的,這是一個活動的能夠自動增長的對象池,就和自動增長的線程池一樣,每當對象不夠用的時候就會新增加對象。這個對象池可以優化服務器資源,因為這兩個對象可以反復的利用,不會造成資源的浪費。如果沒有這個對象池的話,每次用戶訪問就會新建一次對象的話,這麽做十分耗費資源,而且速度還慢。所以從這一點可以知道,這個對象池就是起到了一個優化資源的作用(好像池子都是這麽回事)。
我們可以打印這個兩個對象的hash值查看一下就知道了(需要不斷的刷新訪問頁面):
運行結果:
從圖中可以看到有幾個hash值重復了好幾次,所以從這一點就可以得知它使用了對象池機制。
好了,以上簡單介紹完HttpServletRequest中接口與實現類的一些關系和使用到了什麽設計模式與對象池機制,接下來介紹一下HttpServletRequest中較為常用的一些方法:
獲得服務器相關信息方法:
方法名稱 | 作用 |
getInputStream() | 獲得本次通信的Input流對象 |
getServerName() | 獲得服務器的名稱 |
getServerPort() | 獲得服務器的端口 |
getContextPath() | 獲得web工程的路徑 |
getLocale() | 獲得區域所使用的語言 |
代碼示例:
運行結果:
獲得請求頭信息方法(請求頭中的信息是鍵/值對形式的):
方法名稱 | 作用 |
getHeader(String) | 參數為鍵,獲得該鍵的值 |
getHeaderNames() | 返回所有的鍵 |
getHeaders(String) | 參數為鍵,獲得拆分的值 |
getContentLength() | 獲得網頁文件的長度,沒有的話就會返回-1 |
getContentType() | 獲得網頁文件的類型 |
getMethod() | 獲得請求的方法 |
getQueryString() | 獲得請求的參數,但是要註意:只有get類型的請求方式才有效果 |
getRequestURI() | 獲得訪問的目標Servlet所在工程下的那一部分內容 |
getRequestURL() | 獲得整個URL |
代碼示例:
運行結果:
獲得客戶端的IP和端口方法:
方法名稱 | 作用 |
getRemoteAddr() | 獲得客戶端IP地址 |
getRemoteHost() | 獲得客戶端IP地址 |
getRemotePort() | 獲得客戶端端口 |
代碼示例:
運行結果:
獲得和設置表單數據方法(如果是上傳文件的話則無法獲取文件中的數據):
方法名稱 | 作用 |
setCharacterEncoding(String) | 設置表單提交上來的文本編碼 |
getParameter(String) | 得到表單中某一個指定的name屬性的值 |
getParameterMap() | 獲得所有的鍵值對 |
getParameterNames() | 獲得所有的name屬性的值: |
getParameterValues(String) | 獲得重復的name屬性的值 |
Html代碼示例:
Java代碼示例:
瀏覽器表單:
控制臺結果:
獲得和設置表單屬性相關方法:
方法名稱 | 作用 |
getAttribute(String) | 獲得屬性對象 |
getAttributeNames() | 獲得所有的屬性名稱 |
removeAttribute(String) | 刪除參數中字符串描述的屬性 |
setAttribute(String, Object) | 設置屬性和屬性的值,這是鍵/值對形式的 |
註意:以上這幾個方法只是在web容器內部流轉,僅在具有轉發關系的Web組件之間共享,也就說只在這個範圍內有效,所以不能直接把值獲得到代碼中打印,以下使用實際示例演示一下就知道無法直接獲得值了:
代碼示例:
瀏覽器:
控制臺結果:
本文出自 “zero” 博客,請務必保留此出處http://zero01.blog.51cto.com/12831981/1979476
HttpServletRequest對象