首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Servlet 開發三大方式全解析:實現接口、繼承 GenericServlet、繼承 HttpServlet

     編輯:Java 綜合教學

Servlet 規范核心契約

javax.servlet.Servlet 接口定義了 Servlet 的生命周期契約:

public interface Servlet {
    void init(ServletConfig config) throws ServletException;  // 初始化,僅一次
    void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; // 服務,多次
    void destroy();                                           // 銷毀,僅一次
    ServletConfig getServletConfig();                         // 獲取配置
    String getServletInfo();                                  // 獲取描述信息
}

方式一:直接實現 Servlet 接口 (教學演示用)

完整實現代碼

package com.focus;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class MyFirstServlet implements Servlet {
    private transient ServletConfig config;

    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        System.out.println("【MyFirstServlet】init() 執行 - 裝載到內存");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) 
            throws ServletException, IOException {
        System.out.println("【MyFirstServlet】service() 執行 - 處理請求");
        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out = res.getWriter();
        out.println("

Hello World from MyFirstServlet!

"); out.println("

時間: " + new java.util.Date() + "

"); } @Override public void destroy() { System.out.println("【MyFirstServlet】destroy() 執行 - 卸載銷毀"); } @Override public ServletConfig getServletConfig() { return config; } @Override public String getServletInfo() { return "MyFirstServlet v1.0"; } }

編譯與部署關鍵步驟

  1. Web 應用標準目錄結構:
    webapps/MyServletDemo/
    ├── WEB-INF/
    │   ├── web.xml
    │   └── classes/
    │       └── com/focus/MyFirstServlet.class
  2. 編譯需引入 servlet-api.jar (位於 Tomcat/lib/):
    javac -cp "D:/Tomcat/lib/servlet-api.jar" -d WEB-INF/classes src/com/focus/MyFirstServlet.java
  3. web.xml 註冊與映射:
    <servlet>
      <servlet-name>MyFirstServlet</servlet-name>
      <servlet-class>com.focus.MyFirstServlet</servlet-class>
      <load-on-startup>1</load-on-startup> <!-- 啟動時加載 -->
    </servlet>
    <servlet-mapping>
      <servlet-name>MyFirstServlet</servlet-name>
      <url-pattern>/My</url-pattern>
    </servlet-mapping>

訪問驗證

啟動 Tomcat,瀏覽器訪問 https://localhost:8080/MyServletDemo/My,頁面顯示 "Hello World...",控制台輸出 init → service 日志。

方式二:繼承 GenericServlet (协议无关)

GenericServlet 實現了 Servlet、ServletConfig、Serializable,提供了 init/destroy/getServletConfig 默認實現,僅需重寫 service()。

代碼示例

package com.focus;

import javax.servlet.*;
import java.io.*;

public class MyGenericServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) 
            throws ServletException, IOException {
        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out = res.getWriter();
        out.println("

Hello from GenericServlet!

"); out.println("

協議無關,適用於任何請求/響應模型

"); } }

web.xml 配置

<servlet>
  <servlet-name>MyGenericServlet</servlet-name>
  <servlet-class>com.focus.MyGenericServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyGenericServlet</servlet-name>
  <url-pattern>/Generic</url-pattern>
</servlet-mapping>

方式三:繼承 HttpServlet (HTTP 專用,實戰標準)

HttpServlet 繼承 GenericServlet,在 service() 中解析 HTTP 方法分發到 doGet/doPost/doPut/doDelete...,並封裝 HttpServletRequest/Response。

完整業務示例:用戶歡迎頁

package com.focus;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class MyHttpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println("

這是 doGet 響應

"); resp.getWriter().println("

請用 POST 提交表單

"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); String username = req.getParameter("username"); PrintWriter out = resp.getWriter(); if (username == null || username.trim().isEmpty()) { out.println("

用戶名不能為空!

"); } else { out.println("

歡迎 " + username + " 光臨本站!

"); out.println("

請求方法: " + req.getMethod() + "

"); out.println("

客戶端 IP: " + req.getRemoteAddr() + "

"); } } }

配套 HTML 表單 (go.html)

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>登錄頁面</title></head>
<body>
  <h2>用戶登錄</h2>
  <form action="/MyServletDemo/MyHttpServlet" method="post">
    <label>用戶名: <input type="text" name="username" required></label>
    <button type="submit">提交</button>
  </form>
</body>
</html>

web.xml 映射

<servlet>
  <servlet-name>MyHttpServlet</servlet-name>
  <servlet-class>com.focus.MyHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyHttpServlet</servlet-name>
  <url-pattern>/MyHttpServlet</url-pattern>
</servlet-mapping>

測試流程

  1. 訪問 /go.html → 顯示表單
  2. 輸入用戶名提交 → 觸發 doPost → 顯示歡迎信息
  3. 直接訪問 /MyHttpServlet → 觸發 doGet → 提示用 POST

Servlet 映射規則詳解

url-pattern 三種匹配模式

模式語法示例匹配示例
精確匹配/path/user/login/user/login
目錄匹配/path/*/user/*/user/, /user/list, /user/add/123
擴展名匹配*.ext*.do, *.action/login.do, /user/add.action
默認 Servlet//所有未匹配路徑 (靜態資源)

多映射示例

<servlet>
  <servlet-name>Demo</servlet-name>
  <servlet-class>com.focus.MyHttpServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>Demo</servlet-name>
  <url-pattern>/demo</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>Demo</servlet-name>
  <url-pattern>/demo.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>Demo</servlet-name>
  <url-pattern>/api/demo/*</url-pattern>
</servlet-mapping>

同一 Servlet 可映射多個 URL 模式。

匹配優先級規則

  1. 精確路徑匹配優先 (如 /user/login)
  2. 最長目錄匹配 (如 /user/* 勝過 /*)
  3. 擴展名匹配 (如 *.do)
  4. 默認 Servlet (/)

load-on-startup 載入順序控制

<servlet>
  <servlet-name>InitServlet</servlet-name>
  <servlet-class>com.focus.InitServlet</servlet-class>
  <load-on-startup>1</load-on-startup> <!-- 數值越小越早載入 -->
</servlet>
<servlet>
  <servlet-name>CacheServlet</servlet-name>
  <servlet-class>com.focus.CacheServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
</servlet>
  • >0:容器啟動時實例化並調用 init(),數值小優先
  • =0:同 >0
  • <0 或缺省:首次請求時載入 (懶加載)

典型用途:初始化緩存、加載配置、啟動定時任務、預熱連接池。

Tomcat 管理器實戰

訪問 https://localhost:8080/manager/html (需配置 tomcat-users.xml 添加 manager-gui 角色) 可:

  • 查看所有部署應用、會話數、運行時間
  • Reload:熱重載應用 (開發極其有用,無需重啟 Tomcat)
  • Stop/Start:單獨控制應用生命周期
  • Undeploy:移除應用

三種方式對比總結

維度實現 Servlet 接口繼承 GenericServlet繼承 HttpServlet (推薦)
代碼量最大 (5 方法全實現)中等 (僅 service)最小 (按需重寫 doXxx)
HTTP 特性支持手動轉型 Request/Response手動轉型原生 HttpServletRequest/Response
方法分發自己在 service 判斷 method自己判斷自動分發 doGet/doPost...
適用場景教學理解契約、非 HTTP 協議自定義協議、教學過渡99% Web 應用開發

實戰中始終繼承 HttpServlet,按需重寫 doGet/doPost/doPut/doDelete,必要時重寫 init/destroy 管理資源。Servlet 3.0+ 更推薦使用 @WebServlet 註解替代 web.xml。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved