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介面,它能夠生成動態的內容,不向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語言,擅長於處理流程和業務邏輯,缺點是生成動態網頁不直觀。
參考文章