A. 過濾器和SpringMVC的攔截器的區別
過濾器和攔截器的區別:
①攔截器是基於Java的反射機制的,而過濾器是基於函數回調。
②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。
⑤在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。
⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器里注入一個service,可以調用業務邏輯。
寫了點測試代碼,順便整理一下思路,搞清楚這幾者之間的順序:
1.過濾器是JavaEE標准,採用函數回調的方式進行。是在請求進入容器之後,還未進入Servlet之前進行預處理,並且在請求結束返回給前端這之間進行後期處理。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("before...");
chain.doFilter(request, response);
System.out.println("after...");
}
chain.doFilter(request, response);這個方法的調用作為分水嶺。事實上調用Servlet的doService()方法是在chain.doFilter(request, response);這個方法中進行的。
2.攔截器是被包裹在過濾器之中的。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
a.preHandle()這個方法是在過濾器的chain.doFilter(request, response)方法的前一步執行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之間執行。
b.preHandle()方法之後,在returnModelAndView之前進行,可以操控Controller的ModelAndView內容。
c.afterCompletion()方法是在過濾器返回給前端前一步執行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之間執行。
3.SpringMVC的機制是由同一個Servlet來分發請求給不同的Controller,其實這一步是在Servlet的service()方法中執行的。所以過濾器、攔截器、service()方法,dispatc()方法的執行順序應該是這樣的,大致畫了個圖:其實非常好測試,自己寫一個過濾器,一個攔截器,然後在這些方法中都加個斷點,一路F8下去就得出了結論。
B. java問題: 在過濾器filter中如何獲得spring容器里的對象
WebApplicationContext wac =
WebApplicationContextUtils.(getServletContext());
有WebApplicationContext 了對象了 spring託管的所有對象都可以拿到了。
當然不推薦這種方式,一般是注入的方式,特殊情況下(像你這種情況)這么用。
然後調用 wac.getBean(「beanid」);
C. spring過濾器和攔截器的區別
(1)過濾器:
依賴於servlet容器,是JavaEE標准,是在請求進入容器之後,還未進入Servlet之前進行預處理,並且在請求結束返回給前端這之間進行後期處理。在實現上基於函數回調,可以對幾乎所有請求進行過濾,但是缺點是一個過濾器實例只能在容器初始化時調用一次。使用過濾器的目的是用來做一些過濾操作,獲取我們想要獲取的數據,比如:在過濾器中修改字元編碼;在過濾器中修改HttpServletRequest的一些參數,包括:過濾低俗文字、危險字元等
關於過濾器的一些用法可以參考我寫過的這些文章:
繼承HttpServletRequestWrapper以實現在Filter中修改HttpServletRequest的參數:
在SpringMVC中使用過濾器(Filter)過濾容易引發XSS的危險字元:
(2)攔截器:
攔截器不依賴與servlet容器,依賴於web框架,在SpringMVC中就是依賴於SpringMVC框架。在實現上基於Java的反射機制,屬於面向切面編程(AOP)的一種運用。由於攔截器是基於web框架的調用,因此可以使用spring的依賴注入(DI)獲取IOC容器中的各個bean,進行一些業務操作,同時一個攔截器實例在一個controller生命周期之內可以多次調用。但是缺點是只能對controller請求進行攔截,對其他的一些比如直接訪問靜態資源的請求則沒辦法進行攔截處理,攔截器功在對請求許可權鑒定方面確實很有用處
D. springmvc過濾器和攔截器的區別
攔截器與過濾器的區別 :
1. 攔截器是基於java的反射機制的,而過濾器是基於函數回調。
2. 攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
3. 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
4. 攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。
5. 在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次
攔截器的代碼實現(以struts2為例):
1、在xml文件中如何定義攔截器
<interceptors>
<interceptor name="filterIPInterceptor"
class="com.xxxx.web.FilterIPActionInterceptor" />
<interceptor-stack name="filterIPStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="filterIPInterceptor" />
</interceptor-stack>
</interceptors>
2、怎麼遍別寫自定義攔截器
public class FilterIPActionInterceptor extends AbstractInterceptor
{
/** 日誌控制. */
private final Log log = LogFactory.getLog(getClass());
/**
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
E. 有過濾器的springmvc代碼怎麼用
不過實現的方式有以下幾類:
(1) 直接實現Filter,這一類過濾器只有CompositeFilter;
(2) 繼承抽象類GenericFilterBean,該類實現了javax.servlet.Filter,這一類的過濾器只有一個,即DelegatingFilterProxy;
(3) 繼承抽象類OncePerRequestFilter,該類為GenericFilterBean的直接子類,這一類過濾器包括CharacterEncodingFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter和ShallowEtagHeaderFilter;
(4) 繼承抽象類AbstractRequestLoggingFilter,該類為OncePerRequestFilter的直接子類,這一類過濾器包括CommonsRequestLoggingFilter、和。
過濾器放在容器結構的什麼位置?
過濾器放在web資源之前,可以在請求抵達它所應用的web資源(可以是一個Servlet、一個Jsp頁面,甚至是一個HTML頁面)之前截獲進入的請求,並且在它返回到客戶之前截獲輸出請求。Filter:用來攔截請求,處於客戶端與被請求資源之間,目的是重用代碼。Filter鏈,在web.xml中哪個先配置,哪個就先調用。在filter中也可以配置一些初始化參數。
Java中的Filter 並不是一個標準的Servlet ,它不能處理用戶請求,也不能對客戶端生成響應。 主要用於對HttpServletRequest 進行預處理,也可以對HttpServletResponse 進行後處理,是個典型的處理鏈。
Filter 有如下幾個種類:
l 用戶授權的Filter: Filter 負責檢查用戶請求,根據請求過濾用戶非法請求。
l 日誌Filter: 詳細記錄某些特殊的用戶請求。
l 負責解碼的Filter: 包括對非標准編碼的請求解碼。
l 能改變XML 內容的XSLTFilter 等。
Filter 有如下幾個用處 :
l 在HttpServletRequest 到達Servlet 之前,攔截客戶的HttpServletRequest 。
l 根據需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數據。
l 在HttpServletResponse 到達客戶端之前,攔截HttpServletResponse 。
l 根據需要檢查HttpServletResponse ,可以修改HttpServletResponse 頭和數據。
創建一個 Filter 只需兩個步驟
F. 在springmvc中使用過濾器chain.dofilter 出不去
如果走chain的話,通過chain.doFilter(request,response)這個方法會立即跳轉到被攔截的servlet並且執行完還要再返回filter.chain相當於一扇門,從這扇門出去再從這扇門回來.調用filter的方法就是在web.xml中配置,需要配置一個與你需要攔截的servlet相同的url-pattern.
<!-- 配置一個過濾器 -->
<filter>
<filter-name>suibianxie</filter-name>
<filter-class>com.etoak.filter.MyEncoding</filter-class>
<!-- 配置一個私有參數 -->
<init-param>
<param-name>mycode</param-name>
<param-value>gbk</param-value>
</init-param>
</filter>
<!-- 攔截的先後順序和mapping的順序有關 -->
<filter-mapping>
<filter-name>suibianxie</filter-name>
<!-- 注意這里和要攔截的servlet的url-pattern必須一致,等於是過濾器
搶在servlet之前攔截住了 -->
<url-pattern>/servlet/Test</url-pattern>
</filter-mapping>
<!-- 配置第二個過濾器 -->
<filter>
<filter-name>suibianxie2</filter-name>
<filter-class>com.etoak.filter.Naming</filter-class>
</filter>
<filter-mapping>
<filter-name>suibianxie2</filter-name>
<url-pattern>/servlet/Test</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.etoak.servlet.Test</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/servlet/Test</url-pattern>
</servlet-mapping>
G. spring過濾器和攔截器的區別
①攔截器是基於java的反射機制的,而過濾內器是基於函數回調。
②攔容截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。
⑤在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。
⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器里注入一個service,可以調用業務邏輯。
H. spring中怎麼實現過濾器和監聽器
1、延遲載入過濾器
Hibernate 允許對關聯對象、屬性進行延遲載入,但是必須保證延遲載入的操作限於同一個 Hibernate Session 范圍之內進行。如果 Service 層返回一個啟用了延遲載入功能的領域對象給 Web 層,當 Web 層訪問到那些需要延遲載入的數據時,由於載入領域對象的 Hibernate Session 已經關閉,這些導致延遲載入數據的訪問異常。
Spring 為此專門提供了一個 OpenSessionInViewFilter 過濾器,它的主要功能是使每個請求過程綁定一個 Hibernate Session,即使最初的事務已經完成了,也可以在 Web 層進行延遲載入的操作。
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
2、亂碼過濾器
對post亂碼的處理,如下
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter①Spring編輯過濾器
</filter-class>
<init-param>②編碼方式
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>③強制進行編碼轉換
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>②過濾器的匹配URL
<filter-name>encodingFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
3、請求跟蹤日誌過濾器
程度調試者可以詳細地查看到有哪些請求被調用,請求的參數是什麼,請求是否正確返回等信息,需要將log4j設為debug
org.springframework.web.filter.: 該過濾器將請求的 URI 記錄到 Common 日誌中
4、WebAppRootListener
可以將 Web 應用根目錄添加到系統參數中,對應的屬性名可以通過名為「webAppRootKey」的 Servlet 上下文參數指定,默認為「webapp.root」,配置如下
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>baobaotao.root</param-value>①Web應用根目錄以該屬性名添加到系統參數中
</context-param>
…
②負責將Web應用根目錄以webAppRootKey上下文參數指定的屬性名添加到系統參數中
<listener>
<listener-class>
org.springframework.web.util.WebAppRootListener
</listener-class>
</listener>
5、Log4jConfigListener監聽器
包括了 WebAppRootListener 的功能,也就是說,Log4jConfigListener 會自動完成將 Web 應用根目錄以 webAppRootKey 上下文參數指定的屬性名添加到系統參數中,在log4j.xml可以直接使用
6、Introspector 緩存清除監聽器
負責處理由 JavaBean Introspector 功能而引起的緩存泄露。IntrospectorCleanupListener 監聽器在 Web 應用關閉的時會負責清除 JavaBean Introspector 的緩存,在 web.xml 中注冊這個監聽器可以保證在 Web 應用關閉的時候釋放與其相關的 ClassLoader 的緩存和類引用。
I. springmvc返回json數據 如何在filter中獲取的返回參數
filter在你調用/noaccess介面之前執行了,當然沒有retMsg了
J. SpringMVC的攔截器和過濾器的區別與聯系
1、首先要明確什麼是攔截器、什麼是過濾器
1.1 什麼是攔截器:
攔截器,在AOP(Aspect-Oriented Programming)中用於在某個方法或欄位被訪問之前,進行攔截然後在之前或之後加入某些操作。攔截是AOP的一種實現策略。
在Webwork的中文文檔的解釋為——攔截器是動態攔截Action調用的對象。它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的代碼,也可以在一個action執行前阻止其執行。同時也是提供了一種可以提取action中可重用的部分的方式。
談到攔截器,還有一個詞大家應該知道——攔截器鏈(Interceptor Chain,在Struts2中稱為攔截器棧 Interceptor Stack)。攔截器鏈就是將攔截器按一定的順序聯結成一條鏈。在訪問被攔截的方法或欄位時,攔截器鏈中的攔截器就會按其之前定義的順序被調用。
1.2. 攔截器的實現原理:
大部分時候,攔截器方法都是通過代理的方式來調用的。Struts2的攔截器實現相對簡單。當請求到達Struts2的ServletDispatcher時,Struts 2會查找配置文件,並根據其配置實例化相對的攔截器對象,然後串成一個列表(list),最後一個一個地調用列表中的攔截器。
1.3 什麼是過濾器
過濾器是一個程序,它先於與之相關的servlet或JSP頁面運行在伺服器上。過濾器可附加到一個或多個servlet或JSP頁面上,並且可以檢查進入這些資源的請求信息。在這之後,過濾器可以作如下的選擇:
①以常規的方式調用資源(即,調用servlet或JSP頁面)。
②利用修改過的請求信息調用資源。
③調用資源,但在發送響應到客戶機前對其進行修改。
④阻止該資源調用,代之以轉到其他的資源,返回一個特定的狀態代碼或生成替換輸出。
1.4 Servlet過濾器的基本原理
在Servlet作為過濾器使用時,它可以對客戶的請求進行處理。處理完成後,它會交給下一個過濾器處理,這樣,客戶的請求在過濾鏈里逐個處理,直到請求發送到目標為止。例如,某網站里有提交「修改的注冊信息」的網頁,當用戶填寫完修改信息並提交後,伺服器在進行處理時需要做兩項工作:判斷客戶端的會話是否有效;對提交的數據進行統一編碼。這兩項工作可以在由兩個過濾器組成的過濾鏈里進行處理。當過濾器處理成功後,把提交的數據發送到最終目標;如果過濾器處理不成功,將把視圖派發到指定的錯誤頁面。
2、攔截器與過濾器的區別 :
1. 攔截器是基於java的反射機制的,而過濾器是基於函數回調。
2. 攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
3. 攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
4. 攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。
5. 在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次
攔截器的代碼實現(以struts2為例):
1、在xml文件中如何定義攔截器
<interceptors>
<interceptor name="filterIPInterceptor"
class="com.xxxx.web.FilterIPActionInterceptor" />
<interceptor-stack name="filterIPStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="filterIPInterceptor" />
</interceptor-stack>
</interceptors>
2、怎麼遍別寫自定義攔截器
public class FilterIPActionInterceptor extends AbstractInterceptor
{
/** 日誌控制. */
private final Log log = LogFactory.getLog(getClass());
/**
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
@SuppressWarnings("unchecked")
public String intercept(ActionInvocation invocation) throws Exception
{
String result = null;
// 獲得當前方法名.
String methodName = invocation.getInvocationContext().getName();
String currIp = null;
try
{
if (invocation.getAction() instanceof PortletAction)
{
PortletAction action = (PortletAction) invocation.getAction();
currIp = action.getRequest().getRemoteAddr();
}
String ip = ApplicationResource.getHotValue("ALLOW_CACHE_IP");
if (StringUtils.isBlank(ip) || StringUtils.isBlank(currIp))
{
log.error("允許刷新的IP不存在或當前請求的IP非法.");
throw new NoAllowIPException();
}
else
{
String[] ips = ip.split(",");
boolean errorIp = true;
for (String s : ips)
{
if (s.equals(currIp))
errorIp = false;
}
// 判斷IP
if (errorIp)
throw new NoAllowIPException();
}
result = invocation.invoke();//調用被攔截的方法
}
catch (Exception e)
{
log.error("異常類名:" + invocation.getAction().getClass());
log.error("異常方法:" + methodName, e);
throw e;
}
return result;
}
}
3、怎麼編寫過濾器
1、在web.xml裡面配置自定義的攔截器
<filter>
<filter-name>Redirect Filter</filter-name>
<filter-class>com.xx.filter.RedirectFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Redirect Filter</filter-name>
<url-pattern>/xx/xx/*</url-pattern>
</filter-mapping>
2、如何編寫自定義的攔截器
public class RedirectFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// 獲取URL
Long startTime = null;
if (log.isDebugEnabled())
{
startTime = System.currentTimeMillis();
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
String url = httpRequest.getRequestURL().toString();
if (url == null || url.trim().length() == 0) {
return;
}
if (url.indexOf(luceneCreateMapping) != -1
|| url.indexOf(luceneSearchMapping) != -1) {
doFilterForxxx(request, response, url);
} else {
doxxxx(request, response, url);
}
if (log.isDebugEnabled())
{
long endTime = System.currentTimeMillis();
Thread currentThread = Thread.currentThread();
String threadName = currentThread.getName();
log.debug("[" + threadName + "]" + "< "
+ this.getClass().getName() + " " + url + " "
+ (endTime - startTime) + " ms");
}
// 激活下一個Filter
filterChain.doFilter(request, response);
}
}