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

Servlet API 核心接口深度解析:ServletConfig、ServletContext 與生命周期方法

     編輯:Java 程式設計入門

Servlet 規範是 Java Web 開發的基石。理解 ServletConfig、ServletContext、GenericServlet、HttpServlet 之間的關係,以及 init()、service()、destroy() 的調用鏈路,對排查部署問題、設計濾鏡器鏈、實現框架擴展至關重要。

一、核心接口職責劃分

接口/類職責典型用法
javax.servlet.Servlet核心契約:定義 init/config/service/destroy/getServletInfo所有 Servlet 必須實現(直接或間接)
GenericServlet协议无关抽象基类,实现 ServletConfig、Serializable,提供无参 init() 模板方法自定义非 HTTP 协议 Servlet(如 FTP、SMTP)
HttpServletHTTP 協議專用,重寫 service() 分發 doGet/doPost 等99% Web 業務 Servlet 直接繼承
ServletConfig單個 Servlet 的初始化配置(、servlet-name)this.getInitParameter("key")
ServletContext整個 Web 應用(一個 Context)的全局上下文,跨 Servlet 共享application 域屬性、資源訪問、初始化參數

二、web.xml 雙層初始化參數機制

1. Servlet 級 (私有)

<servlet>
  <servlet-name>MyServlet</servlet-name>
  <servlet-class>com.demo.MyServlet</servlet-class>
  <init-param>
    <param-name>dbUrl</param-name>
    <param-value>jdbc:mysql://localhost:3306/mydb</param-value>
  </init-param>
</servlet>

獲取:this.getInitParameter("dbUrl") 或 getServletConfig().getInitParameter("dbUrl")。

2. Context 級 (全局共享)

<context-param>
  <param-name>appName</param-name>
  <param-value>MyWebApp</param-value>
</context-param>

獲取:getServletContext().getInitParameter("appName"),任意 Servlet/Filter/Listener 均可訪問。

三、生命周期方法調用鏈路圖解

容器啟動
   │
   ├─> 實例化 Servlet(無參構造器)
   │
   ├─> init(ServletConfig config)  【GenericServlet 實現】
   │       │
   │       ├─ 保存 config 引用
   │       └─> init()  【無參,供子類重寫,此處執行業務初始化】
   │
   ├─> 就緒服務請求
   │       │
   │       ├─> service(ServletRequest, ServletResponse) 【GenericServlet 抽象方法】
   │       │       │
   │       │       └─> HttpServlet.service() 【分發 doGet/doPost/doPut...】
   │       │
   │       └─> 多線程並發調用 service()
   │
   └─> 容器關閉/卸載
           │
           └─> destroy() 【釋放資源:關閉連接池、線程池、臨時文件】

四、HttpServlet 中的關鍵點

  1. 不要重寫 service() 除非極其必要。 重寫後 doGet/doPost 失效,需自行分發 HTTP 方法。
  2. init() 拋異常 → Servlet 標記為不可用,後續請求直接 500/404,不會進入 service()。
  3. 線程安全: Servlet 實例單例,service() 多線程共享實例字段 → 嚴禁在 Servlet 類中定義非線程安全的實例變量(如 SimpleDateFormat、ArrayList、JDBC Connection)。請使用局部變量或 ThreadLocal。

五、ServletContext 實戰高頻 API

// 1. 域屬性共享(Application 範圍)
context.setAttribute("onlineCount", 100);
context.getAttribute("onlineCount");

// 2. 訪問 WEB-INF 下資源(不依賴絕對路徑)
InputStream is = context.getResourceAsStream("/WEB-INF/config.properties");
Properties p = new Properties();
p.load(is);

// 3. 獲取真實物理路徑(慎用,容器遷移可能失效)
String realPath = context.getRealPath("/uploads");

// 4. 請求轉發/包含(服務端跳轉)
context.getRequestDispatcher("/target.jsp").forward(req, resp);

// 5. 獲取 MIME 類型
String mime = context.getMimeType("image.png"); // image/png

// 6. 容器版本信息
String serverInfo = context.getServerInfo(); // Apache Tomcat/9.0.85

六、Servlet 3.0+ 註解式配置(零 web.xml)

@WebServlet(
    urlPatterns = "/api/user/*",
    initParams = {
        @WebInitParam(name = "pageSize", value = "20"),
        @WebInitParam(name = "cacheEnable", value = "true")
    },
    loadOnStartup = 1,
    asyncSupported = true
)
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String pageSize = getInitParameter("pageSize"); // 直接獲取
        // ...
    }
}

架構建議: 現代 Spring Boot 項目中,極少直接編寫 Servlet。但理解其生命周期與上下文機制,有助於掌握 DispatcherServlet、FilterRegistrationBean、ServletListenerRegistrationBean 等自動配置原理,以及排查「Bean 未注入」、「Filter 不生效」等容器級問題。

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