RESTful API的攔截

  • 過(guò)濾器(Filter)

依賴于servlet容器镐躲。在實(shí)現(xiàn)上基于函數(shù)回調(diào)吨述,可以對(duì)幾乎所有請(qǐng)求進(jìn)行過(guò)濾候学,但是缺點(diǎn)是一個(gè)過(guò)濾器實(shí)例只能在容器初始化時(shí)調(diào)用一次具伍。使用過(guò)濾器的目的是用來(lái)做一些過(guò)濾操作翅雏,獲取我們想要獲取的數(shù)據(jù),比如:在過(guò)濾器中修改字符編碼人芽;在過(guò)濾器中修改HttpServletRequest的一些參數(shù)望几,包括:過(guò)濾低俗文字、危險(xiǎn)字符等


@Slf4j
//@Component
public class TimeFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("time filter init");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("filter start");
        long startTime = new Date().getTime();
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("consumingTime:{}",new Date().getTime()-startTime);
        log.info("filter end");
    }
    @Override
    public void destroy() {
        log.info("time filter destroy");
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer{
    @Bean
    public FilterRegistrationBean timeFilter() {
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TimeFilter());
        ArrayList<String> urls = new ArrayList<>();
        urls.add("/*");
        registrationBean.setUrlPatterns(urls);
        return registrationBean;
    }
}
  • 過(guò)濾器生命周期
    • Filter的創(chuàng)建和銷(xiāo)毀由web服務(wù)器負(fù)責(zé)萤厅。 web應(yīng)用程序啟動(dòng)時(shí)橄抹,web服務(wù)器將創(chuàng)建Filter的實(shí)例對(duì)象靴迫,并調(diào)用其init方法,完成對(duì)象的初始化功能楼誓,從而為后續(xù)的用戶請(qǐng)求作好攔截的準(zhǔn)備工作矢劲,filter對(duì)象只會(huì)創(chuàng)建一次,init方法也只會(huì)執(zhí)行一次慌随。通過(guò)init方法的參數(shù)芬沉,可獲得代表當(dāng)前filter配置信息的FilterConfig對(duì)象。
    • web容器調(diào)用destroy方法銷(xiāo)毀Filter阁猜。destroy方法在Filter的生命周期中僅執(zhí)行一次丸逸。在destroy方法中,可以釋放過(guò)濾器使用的資源剃袍。

  • 攔截器(Interceptor)

攔截器是AOP實(shí)現(xiàn)的一種策略黄刚,在AOP中用于在訪問(wèn)某個(gè)方法或字段之前,進(jìn)行攔截民效,在執(zhí)行之前或之后加入某些處理憔维。
SpringMVC 中的Interceptor 攔截請(qǐng)求是通過(guò)HandlerInterceptor 來(lái)實(shí)現(xiàn)的。在SpringMVC 中定義一個(gè)Interceptor 非常簡(jiǎn)單畏邢,主要有兩種方式业扒,第一種方式是要定義的Interceptor類(lèi)要實(shí)現(xiàn)了Spring 的HandlerInterceptor 接口,或者是這個(gè)類(lèi)繼承實(shí)現(xiàn)了HandlerInterceptor 接口的類(lèi)舒萎,比如Spring 已經(jīng)提供的實(shí)現(xiàn)了HandlerInterceptor 接口的抽象類(lèi)HandlerInterceptorAdapter 程储;第二種方式是實(shí)現(xiàn)Spring的WebRequestInterceptor接口,或者是繼承實(shí)現(xiàn)了WebRequestInterceptor的類(lèi)臂寝。


@Slf4j
@Component
public class TimeInterceptor implements HandlerInterceptor {
  //在handler執(zhí)行之前章鲤,返回 boolean 值,true 表示繼續(xù)執(zhí)行咆贬,false 為停止執(zhí)行并返回
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandle");
        //攔截器可以拿到請(qǐng)求轉(zhuǎn)向的具體類(lèi)和方法
        log.info(((HandlerMethod) handler).getBean().getClass().getName());
        log.info(((HandlerMethod) handler).getMethod().getName());
        request.setAttribute("startTime", new Date().getTime());
        return true;
    }
    //在handler執(zhí)行之后, 可以在返回之前對(duì)返回的結(jié)果進(jìn)行修改 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle consumingTime:{}", new Date().getTime() - (long) request.getAttribute("startTime"));
    }
  //進(jìn)行資源清理工作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion consumingTime:{},ex:{}", new Date().getTime() - (long) request.getAttribute("startTime"), ex);

    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer{
    @Autowired
    private TimeInterceptor timeInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(timeInterceptor);
    }
}
  • 兩者比較
    1. filter基于函數(shù)回調(diào)败徊,interceptor基于java反射機(jī)制;
    2. filter依賴于servlet容器掏缎; 攔截器是一個(gè)Spring的組件皱蹦,歸Spring管理,配置 在Spring文件中御毅,因此能使用Spring里的任何資源根欧、對(duì)象,例如 Service對(duì)象端蛆、數(shù)據(jù)源、事務(wù)管理等酥泛,通過(guò)IoC注入到攔截器即可今豆。
    3. filter對(duì)所有的請(qǐng)求進(jìn)行過(guò)濾嫌拣,interceptor只對(duì)action請(qǐng)求起作用。
    4. 在action的生命周期里呆躲,Interceptor可以被多次調(diào)用异逐,而Filter只能在容器初始化時(shí)調(diào)用一次。
    5. 執(zhí)行順序:過(guò)濾前-攔截前-action執(zhí)行-攔截后-過(guò)濾后

  • 切片(Aspect)


    image.png
