攔截器與過濾器的區別 :
1. 攔截器是基於java的反射機制的。而過濾器是基於函數回調,Spring框架支持,可Spring中的數據源、事務管理等。
2. 使用範圍不一樣:攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
3. 攔截器只能對action請求起做用,針對類,攔截器能夠屢次被調用。java
而過濾器則能夠對幾乎全部的請求起做用,在容器啓動是初始化調用init方法,之後每一個請求都調用doFilter()。做用範圍包含攔截器。
4. 攔截器能夠訪問action上下文、值棧裏的對象(即方法中的對象),而過濾器不能訪問。
5. 攔截器能夠在方法先後,異常前請求後各調用一次後等調用,程序員
而過濾器只能在請求前和。web
6.深度不一樣:Filter在Servlet先後做用,Interceptor在方法的先後做用,異常拋出先後,具備更大的彈性。因此優先使用攔截器。spring
7.filter配置在web.xml中 interceptor配置在spring配置文件中 服務器
攔截器是AOP的一種實現策略,可實現依賴注入。app
所以它的完整加載順序就是 :ServletContext -> context-param -> listener-> filter -> servlet框架
開發一個監聽器,實現 ServletContextListener 接口webapp
不過有一點須要注意的是: spring容器的加載要在servlet以後,所以在有些過濾器當中須要提早用到spring bean的時候,就須要改爲 Listener 的方式函數
org.springframework.web.context.ContextLoaderListener工具
ContextLoaderListener的做用就是啓動Web容器時,自動裝配ApplicationContext的配置信息。由於它實現了ServletContextListener這個接口,在web.xml配置這個監聽器,啓動容器時,就會默認執行它實現的方法。
容器監聽器ServletContextListener 是 ServletContext 的監聽者,若是 ServletContext 發生變化,如服務器啓動時 ServletContext 被建立,服務器關閉時 ServletContext 將要被銷燬。
要求每次訪問action都無需加載新的xml文件,利用框架的監聽器實現只在服務器啓動時加載一次xml配置,用於提升性能。
監聽器內如何引用對象:
一、直接加載「bean.xml」文件,bean被實例化了兩次,不可取。
二、從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返回以前執行。