SpringBoot 三種攔截http請求方式Filter,interceptor和aop

SpringBoot 三種攔截http請求方式Filter,interceptor和aop。

這三種攔截方式的攔截順序是:filter—>Interceptor-->ControllerAdvice-->@Aspect -->Controller吩翻;

這三種方式的區(qū)別:
1.過濾器Filter可以拿到原始的HTTP請求和響應(yīng)的信息, 但是拿不到你真正處理請求方法的信息钥组,也就是方法的信息。
2.攔截器Interceptor可以拿到原始的HTTP請求和響應(yīng)的信息今瀑,也可以拿到你真正處理請求方法的信息程梦,但是拿不到傳進參數(shù)的那個值。
3.切片Aspect橘荠,既然Spring那么支持AOP屿附,可以拿到原始的HTTP請求和響應(yīng)的信息, 也可以拿到你真正處理請求方法的信息,也可以傳進參數(shù)的那個值哥童。

第一種方式:Filter

實現(xiàn)Filter接口

/**
 * 自定義Filter
 * 對請求的header 過濾token
 *
 * 過濾器Filter可以拿到原始的HTTP請求和響應(yīng)的信息拿撩,
 *     但是拿不到你真正處理請求方法的信息,也就是方法的信息
 *
 * @Component 注解讓攔截器注入Bean如蚜,從而讓攔截器生效
 * @WebFilter 配置攔截規(guī)則
 *
 * 攔截順序:filter—>Interceptor-->ControllerAdvice-->@Aspect -->Controller
 *
 */
@Slf4j
@Component
@WebFilter(urlPatterns = {"/**"},filterName = "tokenAuthorFilter")
public class TokenFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("TokenFilter init {}",filterConfig.getFilterName());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("TokenFilter doFilter 我攔截到了請求");
//        log.info("TokenFilter doFilter",((HttpServletRequest)request).getHeader("token"));

        chain.doFilter(request,response);//到下一個鏈

    }

    @Override
    public void destroy() {
        log.info("TokenFilter destroy");
    }
}
第二種方式:攔截器 Interceptor

實現(xiàn) HandlerInterceptor 接口,然后配置進Spring影暴。