@Aspect
@Component
@Slf4j
public class TimeAspect {
    @Around("execution(* com.dzg.web.controller.UserController.*(..))")
    public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("timeAspect start");
        Object proceed = joinPoint.proceed();
        //Aspect可以拿到請(qǐng)求中的攜帶的參數(shù)信息插掂,這是攔截器無(wú)法做到的灰瞻,但其無(wú)法拿到request和response
        Object[] args = joinPoint.getArgs();
        for(Object arg :args){
            log.info("arg:{}",arg);
        }
        log.info("timeAspect end");
        return proceed;

    }
}
  • 攔截順序
    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辅甥,隨后出現(xiàn)的幾起案子酝润,更是在濱河造成了極大的恐慌,老刑警劉巖璃弄,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件要销,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夏块,警方通過(guò)查閱死者的電腦和手機(jī)疏咐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脐供,“玉大人浑塞,你說(shuō)我怎么就攤上這事≌海” “怎么了缩举?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)匹颤。 經(jīng)常有香客問(wèn)我仅孩,道長(zhǎng),這世上最難降的妖魔是什么印蓖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任辽慕,我火速辦了婚禮,結(jié)果婚禮上赦肃,老公的妹妹穿的比我還像新娘溅蛉。我一直安慰自己,他們只是感情好他宛,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布船侧。 她就那樣靜靜地躺著,像睡著了一般厅各。 火紅的嫁衣襯著肌膚如雪镜撩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天队塘,我揣著相機(jī)與錄音袁梗,去河邊找鬼宜鸯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遮怜,可吹牛的內(nèi)容都是我干的淋袖。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锯梁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼即碗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起陌凳,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剥懒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后冯遂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蕊肥,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年蛤肌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壁却。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡裸准,死狀恐怖展东,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炒俱,我是刑警寧澤盐肃,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站权悟,受9級(jí)特大地震影響砸王,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峦阁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一谦铃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榔昔,春花似錦驹闰、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至诵肛,卻和暖如春屹培,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工惫谤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壁顶,地道東北人珠洗。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓溜歪,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親许蓖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝴猪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • RESTful API的攔截 場(chǎng)景:對(duì)RESTfulAPI作統(tǒng)一的處理,比如希望對(duì)所有的RESTfulAPI記錄服...
    我可能是個(gè)假開(kāi)發(fā)閱讀 1,902評(píng)論 0 14
  • 【原創(chuàng)文章膊爪,轉(zhuǎn)載請(qǐng)注明原文章地址自阱,謝謝!】 上一節(jié)我們介紹了Jesery中的過(guò)濾器米酬。過(guò)濾器主要用來(lái)處理請(qǐng)求頭沛豌,響應(yīng)...
    叩丁狼教育閱讀 7,136評(píng)論 1 2
  • 飛鳥(niǎo)在天空劃出鉛色的痕跡, 遠(yuǎn)走赃额,高飛加派, 徒留我形單孤寂。 陰云在天空織出灰色的布匹跳芳, 迷蒙芍锦,暗沉, 只令我停步站...
    小卜姑娘閱讀 1,884評(píng)論 51 49
  • ? 五飞盆、血濺巡按府 村民拉大徳他們正要出去行刑時(shí)娄琉,忽聽(tīng)大德長(zhǎng)呼一聲,淚如雨下吓歇,說(shuō)道:“想我秦家一世忠良孽水,卻被奸人所...
    wangfengqun閱讀 258評(píng)論 0 0
  • 產(chǎn)品經(jīng)理得title是什么女气,很重要么?很多產(chǎn)品新人析命,都被誤導(dǎo)了主卫,總以為作為PM是可以改變世界,創(chuàng)造世界鹃愤,其實(shí)非也簇搅。...
    產(chǎn)品經(jīng)理之二三事閱讀 4,435評(píng)論 0 1