web.xml 定義兩種初始化參數,作用域、生命週期、存取方式截然不同。本文透過配置範例與程式碼,釐清 context-param(應用層)與 init-param(Servlet 層)的核心差異。
| 維度 | context-param | init-param |
|---|---|---|
| 作用域 | 整個 Web 應用 (ServletContext) | 單一 Servlet (ServletConfig) |
| 配置位置 | <web-app> 直屬子元素 | <servlet> 內部 |
| 生命週期 | 應用啟動~銷毀 | Servlet 初始化~銷毀 |
| 可見性 | 所有 Servlet、Filter、Listener | 僅對應 Servlet |
| 存取 API | ServletContext.getInitParameter() | ServletConfig.getInitParameter() |
<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<!-- 應用層參數:資料庫連線池、全域功能開關 -->
<context-param>
<param-name>db.pool.size</param-name>
<param-value>20</param-value>
</context-param>
<context-param>
<param-name>feature.export.enabled</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>ReportServlet</servlet-name>
<servlet-class>com.example.ReportServlet</servlet-class>
<!-- Servlet 專屬參數:報表模板路徑、分頁大小 -->
<init-param>
<param-name>template.path</param-name>
<param-value>/WEB-INF/templates/report.jrxml</param-value>
</init-param>
<init-param>
<param-name>page.size</param-name>
<param-value>50</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ReportServlet</servlet-name>
<url-pattern>/report</url-pattern>
</servlet-mapping>
</web-app>
public class ReportServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// 1. 讀取 Servlet 專屬參數 (init-param)
String template = config.getInitParameter("template.path");
int pageSize = Integer.parseInt(config.getInitParameter("page.size"));
// 2. 讀取應用層參數
ServletContext ctx = getServletContext();
int poolSize = Integer.parseInt(ctx.getInitParameter("db.pool.size"));
boolean exportEnabled = Boolean.parseBoolean(
ctx.getInitParameter("feature.export.enabled"));
System.out.printf("Template: %s, PageSize: %d, Pool: %d, Export: %b%n",
template, pageSize, poolSize, exportEnabled);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// doGet 也可透過 getServletContext() 讀取 context-param
String pool = getServletContext().getInitParameter("db.pool.size");
resp.getWriter().write("DB Pool: " + pool);
}
}
init-param 僅在 init() 可用?錯誤迷思。ServletConfig 實例隨 Servlet 生命週期存在,doGet/doPost 同樣可呼叫 getServletConfig().getInitParameter()。但慣例在 init() 讀取並快取為欄位,避免重複查找。
若 context-param 與 init-param 同名,互不干擾,分別透過 ServletContext / ServletConfig 存取。
@Value / @ConfigurationProperties@Component
public class ReportService {
@Value("${db.pool.size:10}") // 對應 context-param 或 application.yml
private int poolSize;
@Value("${template.path}") // 對應 init-param 或配置檔
private String templatePath;
}
Spring 容器整合 ServletContextInitParameter,可無縫讀取 web.xml 參數,建議新專案採用配置檔 (application.yml) 統一管理。
ServletContext / ServletConfigapplication.yml,搭配 Spring @Value