/**
 * 自定義攔截器
 * 自定義攔截器后错邦,需要配置進Spring
 *
 * 攔截器Interceptor可以拿到原始的HTTP請求和響應(yīng)的信息,
 *    也可以拿到你真正處理請求方法的信息型宙,但是拿不到傳進參數(shù)的那個值撬呢。
 *
 *攔截順序:filter—>Interceptor-->ControllerAdvice-->@Aspect -->Controller
 */
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {

    /**
     * 在訪問Controller某個方法之前這個方法會被調(diào)用。
     * @param request
     * @param response
     * @param handler
     * @return false則表示不執(zhí)行postHandle方法,true 表示執(zhí)行postHandle方法
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("Token Interceptor preHandle {}","");
        String token = request.getHeader("token");
        log.info("Token Interceptor preHandle token :{}",token);
        log.info("Token Interceptor preHandle uri {}",request.getRequestURL().toString());

        //spring boot 2.0對靜態(tài)資源也進行了攔截妆兑,當(dāng)攔截器攔截到請求之后魂拦,
        // 但controller里并沒有對應(yīng)的請求時,該請求會被當(dāng)成是對靜態(tài)資源的請求搁嗓。
        // 此時的handler就是 ResourceHttpRequestHandler芯勘,就會拋出上述錯誤。
        if (handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            log.info("Token Interceptor preHandle getMethod {}",method.getName());
        }else if(handler instanceof ResourceHttpRequestHandler){//靜態(tài)資源
            ResourceHttpRequestHandler resourceHttpRequestHandler = (ResourceHttpRequestHandler) handler;
            log.info("Token Interceptor preHandle getMethod {}",resourceHttpRequestHandler.getMediaTypes());
        }

        //false則表示不執(zhí)行postHandle方法,不執(zhí)行下一步chain鏈腺逛,直接返回response
        return true;
    }

    /**
     * 請求處理之后進行調(diào)用荷愕,但是在視圖被渲染之前(Controller方法調(diào)用之后)
     * preHandle方法處理之后這個方法會被調(diào)用,如果控制器Controller出現(xiàn)了異常棍矛,則不會執(zhí)行此方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("Token Interceptor postHandle");  
    }

    /**
     * 不管有沒有異常安疗,這個afterCompletion都會被調(diào)用
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("Token Interceptor afterCompletion");
    }

}

配置進spring

/**
 *  TokenInterceptor 自定義攔截器后,需要配置進Spring
 * 也可以mapping够委,跨域設(shè)置
 */
@Slf4j
@Configuration
public class TokenConfig implements WebMvcConfigurer {

    @Autowired
    TokenInterceptor tokenInterceptor;

    /**
     * 添加攔截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        log.info("TokenConfig addInterceptors tokenInterceptor");
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")//指定該類攔截的url
        .excludePathPatterns( "/static/**");//過濾靜態(tài)資源
    }

    /**
     * 如果實現(xiàn)了Filter跨域攔截荐类,這個跨域無效
     * 攔截器實現(xiàn) 跨域支持
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        log.info("TokenConfig addInterceptors addCorsMappings");
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT","OPTIONS","HEAD")
                .allowedHeaders("*")
                .maxAge(3600);
    }
 
}
第三種方式 : aop攔截

pom.xml 添加Aop支持

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
/**
 * pom.xml 添加Aop支持
 *     <dependency>
 *             <groupId>org.springframework.boot</groupId>
 *             <artifactId>spring-boot-starter-aop</artifactId>
 *         </dependency>
 *
 * 切片Aspect,既然Spring那么支持AOP茁帽,可以拿到原始的HTTP請求和響應(yīng)的信息玉罐,
 *      也可以拿到你真正處理請求方法的信息屈嗤,也可以傳進參數(shù)的那個值。
 *
 * 攔截順序:filter—>Interceptor-->ControllerAdvice-->@Aspect -->Controller
 */
@Slf4j
@Component  //表示它是一個Spring的組件
@Aspect  //表示它是一個切面
public class HttpAspect {

    /**
     * 通過ProceedingJoinPoint對象的getArgs()我們可以得到傳進來的參數(shù)厌小。
     * 通過ProceedingJoinPoint對象的proceed()我們可以得到拿到切面方法返回值的對象恢共。
     * @param pjp
     * @return
     * 環(huán)繞通知    首先是:包名  然后是: 類名  然后是方法名:方法名   括號內(nèi)是:參數(shù)
     */
    @Around("execution(* com.learn.jwttoken.controller.*.*(..))")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        log.info("HttpAspect handleControllerMethod filter start");

        //原始的HTTP請求和響應(yīng)的信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();

        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature)signature;
        //獲取當(dāng)前執(zhí)行的方法
        Method targetMethod = methodSignature.getMethod();
        log.info("當(dāng)前執(zhí)行的方法:{}",targetMethod.getName());

        //獲取參數(shù)
        Object[] objs = pjp.getArgs();
        for (Object obj:objs){
            log.info("參數(shù):"+obj);
        }

        //獲取返回對象
        Object object = pjp.proceed();
        log.info("獲得返回對象 :{}",object);
        log.info("HttpAspect handleControllerMethod filter end");

        return pjp.proceed();//代理方法的返回值
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市璧亚,隨后出現(xiàn)的幾起案子讨韭,更是在濱河造成了極大的恐慌,老刑警劉巖癣蟋,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件透硝,死亡現(xiàn)場離奇詭異,居然都是意外死亡疯搅,警方通過查閱死者的電腦和手機濒生,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幔欧,“玉大人罪治,你說我怎么就攤上這事〗刚幔” “怎么了觉义?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浴井。 經(jīng)常有香客問我晒骇,道長,這世上最難降的妖魔是什么磺浙? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任洪囤,我火速辦了婚禮,結(jié)果婚禮上撕氧,老公的妹妹穿的比我還像新娘瘤缩。我一直安慰自己,他們只是感情好呵曹,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布款咖。 她就那樣靜靜地躺著,像睡著了一般奄喂。 火紅的嫁衣襯著肌膚如雪铐殃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天跨新,我揣著相機與錄音富腊,去河邊找鬼。 笑死域帐,一個胖子當(dāng)著我的面吹牛赘被,可吹牛的內(nèi)容都是我干的是整。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼民假,長吁一口氣:“原來是場噩夢啊……” “哼浮入!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起羊异,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤事秀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后野舶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體易迹,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年平道,在試婚紗的時候發(fā)現(xiàn)自己被綠了睹欲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡一屋,死狀恐怖窘疮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冀墨,我是刑警寧澤考余,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站轧苫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疫蔓。R本人自食惡果不足惜含懊,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衅胀。 院中可真熱鬧岔乔,春花似錦、人聲如沸滚躯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掸掏。三九已至茁影,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丧凤,已是汗流浹背募闲。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愿待,地道東北人浩螺。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓靴患,卻偏偏與公主長得像,于是被迫代替她去往敵國和親要出。 傳聞我的和親對象是個殘疾皇子鸳君,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354