一、Servlet的前世今生

Java Servlet技術簡稱Servlet技術,是Java開發Web應用的底層技術。由Sun公司於1996年發布,用來代替CGU----當時生成Web動態內容的主流技術。CGI的問題是每一個WEB請求都需要重新啟動一個進程來處理。創建進程需要消耗不少CPU周期,導致難以編寫刻苦鏖戰的CGI程序,而Servlet在創建後(處理第一個請求時)就一直保存在內存中,這就比CGI有著更好的性能。

Servlet是一個Java程序,一個servlet應用有一個或多個Servlet程序。JSP頁面會被轉換和編譯成servlet程序。

Servlet程序無法獨立運行,必須運行在Servlet容器中。Servlet容器將用戶的請求床底給servlet應用,並將結果返回給用戶。由於大部分Servlet用用都包含多個JSP頁面,因此更準確地說是「Servlet/JSP應用」。

Servlet/JSP容器是一個可以同時處理Servlet和靜態內容的Web容器。過去,由於通常認為HTTP伺服器比Servlet/JSP 容器更加可靠,因此人們習慣將servlet容器當做HTTP伺服器的一個模塊,這種模式下,HTTP伺服器用來處理靜態資源,Servlet容器則負責生成動態內容。

Tomcat架構圖

我們可以看到Tomcat的核心就是Servlet/Jsp容器

Tomcat的執行過程一般可以認為是:

— 獲取連接 — Servlet來分析請求(HttpServletRequest)— 調用其service方法,進行業務處理 — 產生相應的響應(HttpServletResponse)— 關閉連接

二、一個簡單的Servlet

1.我們來創建一個servlet

public class HelloServlet extends HttpServlet {

/**
* Constructor of the object.
*/
public HelloServlet() {
super();
}

/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}

/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the GET method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}

/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is ");
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}

/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}

}

我們可以看見,這個HelloServlet繼承了HTTPServlet類,主要有init()、doGet()、doPost()、destroy()四個方法。我們在瀏覽器中分別用get和post訪問這個servlet。

我們可以看到,這就是上文我們編寫的doGet方法中的Html生成的頁面。

返回的是doPost方法中構造的html。

三、Servlet從請求到響應

如上圖所示,當我們從瀏覽器向伺服器發起一個請求,通常會包含如下信息:RequestUrl和Method,URL中包含hostname(localhost)和port(8080),hostname 和 port 是用來與伺服器建立 TCP 連接,而後面的 URL 才是用來選擇伺服器中那個子容器服務用戶的請求。

1.如我們在第一部分講的tomcat為例,一個Connecter將在某個指定的埠上偵聽客戶請求,接收瀏覽器的發過來的 tcp 連接請求,創建一個 Request 和 Response 對象分別用於和請求端交換數據,然後會產生一個線程來處理這個請求並把產生的 Request 和 Response 對象傳給處理Engine(Container中的一部分),從Engine出獲得響應並返回客戶。

Container架構
  • Engine 容器 Engine 容器比較簡單,它只定義了一些基本的關聯關係
  • Host 容器 Host 是 Engine 的字容器,一個 Host 在 Engine 中代表一個虛擬主機,這個虛擬主機的作用就是運行多個應用,它負責安裝和展開這些應用,並且標識這個應用以便能夠區分它們。它的子容器通常是 Context,它除了關聯子容器外,還有就是保存一個主機應該有的信息。
  • Context 容器

    Context 代表 Servlet 的 Context,它具備了 Servlet 運行的基本環境,理論上只要有 Context 就能運行 Servlet 了。簡單的 Tomcat 可以沒有 Engine 和 Host。Context 最重要的功能就是管理它裡面的 Servlet 實例,Servlet 實例在 Context 中是以 Wrapper 出現的,還有一點就是 Context 如何才能找到正確的 Servlet 來執行它呢? Tomcat5 以前是通過一個 Mapper 類來管理的,Tomcat5 以後這個功能被移到了 request 中,在前面的時序圖中就可以發現獲取子容器都是通過 request 來分配的。

  • Wrapper 容器 Wrapper 代表一個 Servlet,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。Wrapper 是最底層的容器,它沒有子容器了,所以調用它的 addChild 將會報錯。 Wrapper 的實現類是 StandardWrapper,StandardWrapper 還實現了擁有一個 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 將直接和 Servlet 的各種信息打交道。

四、Tomcat Server處理一個HTTP請求的過程

1、用戶點擊網頁內容,請求被發送到本機埠8080,被在那裡監聽的Coyote HTTP/1.1 Connector獲得。

2、Connector把該請求交給它所在的Service的Engine來處理,並等待Engine的回應。 3、Engine獲得請求localhost/servlet/helloServlet,匹配所有的虛擬主機Host。 4、Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機),名為localhost的Host獲得求/servlet/HelloServlet,匹配它所擁有的所有的Context。Host匹配到路徑為/servlet的Context(如果匹配不到就把該請求交給路徑名為「 」的Context去處理)。 5、path=「/servlet」的Context獲得請求/HelloServlet,在它的mapping table中尋找出對應的Servlet。6、構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用Servlet的doGet()或doPost().執行業務邏輯、數據存儲等程序。 7、Context把執行完之後的HttpServletResponse對象返回給Host。 8、Host把HttpServletResponse對象返回給Engine。 9、Engine把HttpServletResponse對象返回Connector。 10、Connector把HttpServletResponse對象返回給客戶Browser。

簡單的講就是:

當用戶發送一個請求到某個servlet的時候,servlet容器會創建一個servletRequest和servletResponse對象。在servletRequest對象中封裝了用戶的請求信息,然後servlet容器把servletRequest和servletResponse對象傳遞給用戶所請求的servlet,servlet把處理好的結果卸載servletResponse中,然後servlet容器把響應結果傳給用戶。


推薦閱讀:
相关文章