當應用需要在伺服器啟動階段完成資料預載入、快取預熱、定時任務排程、連線池初始化等工作時,load-on-startup 配合 Servlet init() 方法是最輕量、標準的解決方案。
web.xml 中 <load-on-startup> 元素指定 Servlet 載入優先級(整數,越小越早載入,0 或正整數均表示啟動時載入)。init(ServletConfig)。init() 僅執行一次,適合一次性初始化邏輯。
public class AutoRunServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void init() throws ServletException {
System.out.println(">> 伺服器啟動,執行初始化邏輯 <<");
// 讀取初始化參數
String paramA = getInitParameter("a");
System.out.println("參數 a = " + paramA);
Enumeration paramNames = getInitParameterNames();
while (paramNames.hasMoreElements()) {
String name = paramNames.nextElement();
System.out.println("初始化參數: " + name + " = " + getInitParameter(name));
}
// 實際業務:載入配置、預熱快取、啟動排程器等
// DataCache.preload();
// QuartzScheduler.start();
}
}
<servlet>
<servlet-name>AutoRunServlet</servlet-name>
<servlet-class>com.example.AutoRunServlet</servlet-class>
<load-on-startup>0</load-on-startup>
<init-param>
<param-name>a</param-name>
<param-value>啟動參數值1</param-value>
</init-param>
<init-param>
<param-name>b</param-name>
<param-value>啟動參數值2</param-value>
</init-param>
</servlet>
啟動 Tomcat,控制台輸出:
>> 伺服器啟動,執行初始化邏輯 << 參數 a = 啟動參數值1 初始化參數: a = 啟動參數值1 初始化參數: b = 啟動參數值2
錯誤現象:
jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
原因:專案依賴包含 servlet-api.jar(如 servlet-api-2.5-6.1.14.jar),而 Tomcat lib/ 目錄下已提供 servlet-api.jar,導致同一類別由不同 ClassLoader 載入,違反 Servlet 規範 9.7.2 節。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
@WebServlet(
name = "AutoRunServlet",
urlPatterns = {"/auto-run"}, // 雖不處理請求,但規範要求
loadOnStartup = 0,
initParams = {
@WebInitParam(name = "a", value = "啟動參數值1"),
@WebInitParam(name = "b", value = "啟動參數值2")
}
)
public class AutoRunServlet extends HttpServlet {
@Override
public void init() throws ServletException {
// 同上
}
}
無需 web.xml,容器掃描註解自動註冊。
| 適用 | 不適用 |
|---|---|
| 配置載入、快取預熱 | 長時間運行的後台任務(用 ScheduledExecutorService/Quartz) |
| 連線池/資料源初始化 | 需用戶觸發的業務邏輯 |
| 指標註冊、健康檢查準備 | 依賴其他未就緒服務的初始化(需延遲或重試) |
| 單例服務啟動 | 高併發下的延遲初始化(用 Double-Check Locking/Holder 模式) |
load-on-startup + init() 是 Java EE 標準的「啟動即執行」機制,零依賴、零框架、容器原生支援。記住:排除專案中的 servlet-api.jar 是避免啟動報錯的關鍵一步。