面試官:談?wù)勥^濾器和攔截器的區(qū)別?
點擊關(guān)注上方“Stephen”,
設(shè)為“置頂或星標(biāo)”,第一時間送達干貨
來源:blog.csdn.net/qq_42924666/article/details/109563400
一、攔截器和過濾器的區(qū)別 二、攔截器和過濾器的代碼實現(xiàn) 三、總結(jié) 1、什么是Filter及其作用介紹 2、Filter API介紹 3、Filter鏈與Filter生命周期 四、攔截器 五、過濾器和攔截器的區(qū)別
一、攔截器和過濾器的區(qū)別
1、攔截器(Interceptor)只對action請求起作用 即對外訪問路徑
而過濾器(Filter)則可以對幾乎所有的請求都能起作用 包括css js等資源文件
2、攔截器(Interceptor)是在Servlet和Controller控制器之間執(zhí)行
而過濾器(Filter)是在請求進入Tomcat容器之后 但是在請求進入Servlet之前執(zhí)行
web.xml加載順序:context- param -> listener -> filter -> servlet
在請求結(jié)束返回時也是一樣 是在Servlet處理完之后返回給前端之間執(zhí)行

二、攔截器和過濾器的代碼實現(xiàn)
1、攔截器
首先需要一個攔截器類 并且這個類要實現(xiàn)HandlerInterceptor接口
這個接口里面有三個方法:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
// 在攔截點(Controller方法處理之前)執(zhí)行攔截 若返回的是false則中斷執(zhí)行 反之亦然
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
{
// 在處理過程中(Controller方法處理完之后 DispatcherServlet進行視圖的渲染之前)執(zhí)行攔截
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
// 在DispatcherServlet進行視圖的渲染后 返回前進行攔截
}
稍微寫一下方法:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
// 在Controller方法處理之前執(zhí)行攔截 若返回的是false則中斷執(zhí)行 反之亦然
// 判斷當(dāng)前的User是否為空 若不為空則不攔截
if (request.getSession().getAttribute("USERINFO")!=null)
{
return true;
}
// 進行攔截 返回登錄界面
response.sendRedirect(request.getContextPath()+"/user/doLogin.do");
return false;
}
然后需要去SpringMVC的配置文件中配置攔截器:
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 攔截所有的mvc控制器(Controller) -->
<mvc:mapping path="/**"/>
<!-- 放行機制 指定對某個頁面不進行攔截 -->
<!-- 攔截器只對action起作用 因此填入的不是頁面路徑 而是方法 -->
<mvc:exclude-mapping path="/user/doLogin.do"/>
<!-- 指定使用哪個攔截器 -->
<bean class="net.zjitc.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
如此 當(dāng)訪問的請求不為/user/doLogin.do會被攔截然后重定向到/user/doLogin.do
但是訪問其它的頁面不會被攔截
想要讓頁面也被攔截?你需要過濾器!
2、過濾器
同理 需要一個過濾器類 然后實現(xiàn)javax.servlet.Filter接口
注意Filter的路徑別導(dǎo)錯了 因為有很多同名接口
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
// 過濾器初始化
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
}
@Override
public void destroy()
{
// 過濾器銷毀
}
}
稍微寫一下方法:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
// ServletRequest是一個接口 而HttpServletRequest是接口的實現(xiàn)
// 但有些方法是HttpServletRequest獨有的 例如getSession()
// HttpServletRequest接口繼承自ServletRequest接口 增加了和Http相關(guān)的方法
// 但是我們可以強制轉(zhuǎn)換
HttpServletRequest request=(HttpServletRequest)servletRequest;
HttpServletResponse response=(HttpServletResponse)servletResponse;
// 若用戶沒有登錄
if (request.getSession().getAttribute("USERINFO")==null && request.getRequestURI().indexOf("/user/doLogin.do")==-1)
{
response.sendRedirect(request.getContextPath()+"/user/doLogin.do");
}
// 若用戶已經(jīng)登錄 則繼續(xù)下一個請求(繼續(xù)訪問)
filterChain.doFilter(request,response);
}
然后需去web.xml中配置過濾器:
<!-- 配置自定義的Filter 實現(xiàn)登錄控制 -->
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>net.zjitc.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<!-- 攔截所有的頁面 /斜杠代表在webapp目錄下 -->
<url-pattern>/pages/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/img/*</url-pattern>
<url-pattern>/failer.jsp</url-pattern>
</filter-mapping>
三、總結(jié)
攔截器和過濾器其實都是AOP編程思想的實現(xiàn)
都可以體現(xiàn)例如權(quán)限的檢查 日志的記錄等功能
但是有不同之處:
1、使用范圍不同
攔截器既可以用在web層 又可以用在Application和Swing程序中 而filter是Servlet規(guī)范規(guī)定的 只能用于web程序中
2、規(guī)范不同
攔截器是在Spring容器內(nèi)的 是Spring框架支持的 而filter是Servlet規(guī)范規(guī)定的 是Servlet容器支持的
1、什么是Filter及其作用介紹
(1)概念
Servlet規(guī)范中三個技術(shù) Servlet Listener Filter(順序為L F S)
Filter是sun公司中servlet2.3后增加的一個新功能,在javaEE中定義了一個接口 javax.servlet.Filter來描述過濾器
(2)作用
通過Filter可以攔截訪問web資源的請求與響應(yīng)操作。
WEB開發(fā)人員通過Filter技術(shù),對web服務(wù)器管理的所有web資源:例如Jsp, Servlet, 靜態(tài)圖片文件或靜態(tài) html 文件等進行攔截,從而實現(xiàn)一些特殊的功能。例如實現(xiàn)URL級別的權(quán)限訪問控制、過濾敏感詞匯、壓縮響應(yīng)信息等一些高級功能。
(3)舉例
在java web中,針對傳入的request,或response提前過濾掉一些信息,或者提前設(shè)置一些參數(shù),然后再傳入servlet進行業(yè)務(wù)邏輯,比如過濾掉非法url(不是login.do的地址請求,如果用戶沒有登陸都過濾掉),或者在傳入servlet或者 struts的action前統(tǒng)一設(shè)置字符集,或者去除掉一些非法字符。
2、Filter API介紹
Filter是javax.servlet包下的一個接口主要有以下三個方法
destory()
doFilter(ServletRequest request,ServletResponse response,FilterCjain chain)
init(FilterConfig filterConfig)
3、Filter鏈與Filter生命周期
(1)Filter鏈介紹
多個Filter對同一個資源進行了攔截,那么當(dāng)我們在開始的Filter中執(zhí)行chain.doFilter(request,response)時,是訪問下一下Filter,直到最后一個Filter執(zhí)行時,它后面沒有了Filter,才會訪問web資源。
(2)關(guān)于多個FIlter的訪問順序問題
如果有多個Filter形成了Filter鏈,那么它們的執(zhí)行順序是怎樣確定的?
它們的執(zhí)行順序取決于在web.xml文件中配置的先后順序。
(3)Filter生命周期
當(dāng)服務(wù)器啟動,會創(chuàng)建Filter對象,并調(diào)用init方法,只調(diào)用一次. 當(dāng)訪問資源,路徑與Filter的攔截路徑匹配,會執(zhí)行Filter中的 doFilter方法,這個方法是真正攔截操作的方法.當(dāng)服務(wù)器關(guān)閉時,會調(diào)用Filter的 destroy方法來進行銷毀操作過濾器是JavaEE標(biāo)準(zhǔn),采用函數(shù)回調(diào)的方式進行。是在請求進入容器之后,還未進入Servlet之前進行預(yù)處理,并且在請求結(jié)束返回給前端這之間進行后期處理。
四、攔截器
攔截器是spring容器的,是spring支持的
java里的攔截器是動態(tài)攔截Action調(diào)用的對象。它提供了一種機制可以使開發(fā)者可以定義在一個action執(zhí)行的前后執(zhí)行的代碼,也可以在一個action執(zhí)行前阻止其執(zhí)行,同時也提供了一種可以提取action中可重用部分的方式。
在面向切面編程AOP(Aspect-Oriented Programming)中攔截器用于在某個方法或字段被訪問之前,進行攔截,然后在之前或之后加入某些操作。
比如動態(tài)代理就是攔截器的簡單實現(xiàn),在你調(diào)用方法前打印出字符串(或者做其它業(yè)務(wù)邏輯的操作),也可以在你調(diào)用方法后打印出字符串,甚至在你拋出異常的時候做業(yè)務(wù)邏輯的操作。
五、過濾器和攔截器的區(qū)別
①攔截器是基于java的反射機制的,而過濾器是基于函數(shù)回調(diào)。 ②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。 ③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。 ④攔截器可以訪問action上下文、值棧里的對象,而過濾器不能訪問。 ⑤在action的生命周期中,攔截器可以多次被調(diào)用,而過濾器只能在容器初始化時被調(diào)用一次。 ⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器里注入一個service,可以調(diào)用業(yè)務(wù)邏輯。攔截器可以獲取ioc中的service bean實現(xiàn)業(yè)務(wù)邏輯。
回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當(dāng)這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應(yīng)。
Spring MVC中每個控制器中可以定義多個請求處理方法,我們把這種請求處理方法簡稱為Action

END
關(guān)注 Stephen,一起學(xué)習(xí),一起成長。
點“在看”支持下吧
點 閱讀原文 可優(yōu)惠充值話費,流量,視頻會員等。
