過濾器(filter)/攔截器(Interceptor)/切片(Aspect)的區(qū)別

Restful API 的攔截

在某些情況下愉镰,會(huì)有需求對(duì)api攔截做一些統(tǒng)一的業(yè)務(wù)處理氢哮。簡(jiǎn)單的如api執(zhí)行時(shí)間等葛圃。下面用過濾器默垄、攔截器此虑、切片三種方式實(shí)現(xiàn)統(tǒng)計(jì)api執(zhí)行時(shí)間功能甚纲,從中介紹三者的區(qū)別口锭。

過濾器(Filter)實(shí)現(xiàn):

@Component

public class TimeFilter implements Filter {

?? @Override

?? public void init(FilterConfig filterConfig) throws ServletException {

?? }

?? @Override

?? public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

? ? ?? //開始時(shí)間

? ? ?? long start = System.currentTimeMillis();

? ? ?? //執(zhí)行下一個(gè)過濾器。無執(zhí)行Api

? ? ?? filterChain.doFilter(servletRequest, servletResponse);

? ? ?? System.out.println("執(zhí)行時(shí)間為:"+(System.currentTimeMillis()-start));

?? }

?? @Override

?? public void destroy() {

?? }

}

?

有時(shí)我們需要使用第三方的過濾器,在第三方的過濾器中沒有@Component注解鹃操,也就是不能自動(dòng)注冊(cè)成bean韭寸。在springboot項(xiàng)目中可通過配置注解解決問題。如下:

@Configuration

public class WebConfig{

?? @Bean

?? public FilterRegistrationBean timeFilter(){

? ? ?? FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();

? ? ?? TimeFilter timeFilter = new TimeFilter();

? ? ?? filterRegistrationBean.setFilter(timeFilter);

? ? ?? List<String> urls = new ArrayList<>(4);

? ? ?? urls.add("/*");

? ? ?? filterRegistrationBean.setUrlPatterns(urls);

? ? ?? return filterRegistrationBean;

?? }

}

Filter只能攔截servlet請(qǐng)求響應(yīng)荆隘,不能知道是那個(gè)控制器執(zhí)行的那個(gè)API恩伺。若要獲取可使用Interceptor攔截器。

攔截器(Interceptor)實(shí)現(xiàn)

攔截器為spring框架本身提供椰拒。

@Component

public class TimeInterceptor implements HandlerInterceptor {

?? @Override

?? public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

? ? ?? System.out.println("pre");

? ? ?? System.out.println(((HandlerMethod)o).getBean().getClass().getName());

? ? ?? System.out.println(((HandlerMethod)o).getMethod().getName());

? ? ?? httpServletRequest.setAttribute("startTime",System.currentTimeMillis());

? ? ?? return true;

?? }

?? @Override

?? public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

? ? ?? System.out.println("postHandle");

? ? ?? long startTime = (long) httpServletRequest.getAttribute("startTime");

? ? ?? System.out.println("耗時(shí):"+(System.currentTimeMillis()-startTime));

?? }

?? @Override

?? public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

? ? ?? System.out.println("afterCompletion");

? ? ?? long startTime = (long) httpServletRequest.getAttribute("startTime");

? ? ?? System.out.println("耗時(shí):"+(System.currentTimeMillis()-startTime));

? ? ?? System.out.println("ex is "+e);

?? }

}

在執(zhí)行控制器方法前執(zhí)行攔截器preHandle方法晶渠,然后執(zhí)行控制器方法,控制器方法執(zhí)行完畢后執(zhí)行postHandle方法燃观。最后執(zhí)行afterCompletion方法褒脯。若控制器方法拋錯(cuò)則不會(huì)執(zhí)行postHandle方法,但會(huì)執(zhí)行afterCompletion方法缆毁。在方法的最后一個(gè)object類型參數(shù)中可獲取控制器api信息番川。

和filter不同,在注冊(cè)成bean后脊框。攔截器需要額外的配置生效颁督,如下:

@Configuration

public class WebConfig extends WebMvcConfigurerAdapter {

?? @Autowired

?? private TimeInterceptor timeInterceptor;

?? @Override

?? public void addInterceptors(InterceptorRegistry registry) {

? ? ?? registry.addInterceptor(timeInterceptor);

?? }

}

攔截器的缺陷在于無法拿到控制器方法中參數(shù)的值,若要獲取到浇雹,可使用切片沉御。

切片(Aspect)實(shí)現(xiàn)

@Aspect

@Component

public class TimeAspect {

?? @Around("execution(* com.imooc.web.controller.UserController.*(..))")

? ? ? ?? //表示攔UserController下所有方法

?? public Object handlerControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {

? ? ?? System.out.println("切片");

? ? ?? //獲取方法參數(shù)

? ? ?? Object[] args = joinPoint.getArgs();

? ? ?? for (Object arg : args) {

? ? ? ? ?? System.out.println("參數(shù):"+arg);

? ? ?? }

? ? ?? long start = System.currentTimeMillis();

? ? ?? Object o = joinPoint.proceed();

? ? ?? System.out.println("耗時(shí):" + (System.currentTimeMillis() - start));

? ? ?? return o;

?? }

}

總結(jié)

過濾器能獲取原始的http請(qǐng)求和響應(yīng)的消息,但不能拿到真正處理請(qǐng)求方法的信息昭灵。

攔截器能獲取原始的http請(qǐng)求和響應(yīng)的消息嚷节,也能拿到真正處理請(qǐng)求方法的信息,但不能拿到方法的參數(shù)虎锚。

切片可以拿到方法的參數(shù)硫痰,但不能拿到原始的http請(qǐng)求和響應(yīng)的消息。

三種攔截的順序:

filter>interceptor>controllerAdvice>aspect>controller方法

當(dāng)controller方法方法拋出錯(cuò)誤時(shí)窜护,獲取錯(cuò)誤的順序:

aspect>controllerAdvice>interceptor>filter

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末效斑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子柱徙,更是在濱河造成了極大的恐慌缓屠,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件护侮,死亡現(xiàn)場(chǎng)離奇詭異敌完,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)羊初,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門滨溉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來什湘,“玉大人,你說我怎么就攤上這事晦攒∶龀罚” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵脯颜,是天一觀的道長(zhǎng)哟旗。 經(jīng)常有香客問我,道長(zhǎng)栋操,這世上最難降的妖魔是什么闸餐? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮矾芙,結(jié)果婚禮上绎巨,老公的妹妹穿的比我還像新娘。我一直安慰自己蠕啄,他們只是感情好场勤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著歼跟,像睡著了一般和媳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哈街,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天留瞳,我揣著相機(jī)與錄音,去河邊找鬼骚秦。 笑死她倘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的作箍。 我是一名探鬼主播硬梁,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼胞得!你這毒婦竟也來了荧止?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤阶剑,失蹤者是張志新(化名)和其女友劉穎跃巡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牧愁,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡素邪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了猪半。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兔朦。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡偷线,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烘绽,到底是詐尸還是另有隱情,我是刑警寧澤俐填,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布安接,位于F島的核電站,受9級(jí)特大地震影響英融,放射性物質(zhì)發(fā)生泄漏盏檐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一驶悟、第九天 我趴在偏房一處隱蔽的房頂上張望胡野。 院中可真熱鬧,春花似錦痕鳍、人聲如沸硫豆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熊响。三九已至,卻和暖如春诗赌,著一層夾襖步出監(jiān)牢的瞬間汗茄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工铭若, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洪碳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓叼屠,卻偏偏與公主長(zhǎng)得像瞳腌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子镜雨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355