在前面的學習中知道HTTP是一套網絡通訊協議,並且它是一種無狀態的協議。這裏無狀態的html
含義是指客戶端web瀏覽器和web服務器之間不須要創建持久的鏈接,這意味着當一個客戶端向java
服務器發出請求(HttpRequest),而後web服務器返回響應(HttpResponse)以後鏈接就關閉了,web
在web服務器上不保留鏈接的信息。apache
HTTP協議遵循請求(Request)/應答(Response)模型,瀏覽器向服務器發送請求,服務器處理瀏覽器
請求並返回適當的應答。其一次鏈接被構形成一次請求和應答。服務器
在完整的一次請求、應答模式中HTTP通訊的過程爲如下七個步驟:網絡
一、創建TCP鏈接框架
在HTTP協議開始工做以前,瀏覽器和服務器首先須要創建鏈接,該鏈接是經過TCP來完成的jsp
二、瀏覽器向服務器發送請求指令ide
TCP鏈接創建了之後,瀏覽器就能夠向服務器發送請求指令了。
常見的位POST和GET
三、瀏覽器發送請求頭消息
瀏覽器發送請求命令以後,還要以頭消息的形式向服務器發送一些別的信息,以後瀏覽器發送
一行空白行來通知服務器其已經結束了頭信息的發送。
四、Web服務器響應
瀏覽器發送請求後進行一些相關邏輯的處理以後,服務器會向客戶端瀏覽器返回應答。
例如:HTTP/1.1 200 OK 版本號+狀態碼
五、web服務器發送應答頭信息
如同客戶端同樣,服務器應答也會想用戶發送關於他本身的數據和被請求的文檔信息。
六、web服務器向瀏覽器發送數據
向瀏覽器發送頭信息,一樣以空白行來表示頭信息的發送結束。以後以Content-type應答
頭信息所描述的格式發送實際的數據。
七、web服務器關閉TCP鏈接
當實際的數據發送完畢以後,Web服務器關閉TCP鏈接。不過服務器或者瀏覽器頭信息
加入了Connection:keep-alive。TCP鏈接在數據發送完畢以後仍然保持的是打開狀態。
縮短了下一次鏈接創建的時間,節約了網絡帶寬。
HTTP請求信息由三部分組成:
請求方法URI協議/版本、請求頭(Request Header)、正文
HTTP/1.1 表示的是HTTP一些的版本,GET表示請求的方法,/sample.jsp表示資源URI。
在Intenet應用中經常使用的請求方法是GET和POST,固然還有其餘的一些方法例如HEAD、PUT
URI完整的指定了要訪問的網絡資源,通常狀況下只須要給出相對於服務器根目錄的相對目錄
便可。
上述中GET方法和POST方法由很大的區別,筆者會找個時間作一個總結。
以一行空信息爲結束標誌,請求頭信息包含了一些客戶端環境信息和一些正文信息。
請求正文包含客戶端提交的查詢字符串的信息。通常狀況下查詢字符串信息是經過表單
傳遞給服務器,進行一些邏輯的處理,例如登陸,註冊等功能。
瞭解了HTTP協議和HTTP請求的相關內容,咱們可能會思考一個問題:Servlet中如何獲取
HTTP請求信息來實現相關的業務邏輯呢?
接下來筆者將實際進行一下演示,來講明Servlet對HTTP請求的處理。
閱讀源碼能夠知道HTTP請求是封裝在HttpServletRequest對象中的。
不過這裏咱們會發現HttpServletRequest是一個接口,是不能直接實例化的,不過根據Java
的多態性質咱們不難猜測到,具體實例化的確定是實現此接口的子類,不過咱們如何知道是哪
個類呢?(其實這裏實例化的是Tomcat容器裏面的類)
利用反射嘛,合理的運用反射在一些框架的學習中是十分有必要的。
class org.apache.catalina.connector.RequestFacade這裏是筆者經過反射獲得的結果,具體的類在Tomcat容器中,對於Tomcat的學習筆者
有時間的時候會進行下去的。
咱們如今知道HttpServletRequest封裝了HTTP請求的相關信息,這些信息咱們如何獲取呢?
讀者能夠去查閱其源碼。這裏筆者給出一些比較經常使用的方法。
getHeader(name):返回指定的請求頭的信息。
............
getMethod():獲取HTTP請求的方法。
getContextPath();獲取請求URI資源的上下文路徑
getServletPath();獲取Servlet的映射路徑
getPrarameter(parameterName)
............................................................
這裏Tomcat在實現了對HTTP請求的封裝以後,還提供了請求派發的功能:每一個客戶的請求
能夠傳遞給多個Servlet、web應用程序中的其餘資源。整個的過程是在服務器端完成的,沒有
任何客戶端的參與不須要在客戶端瀏覽器和服務器之間傳遞什麼特殊的信息。
研究其源碼能夠發現其是藉助於RequestDispatcher對象來實現的。
須要注意的是RequestDispatcher提供了兩種派發的方式:
include、forward();二者的區別在於forward()方法只會輸出後面頁面的內容,而include()
方法兩個頁面都會輸出。
package com.kiritor.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class HelloServlet */ public class HelloServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public HelloServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(request.getMethod()); System.out.println(request.getContextPath()); System.out.println(request.getHeader("User-Agent")); System.out.println(request.getParameter("username")); } }這裏咱們直接看輸出結果吧:
至於其餘的方法,筆者這裏就很少講了,讀者本身去看源碼,寫實例嘗試吧。
以後一篇文章將會就HTTP響應,以及Servlet如何處理HTTP的響應作一些總結、學習。
OK,這篇文章就到這兒了!