轉(zhuǎn)載自:https://d.we90s.net/article/23
三者區(qū)別
Filter(過(guò)濾器)
過(guò)濾器是服務(wù)端的一個(gè)組件,是基于servlet實(shí)現(xiàn)從客戶端訪問(wèn)服務(wù)端web資源的一種攔截機(jī)制,對(duì)請(qǐng)求request和響應(yīng)response都進(jìn)行過(guò)濾,依賴于serverlet容器,使用時(shí),實(shí)現(xiàn)Filter接口,在web.xml里配置對(duì)應(yīng)的class還有mapping-url。

//@Component
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("過(guò)濾器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("過(guò)濾器執(zhí)行了");
long start2 = System.currentTimeMillis();
filterChain.doFilter(servletRequest, servletResponse);
long time = System.currentTimeMillis() - start2;
System.out.println("過(guò)濾器執(zhí)行的時(shí)間是 :" + time);
System.out.println("過(guò)濾器執(zhí)行結(jié)束");
}
@Override
public void destroy() {
System.out.println("過(guò)濾器銷毀了");
}
}
interceptor(攔截器)
攔截器,顧名思義,它的作用就是攔截,這個(gè)要和過(guò)濾器區(qū)分開(kāi),過(guò)濾器依賴serverlet容器,獲取request和response處理,是基于函數(shù)回調(diào)(框架本身調(diào)用的,它會(huì)遍歷所有注冊(cè)的過(guò)濾器,并且一一調(diào)用doFilter()),簡(jiǎn)單說(shuō)就是“去取你想取的”。攔截器是通過(guò)Java反射機(jī)制來(lái)攔截web請(qǐng)求,是“拒你想拒絕的”,它只攔截web請(qǐng)求,但不攔截靜態(tài)資源。
攔截器,在AOP中用于在某個(gè)方法或字段被訪問(wèn)之前,進(jìn)行攔截,然后在之前或之后加入某些操作。攔截是AOP的一種實(shí)現(xiàn)策略。
@Component
public class TimeInterceptor implements HandlerInterceptor {
// 在controller調(diào)用之前調(diào)用,通過(guò)返回true或者false決定是否進(jìn)入Controller層
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("preHandle");
System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
System.out.println(((HandlerMethod)handler).getMethod().getName());
request.setAttribute("startTime", new Date().getTime());
return true;
}
// 在請(qǐng)求進(jìn)入控制層之后調(diào)用,但是在處理請(qǐng)求拋出異常時(shí)不會(huì)調(diào)用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long start = (Long)request.getAttribute("startTime");
System.out.println("time interceptor 耗時(shí):"+ (new Date().getTime() - start));
}
// 在請(qǐng)求處理完成之后,也就是在DispatherServlet渲染了視圖之后執(zhí)行,也就是說(shuō)這個(gè)方法必定是執(zhí)行,包含異常信息,它的主要作用就是清理資源
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion");
Long start = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗時(shí):"+ (new Date().getTime() - start));
System.out.println("ex is "+ex);
}
}

Aspect(切片)
相比過(guò)濾器,攔截器能夠知道用戶發(fā)出的請(qǐng)求最終被哪個(gè)控制器處理,但是攔截器還有一個(gè)明顯的不足,即不能夠獲取request的參數(shù)以及控制器處理之后的response。(注意 ,我曾經(jīng)試過(guò),獲得被攔截方法的一些參數(shù),但是通過(guò)methodParaters無(wú)法獲得,后來(lái)只能通過(guò)request.getParameter(..)來(lái)獲?。┧跃陀辛饲衅挠梦渲亓恕?/p>
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.wtzhou.security.controller.UserController.*(..))")
// @After("")
// @Before("")
// @AfterThrowing()
// @AfterReturning()
public Object handlerControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
out.println("請(qǐng)求參數(shù)為:"+arg);
}
out.println("TimeAspect 切片開(kāi)始執(zhí)行");
long start = currentTimeMillis();
Object proceed = proceedingJoinPoint.proceed();
out.println("切片執(zhí)行耗時(shí):" + (currentTimeMillis() - start));
out.println("切片執(zhí)行結(jié)束!");
return proceed;
}
}
總結(jié)
【Filter與Interceptor的區(qū)別】
- filter基于filter接口中的doFilter回調(diào)函數(shù),interceptor則基于Java本身的反射機(jī)制;
- filter是依賴于servlet容器的,沒(méi)有servlet容器就無(wú)法回調(diào)doFilter方法,而interceptor與servlet無(wú)關(guān);
- filter的過(guò)濾范圍比interceptor大,filter除了過(guò)濾請(qǐng)求外通過(guò)通配符可以保護(hù)頁(yè)面、圖片、文件等,而interceptor只能過(guò)濾請(qǐng)求,只對(duì)action起作用,在action之前開(kāi)始,在action完成后結(jié)束(如被攔截,不執(zhí)行action);
- 在action的生命周期中,攔截器可以被多次調(diào)用,而過(guò)濾器只能在容器初始化時(shí)被調(diào)用一次。
【Interceptor 與spring AOP的區(qū)別】
- spring Interceptor也是一種aop思想,我們這里面的spring AOP主要是講aop應(yīng)用,interceptor 的使用場(chǎng)合比aop小很多,顧名思義,它是攔截一些action請(qǐng)求,但是比aop使用起來(lái)簡(jiǎn)便;
- 程序執(zhí)行的順序是先進(jìn)過(guò)濾器,再進(jìn)攔截器,最后進(jìn)切面;
- Interceptor可以阻止代碼執(zhí)行下去,當(dāng)preHandle返回false,那么這個(gè)請(qǐng)求就到此結(jié)束,真正的被攔截了,但是aop不能,它只是單純的切入添加操作;