| 特性 | 攔截器 | 過濾器 | 監聽器 |
|---|---|---|---|
| 核心機制 | AOP、動態代理、反射 | 函數回調、Servlet 標準 | 觀察者模式、Servlet 生命週期事件 |
| 依賴容器 | 否(Spring 管理) | 是(Servlet 容器) | 是(Servlet 容器) |
| 作用範圍 | 僅 Controller/Action | 所有請求(含靜態資源) | 應用級事件 |
| 訪問上下文 | 可訪問 ActionContext、值棧 | 僅 ServletRequest/Response | ServletContext |
| 執行頻次 | 請求生命週期可多次 | 初始化一次,每請求一次 | 啟動/銷毀各一次 |
| 典型用途 | 權限檢查、日誌、事務、參數預處理 | 編碼統一、XSS 過濾、登入攔截、靜態資源快取 | Spring 初始化、資料庫連接池啟動、定時任務啟動 |
請求到達
→ 過濾器前置
→ 攔截器前置
→ Controller 處理
→ 攔截器後置
→ 過濾器後置
→ 響應返回
public class MyInterceptor extends MethodFilterInterceptor {
private String param; // struts.xml 注入
@Override protected String doIntercept(ActionInvocation inv) {
System.out.println("MyInterceptor-start: " + param);
String result = inv.invoke();
System.out.println("MyInterceptor-end");
return result;
}
}
struts.xml 定義攔截器棧:
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref> <!-- 必含,否則驗證失效 -->
</interceptor-stack>
<default-interceptor-ref name="myStack" />
@WebFilter("/jsp/*")
public class UserAccessFilter implements Filter {
@Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (request.getSession().getAttribute("user") == null
&& !request.getRequestURI().endsWith("login.jsp")) {
response.sendRedirect("login.jsp");
return;
}
chain.doFilter(req, res); // 放行
}
}
@WebListener
public class InitDataListener implements ServletContextListener {
private static ServletContext ctx;
@Override public void contextInitialized(ServletContextEvent sce) {
ctx = sce.getServletContext();
// 初始化緩存、資料源、排程器...
System.out.println("應用啟動完成");
}
public static ServletContext getServletContext() { return ctx; }
}
@Component + FilterRegistrationBean 註冊,或實作 Filter 並標註 @Order。HandlerInterceptor,在 WebMvcConfigurer.addInterceptors() 註冊。@EventListener(ApplicationReadyEvent.class) 替代傳統 ServletContextListener。三者分工明確:過濾器守大門、攔截器管業務、監聽器聽生命週期。Spring Boot 專案優先使用 Spring 原生機制,僅在需處理 Servlet 級別(如編碼、靜態資源)時使用過濾器。