攔截器與過濾器的區別 :
1. 攔截器是基於java的反射機制的。而過濾器是基於函數回調,Spring框架支持,可Spring中的數據源、事務管理等。
2. 使用范圍不同:攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
3. 攔截器只能對action請求起作用,針對類,攔截器可以多次被調用。
而過濾器則可以對幾乎所有的請求起作用,在容器啟動是初始化調用init方法,以后每個請求都調用doFilter()。作用范圍包含攔截器。
4. 攔截器可以訪問action上下文、值棧里的對象(即方法中的對象),而過濾器不能訪問。
5. 攔截器可以在方法前后,異常前請求后各調用一次后等調用,
而過濾器只能在請求前和。
6.深度不同:Filter在Servlet前后作用,Interceptor在方法的前后作用,異常拋出前后,具有更大的彈性。所以優先使用攔截器。
7.filter配置在web.xml中 interceptor配置在spring配置文件中
攔截器是AOP的一種實現策略,可實現依賴注入。
因此它的完整加載順序就是 :ServletContext -> context-param -> listener-> filter -> servlet
開發一個監聽器,實現 ServletContextListener 接口
不過有一點需要注意的是: spring容器的加載要在servlet之后,因此在有些過濾器當中需要提前用到spring bean的時候,就需要改成 Listener 的方式
org.springframework.web.context.ContextLoaderListener
ContextLoaderListener的作用就是啟動Web容器時,自動裝配ApplicationContext的配置信息。因為它實現了ServletContextListener這個接口,在web.xml配置這個監聽器,啟動容器時,就會默認執行它實現的方法。
容器監聽器ServletContextListener 是 ServletContext 的監聽者,如果 ServletContext 發生變化,如服務器啟動時 ServletContext 被創建,服務器關閉時 ServletContext 將要被銷毀。
要求每次訪問action都無需加載新的xml文件,利用框架的監聽器實現只在服務器啟動時加載一次xml配置,用於提高性能。
監聽器內如何引用對象:
1、直接加載“bean.xml”文件,bean被實例化了兩次,不可取。
2、從servletcontext中獲取。解析:(前一步在contextLoaderListener,后兩步在contextLoader中)
1
2
3
4
5
6
7
8
9
10
11
|
/**
* Initialize the root web application context.
*/
public
void
contextInitialized(ServletContextEvent event) {
this
.contextLoader = createContextLoader();
//獲取spring配置文件,創建webapplicationcontext
this
.contextLoader.initWebApplicationContext(event.getServletContext());
}
protected
ContextLoader createContextLoader() {
return
new
ContextLoader();
}
|
1
2
3
4
|
this
.context = createWebApplicationContext(servletContext, parent);
servletContext.setAttribute(
//創建好的spring context交給application內置對象,使監聽器,過濾器,攔截器都可以訪問。
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
this
.context);
|
1
2
3
4
5
6
7
8
9
|
//獲取spring配置文件路徑
String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
if
(configLocation !=
null
) {
wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
//加載spring文件
customizeContext(servletContext, wac);
wac.refresh();
return
wac;
|
1
2
3
4
5
6
|
// 解決方案二,項目在啟動時,把Spring配置文件通過Spring的監聽器加載,存儲到ServletContext中,我們只要在ServletContext中獲取即可。
//方法傳入對象ServletContextEvent event
ApplicationContext context = (ApplicationContext) event.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
//工具類WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
productService = (ProductService) context.getBean(
"productService"
);
System.out.println(productService);
|
開發一個過濾器必須實現java定義好的javax.servlet.Filter接口: (Servlet的特性)
這一接口含有三個過濾器必須執行的方法:
doFilter(ServletRequest, ServletResponse, FilterChain):這是一個完成過濾行為的方法。這同樣是上游過濾器調用的方法。
引入的FilterChain對象提供了后續過濾器所要調用的信息。如果該過濾器是過濾器鏈中的最后一個過濾器,則將請求交給被請求資源。也可以直接給客戶端返回響應信息。
init(FilterConfig):由Web容器來調用完成過濾器的初始化工作。它保證了在第一次doFilter()調用前由容器調用。您能獲取在 web.xml 文件中指定的初始化參數。
destroy():由Web容器來調用來釋放資源,doFilter()中的所有活動都被該實例終止后,調用該方法。
開發一個攔截器必須實現HandlerInterceptor接口:
preHandle():這個方法在handler執行之前被調用,在該方法中對用戶請求 request 進行處理。如果程序員決定該攔截器對 請求進行攔截處理后還要調用其他的攔截器,或者是業務處理器去進行處理,則返回true;如果程序員決定不需要再調用其他的組件去處理請求,則返回false。
postHandle():這個方法在handler執行后,但是DispatcherServlet 向客戶端返回響應前被調用,在該方法中對用戶請求request進行處理。
afterCompletion():這個方法在 DispatcherServlet 完全處理完請求后被調用,可以在該方法中進行一些資源清理的操作。view渲染完成、dispatcherServlet返回之前執行。