1. 程式人生 > >Java Web——Servlet基礎

Java Web——Servlet基礎

靜態網頁:

靜態網頁是指存放在伺服器檔案系統中實實在在的HTML檔案。當用戶在瀏覽器中輸入頁面的URL,然後回車,瀏覽器就會將對應的html檔案下載、渲染並呈現在視窗中。早期的網站通常都是由靜態頁面製作的。

動態網頁:

當瀏覽器請求伺服器的某個頁面時,伺服器根據當前時間、環境引數、資料庫操作等動態的生成HTML頁面,然後在傳送給瀏覽器(後面的處理就跟靜態網頁一樣了),如登陸註冊驗證,訂單生成和提交等。很明顯,動態網頁中的“動態”是指伺服器端頁面的動態生成,相反,“靜態”則指頁面是實實在在的、獨立的檔案。

Web Project目錄結構

Servlet 是什麼?

Java Servlet 是執行在 Web 伺服器或應用伺服器上的程式,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 伺服器上的資料庫或應用程式之間的中間層。

使用Servlet,可以收集網頁表單的使用者輸入,呈現來自資料庫或者其他源的記錄,還可以動態建立網頁。

要注意的是,由於 Servlet 是伺服器端小程式,所以 Servlet 必須部署在 Servlet 容器中才能使用,例如 Tomcat,Jetty 等。

Servlet æ¶æ

Servlet 容器

要介紹 Servlet 必須要先把 Servlet 容器說清楚,Servlet 與 Servlet 容器的關係有點像槍和子彈的關係,槍為彈而生,而彈又讓槍有了殺傷力。雖然它們是彼此依存的,但是又相互獨立發展,這一切都是為了適應工業化生產。從技術角度來說是為了解耦,通過標準化介面來相互協作。

Servlet容器又是什麼東西?就是實現了Servlet規範,然後暴露出來一些程式設計的介面供我們實現自己的邏輯,所以每個自定義的Servlet類都要實現Servlet介面,它能夠生成動態的內容,不向Web伺服器一樣,只是提供靜態資源。

從上圖可以看出 Tomcat 的容器分為四個等級,真正管理 Servlet 的容器是 Context 容器,一個 Context 對應一個 Web 工程

Servlet API

目前用的是Servlet 3.1 API - Apache Tomcat 8.0.53,有以下四個包

  • javax.servlet:包含Servlet與Servlet容器進行通訊需要的類和介面,比如請求、響應、過濾和監聽等;
  • javax.servlet.http:包含Servlet的實現類httpServlet與Servlet容器進行通訊需要的類和介面;
  • javax.servlet.annotation:使用Servlet、Filter和Listener時需要的註解;
  • javax.servlet.descriptor:提供對配置資訊進行程式設計式訪問的型別;

servlet的核心技術就是實現Servlet介面,

如 javax.servlet.http.HttpServlet 類已經實現了 Servlet 介面的所有方法。

             編寫 Servlet時直接繼承 HttpServlet,並覆蓋需要的方法即可,一般只覆蓋 doGet()與 doPost()方法

package servlet;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class HelloServlet
 */
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Servlet#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

Servlet 的生命週期

1,初始化階段                  呼叫init()方法

2,響應客戶請求階段  呼叫service()方法,由service()方法根據請求方式呼叫doGet()或者doPost()方法

3,終止階段                呼叫destroy()方法

Servlet初始化階段:

在下列時刻Servlet容器裝載Servlet,Servlet被裝載後,Servlet容器建立一個Servlet例項並且呼叫Servlet的init()方法進行初始化。在Servlet的整個生命週期內,init()方法只被呼叫一次。

1,Servlet容器啟動時自動裝載某些Servlet,實現它只需要在web.XML檔案中的<Servlet></Servlet>之間新增如下程式碼:


<loadon-startup>1</loadon-startup> 

2,在Servlet容器啟動後,客戶首次向Servlet傳送請求

3,Servlet類檔案被更新後,重新裝載Servlet

簡單介紹一下servlet接受和響應的過程:

首先客戶傳送一個請求,servlet呼叫service方法對請求進行響應。通過原始碼可知,service()方法對請求的方式進行匹配,然後再進入對應的方法中呼叫邏輯層的方法,實現對客戶的響應。在Servlet介面和GenericServlet中是沒有doGet,doPost等等這些方法的,HttpServlet中定義了這些方法,但是都是返回error資訊,所以,我們每次定義一個Servlet的時候,都必須實現doGet或doPost等這些方法。

GenericServlet是一個通用的,不特定於任何協議的Servlet,它實現了Servlet介面。而HttpServlet繼承於GenericServlet,因此HttpServlet也實現了Servlet介面。所以我們定義Servlet的時候只需要繼承HttpServlet即可。

Servlet介面和GenericServlet是不特定於任何協議的,而HttpServlet是特定於HTTP協議的類,所以HttpServlet中實現了service()方法,並將請求ServletRequest,ServletResponse強轉為HttpRequest和HttpResponse。

public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException("non-HTTP request or response");
        }
        service(request, response);
    }
public abstract class HttpServlet extends GenericServlet {}

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {}
public interface Servlet {}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }

Servlet響應請求階段:

對於使用者到達Servlet的請求,Servlet容器會建立特定於這個請求的ServletRequest物件和ServletResponse物件,然後呼叫Servlet的service方法。service方法從ServletRequest物件獲得客戶請求資訊,處理該請求,並通過ServletResponse物件向客戶返回響應資訊。

public Map<String, String[]> getParameterMap();

    /**
     * Returns the name and version of the protocol the request uses in the form
     * <i>protocol/majorVersion.minorVersion</i>, for example, HTTP/1.1. For
     * HTTP servlets, the value returned is the same as the value of the CGI
     * variable <code>SERVER_PROTOCOL</code>.
     *
     * @return a <code>String</code> containing the protocol name and version
     *         number
     */

Servlet終止階段:

  當WEB應用被終止,或Servlet容器終止執行,或Servlet容器重新裝載Servlet新例項時,Servlet容器會先呼叫Servlet的destroy()方法,在destroy()方法中可以釋放掉Servlet所佔用的資源。

在哪些情況下 tomcat 容器會裝載 servlet ?

1.

2.

3. 

Servlet與JSP的比較:

  • 有許多相似之處,都可以生成動態網頁。
  • JSP的優點是擅長於網頁製作,生成動態頁面比較直觀,缺點是不容易跟蹤與排錯。
  • Servlet是純Java語言,擅長於處理流程和業務邏輯,缺點是生成動態網頁不直觀。

參考文章