Servlet 3.0 引入了強大的註解機制,讓開發者能夠告別繁瑣的 web.xml 配置,直接在 Java 類上聲明 Servlet、Filter 和 Listener。本文將系統整理 @WebServlet、@WebFilter、@WebListener、@WebInitParam 以及 @MultipartConfig 的核心用法與參數詳解,並附上完整代碼示例,助你快速掌握零配置開發。
以往需在 web.xml 中配置 <listener>,如今只需在實現類上標註 @WebListener 即可。該註解適用於實現以下任一接口的類:
ServletContextListenerServletContextAttributeListenerServletRequestListenerServletRequestAttributeListenerHttpSessionListenerHttpSessionAttributeListenerpackage com.example.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener("監聽 Session 創建與銷毀")
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Session 已創建:" + se.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("Session 已銷毀:" + se.getSession().getId());
}
}
屬性說明: value(或 description)用於提供監聽器的描述信息,非必填。
@WebFilter 直接標註在實現 javax.servlet.Filter 接口的類上,替代 <filter> 與 <filter-mapping> 配置。
| 參數 | 類型 | 說明 |
|---|---|---|
| filterName | String | 過濾器名稱,對應 <filter-name> |
| urlPatterns / value | String[] | URL 匹配模式,對應 <url-pattern>,兩者不可同時使用 |
| servletNames | String[] | 指定應用於哪些 Servlet(以 @WebServlet 的 name 或 <servlet-name> 為準) |
| dispatcherTypes | DispatcherType[] | 轉發模式:REQUEST、FORWARD、INCLUDE、ERROR、ASYNC |
| initParams | WebInitParam[] | 初始化參數,等同 <init-param> |
| asyncSupported | boolean | 是否支持異步操作 |
| description / displayName | String | 描述與顯示名 |
package com.example.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(
filterName = "authFilter",
urlPatterns = "/*",
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD},
initParams = {
@WebInitParam(name = "excludedPaths", value = "/login,/static/*"),
@WebInitParam(name = "realm", value = "admin")
}
)
public class AuthFilter implements Filter {
private String excludedPaths;
private String realm;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
excludedPaths = filterConfig.getInitParameter("excludedPaths");
realm = filterConfig.getInitParameter("realm");
System.out.println("AuthFilter 初始化完成,realm=" + realm);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
// 簡易放行邏輯演示
if (path.matches(excludedPaths.replace("*", ".*"))) {
chain.doFilter(request, response);
} else {
// 實際項目中應檢查 Session/Token
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// 釋放資源
}
}
@WebServlet 替代 <servlet> 與 <servlet-mapping>,支援多 URL 映射、啟動加載順序、初始化參數等。
| 參數 | 類型 | 說明 |
|---|---|---|
| name | String | Servlet 名稱,對應 <servlet-name> |
| urlPatterns / value | String[] | URL 映射路徑,支援精確匹配、通配符(/*、/api/*) |
| loadOnStartup | int | 啟動加載優先級,>=0 表示容器啟動時實例化 |
| initParams | WebInitParam[] | 初始化參數數組 |
| asyncSupported | boolean | 是否支援異步處理 |
| description / displayName | String | 描述與顯示名 |
package com.example.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet(
name = "userServlet",
urlPatterns = {"/user", "/user/*", "/api/user"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "defaultPageSize", value = "20"),
@WebInitParam(name = "maxPageSize", value = "100")
}
)
public class UserServlet extends HttpServlet {
private int defaultPageSize;
private int maxPageSize;
@Override
public void init() throws ServletException {
super.init();
defaultPageSize = Integer.parseInt(getInitParameter("defaultPageSize"));
maxPageSize = Integer.parseInt(getInitParameter("maxPageSize"));
System.out.println("UserServlet 已加載,默認分頁:" + defaultPageSize);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
HttpSession session = req.getSession();
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().write("{\"sessionId\":\"" + session.getId() + "\"}");
}
}
@WebInitParam 既可用於 @WebFilter 也可用於 @WebServlet,對應 web.xml 中的 <init-param>。主要屬性:
name(必填):參數名value(必填):參數值description:參數描述標註在 Servlet 上,聲明該 Servlet 處理 multipart/form-data 請求,啟用 Servlet 3.0 內建的文件上傳能力(request.getPart())。
| 屬性 | 類型 | 說明 |
|---|---|---|
| location | String | 臨時文件存儲路徑,未指定時使用容器默認臨時目錄 |
| maxFileSize | long | 單個文件最大尺寸(位元組),默認 -1(無限制) |
| maxRequestSize | long | 整個請求最大尺寸(含所有文件與表單字段),默認 -1 |
| fileSizeThreshold | int | 當文件大小超過此閾值(位元組)時,寫入磁盤而非內存,默認 0 |
package com.example.upload;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.nio.file.Paths;
@WebServlet("/upload")
@MultipartConfig(
location = "/tmp/uploads",
maxFileSize = 10 * 1024 * 1024, // 10MB
maxRequestSize = 50 * 1024 * 1024, // 50MB
fileSizeThreshold = 1024 * 1024 // 1MB 閾值
)
public class FileUploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Part filePart = req.getPart("file");
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
filePart.write(fileName); // 寫入 @MultipartConfig.location 目錄
resp.getWriter().write("上傳成功:" + fileName);
}
}
Servlet 3.0 註解極大簡化了 Web 應用配置,實現了「約定優於配置」。掌握 @WebServlet、@WebFilter、@WebListener 三大核心註解及其參數,配合 @WebInitParam 與 @MultipartConfig,即可覆蓋絕大多數 Web 組件聲明場景。建議在新項目中全面採用註解方式,僅在需動態註冊或兼容舊版容器時才回退到 web.xml。