国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring Boot實踐——三種攔截器的創(chuàng)建

fnngj / 483人閱讀

摘要:中的攔截器在開發(fā)中,攔截器是經(jīng)常用到的功能。該攔截器只能過濾請求,允許多個攔截器同時存在,通過攔截器鏈管理。當(dāng)時不再執(zhí)行后續(xù)的攔截器鏈及被攔截的請求。實現(xiàn)攔截器大致也分為兩種,一種是實現(xiàn)接口,另一種利用的注解或配置。

Spring中的攔截器

  在web開發(fā)中,攔截器是經(jīng)常用到的功能。它可以幫我們驗證是否登陸、權(quán)限認(rèn)證、數(shù)據(jù)校驗、預(yù)先設(shè)置數(shù)據(jù)以及統(tǒng)計方法的執(zhí)行效率等等。今天就來詳細(xì)的談一下spring中的攔截器。spring中攔截器主要分種,一個是HandlerInterceptor,一個是MethodInterceptor。

一、HandlerInterceptor攔截器

  HandlerInterceptor是springMVC項目中的攔截器,它攔截的目標(biāo)是請求的地址,比MethodInterceptor先執(zhí)行。實現(xiàn)一個HandlerInterceptor攔截器可以直接實現(xiàn)HandlerInterceptor接口,也可以繼承HandlerInterceptorAdapter類。這兩種方法殊途同歸,其實HandlerInterceptorAdapter也就是聲明了HandlerInterceptor接口中所有方法的默認(rèn)實現(xiàn),而我們在繼承他之后只需要重寫必要的方法。下面就是HandlerInterceptorAdapter的代碼,可以看到一個方法只是默認(rèn)返回true,另外兩個是空方法:

/** * 自定義攔截器-基于springmvc
 * @ClassName: CustomInterceptor 
 * @Description: springMVC項目中的攔截器,它攔截的目標(biāo)是請求的地址,比MethodInterceptor先執(zhí)行。
 *                 該攔截器只能過濾action請求,SPring允許多個攔截器同時存在,通過攔截器鏈管理。
 *                 當(dāng)preHandle return true時,執(zhí)行下一個攔截器,直到所有攔截器執(zhí)行完,再運行被攔截的請求。
 *                 當(dāng)preHandle return false時, 不再執(zhí)行后續(xù)的攔截器鏈及被攔截的請求。
 * @author OnlyMate
 * @Date 2018年8月28日 下午2:30:22  
 * */
public class CustomInterceptor implements HandlerInterceptor  {

    @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

}

這三個方法都是干什么的,有什么作用,什么時候調(diào)用,不同的攔截器之間是怎樣的調(diào)用順序呢?這還得參考一下DispatcherServlet的doDispatch方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we"re processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

  代碼有點長,但是它封裝了springMVC處理請求的整個過程。首先根據(jù)請求找到對應(yīng)的HandlerExecutionChain,它包含了處理請求的handler和所有的HandlerInterceptor攔截器;然后在調(diào)用hander之前分別調(diào)用每個HandlerInterceptor攔截器的preHandle方法,若有一個攔截器返回false,則會調(diào)用triggerAfterCompletion方法,并且立即返回不再往下執(zhí)行;若所有的攔截器全部返回true并且沒有出現(xiàn)異常,則調(diào)用handler返回ModelAndView對象;再然后分別調(diào)用每個攔截器的postHandle方法;最后,即使是之前的步驟拋出了異常,也會執(zhí)行triggerAfterCompletion方法。關(guān)于攔截器的處理到此為止,接下來看看triggerAfterCompletion做了什么

private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
            @Nullable HandlerExecutionChain mappedHandler, Exception ex) throws Exception {

        if (mappedHandler != null) {
            mappedHandler.triggerAfterCompletion(request, response, ex);
        }
        throw ex;
    }

  根據(jù)以上的代碼,分析一下不同攔截器及其方法的執(zhí)行順序。假設(shè)有5個攔截器編號分別為12345,若一切正常則方法的執(zhí)行順序是12345的preHandle,54321的postHandle,54321的afterCompletion。若編號3的攔截器的preHandle方法返回false或者拋出了異常,接下來會執(zhí)行的是21的afterCompletion方法。這里要注意的地方是,我們在寫一個攔截器的時候要謹(jǐn)慎的處理preHandle中的異常,因為這里一旦有異常拋出就不會再受到這個攔截器的控制。12345的preHandle的方法執(zhí)行過之后,若handler出現(xiàn)了異常或者某個攔截器的postHandle方法出現(xiàn)了異常,則接下來都會執(zhí)行54321的afterCompletion方法,因為只要12345的preHandle方法執(zhí)行完,當(dāng)前攔截器的攔截器就會記錄成編號5的攔截器,而afterCompletion總是從當(dāng)前的攔截器逆向的向前執(zhí)行。
  另外,實現(xiàn)HandlerInterceptor攔截器還有一個方法,就是實現(xiàn)WebRequestInterceptor接口。其實它和剛才的兩種方法也是殊途同歸,最終還是被spring適配成HandlerInterceptor。有一點不同,它的preHandle方法最終只會返回true。

這里可以根據(jù)自己的需求在對應(yīng)方法中寫自己業(yè)務(wù)處理邏輯

/**
 * 自定義攔截器-基于springmvc
 * @ClassName: CustomInterceptor 
 * @Description: springMVC項目中的攔截器,它攔截的目標(biāo)是請求的地址,比MethodInterceptor先執(zhí)行。
 *                 該攔截器只能過濾action請求,SPring允許多個攔截器同時存在,通過攔截器鏈管理。
 *                 當(dāng)preHandle return true時,執(zhí)行下一個攔截器,直到所有攔截器執(zhí)行完,再運行被攔截的請求。
 *                 當(dāng)preHandle return false時, 不再執(zhí)行后續(xù)的攔截器鏈及被攔截的請求。
 * @author OnlyMate
 * @Date 2018年8月28日 下午2:30:22  
 *
 */
public class CustomInterceptor implements HandlerInterceptor  {
    private Logger logger = LoggerFactory.getLogger(CustomInterceptor.class);
    
    /**
     * 在請求處理之前執(zhí)行,主要用于權(quán)限驗證、參數(shù)過濾等
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.info("CustomInterceptor ==> preHandle method: do request before");
        return true;
    }

    /**
     * 當(dāng)前請求進(jìn)行處理之后執(zhí)行,主要用于日志記錄、權(quán)限檢查、性能監(jiān)控、通用行為等
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        logger.info("CustomInterceptor ==> postHandle method: do request after");
    }

    /**
     * 當(dāng)前對應(yīng)的interceptor的perHandle方法的返回值為true時,postHandle執(zhí)行完成并渲染頁面后執(zhí)行,主要用于資源清理工作
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.info("CustomInterceptor ==> afterCompletion method: do request finshed");
    }
}

配置如下:

/**
 * Web MVC 配置適配器
 * @ClassName: WebAppConfigurer 
 * @Description: 
 * @author OnlyMate
 * @Date 2018年8月28日 下午2:39:31  
 * 
 * WebAppConfigurer extends WebMvcConfigurerAdapter 在Spring Boot2.0版本已過時了,用官網(wǎng)說的新的類替換
 *
 */
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
    /**
     * 注入自定義攔截器
     * @Title: addInterceptors 
     * @Description: 先add的攔截器會越靠外,即越靠近瀏覽器
     * @Date 2018年8月28日 下午2:47:28 
     * @author OnlyMate
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        WebMvcConfigurer.super.addInterceptors(registry);
        registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**");//攔截所有請求
    }

}
二、MethodInterceptor攔截器

  MethodInterceptor是AOP項目中的攔截器,它攔截的目標(biāo)是方法,即使不是controller中的方法。實現(xiàn)MethodInterceptor攔截器大致也分為兩種,一種是實現(xiàn)MethodInterceptor接口,另一種利用AspectJ的注解或配置。

1、實現(xiàn)MethodInterceptor接口
/**
 * 自定義攔截器-方法攔截器,基于spring aop
 * @ClassName: CustomMethodInterceptor 
 * @Description: AOP項目中的攔截器,它攔截的目標(biāo)是方法
 *                 配置在applicationContext.xml中
 * @author OnlyMate
 * @Date 2018年8月29日 下午3:35:24  
 *
 */
public class CustomMethodInterceptor implements MethodInterceptor {
    private Logger logger = LoggerFactory.getLogger(CustomMethodInterceptor.class);
    
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        logger.info("CustomMethodInterceptor ==> invoke method: process method name is {}", invocation.getMethod().getName());
        
        //TODO 處理操作
        
        return invocation.proceed();
    }

}

配置說明


    
    
        
        
        
        
        
    

CustomAnnotation自定義注解

/**
 * 自定義注解對象
 * @ClassName: TableSplit 
 * @Description: TODO
 * @author OnlyMate
 * @Date 2018年5月22日 上午11:43:57  
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
    /** 需攔截方法名描述 */
    String name() default "";
    
    /** 加密 */
    String[] encrypt() default {};

    /** 解密 */
    String[] decrypt() default {};

}
2、利用AspectJ的注解或配置  a、基于AspectJ注解
/**
 * 自定義攔截器-方法攔截器,基于注解的AspectJ方式
 * @ClassName: CustomAutoAspectJInterceptor 
 * @Description: 配置在applicationContext.xml中
 * @author OnlyMate
 * @Date 2018年8月29日 下午4:03:49  
 *
 */
@Component
@Aspect
public class CustomAutoAspectJInterceptor {
    private Logger logger = LoggerFactory.getLogger(CustomAutoAspectJInterceptor.class);
    
    @Around("execution (* com.onlymate.springboot.controller.*.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        logger.info("CustomAutoAspectJInterceptor ==> invoke method: process method class is {}", point.getTarget().getClass());
        
        //TODO 處理操作
        
        return point.proceed();
    }
}
b、基于AspectJ配置
/**
 * 自定義攔截器-方法攔截器,基于AspectJ方式
 * @ClassName: CustomAspectJInterceptor 
 * @Description: 配置在applicationContext.xml中
 * @author OnlyMate
 * @Date 2018年8月29日 下午4:03:49  
 *
 */
public class CustomAspectJInterceptor {
    private Logger logger = LoggerFactory.getLogger(CustomAspectJInterceptor.class);
    
    public Object around(ProceedingJoinPoint point) throws Throwable{
        logger.info("CustomAspectJInterceptor ==> invoke method: process method class is {}", point.getTarget().getClass());
        
        //TODO 處理操作
        
        return point.proceed();
    }
}
c、配置說明

    
        
        
            
        
        
    

    
    
    
三、效果圖

四、談一談區(qū)別

  上面的兩種攔截器都能起到攔截的效果,但是他們攔截的目標(biāo)不一樣,實現(xiàn)的機(jī)制不同,所以有的時候適用不同的場景。HandlerInterceptoer攔截的是請求地址,所以針對請求地址做一些驗證、預(yù)處理等操作比較合適。當(dāng)你需要統(tǒng)計請求的響應(yīng)時間時MethodInterceptor將不太容易做到,因為它可能跨越很多方法或者只涉及到已經(jīng)定義好的方法中一部分代碼。MethodInterceptor利用的是AOP的實現(xiàn)機(jī)制,在本文中只說明了使用方式,關(guān)于原理和機(jī)制方面介紹的比較少,因為要說清楚這些需要講出AOP的相當(dāng)一部分內(nèi)容。在對一些普通的方法上的攔截HandlerInterceptoer就無能為力了,這時候只能利用AOP的MethodInterceptor。利用MethodInterceptor就可以很容易的實現(xiàn)一個日志攔截處理。

   另外,還有一個跟攔截器類似的東西----Filter。Filter是Servlet規(guī)范規(guī)定的,不屬于spring框架,也是用于請求的攔截。但是它適合更粗粒度的攔截,在請求前后做一些編解碼處理、日志記錄等。而攔截器則可以提供更細(xì)粒度的,更加靈活的,針對某些請求、某些方法的組合的解決方案。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76210.html

相關(guān)文章

  • springboot整合shiro使用shiro-spring-boot-web-starter

    摘要:此文章僅僅說明在整合時的一些坑并不是教程增加依賴集成依賴配置三個必須的用于授權(quán)和登錄創(chuàng)建自己的實例用于實現(xiàn)權(quán)限三種方式實現(xiàn)定義權(quán)限路徑第一種使用角色名定義第二種使用權(quán)限定義第三種使用接口的自定義配置此處配置之后需要在對應(yīng)的 此文章僅僅說明在springboot整合shiro時的一些坑,并不是教程 增加依賴 org.apache.shiro shiro-spring-...

    sevi_stuo 評論0 收藏0
  • Spring Boot - 整合JdbcTemplate、MyBatis

    摘要:更簡答的說就是要么全部執(zhí)行成功,要么撤銷不執(zhí)行。因此,數(shù)據(jù)庫操作的事務(wù)習(xí)慣上就稱為事務(wù)。實現(xiàn)原理單機(jī)事務(wù)事務(wù)是用對象控制的。接口提供了兩種事務(wù)模式自動提交和手工提交。事務(wù)多機(jī)事務(wù),通過實現(xiàn),需要驅(qū)動支持。局限于應(yīng)用使用。 Spring Boot - 數(shù)據(jù)庫配置 回顧 Spring Boot - 初識 Hello World Spring Boot - Servlet、過濾器、監(jiān)聽器、...

    Keagan 評論0 收藏0
  • 貓頭鷹深夜翻譯:使用SpringBoot和AspectJ實現(xiàn)AOP

    摘要:我們會寫切面來攔截對這些業(yè)務(wù)類和類的調(diào)用。切面定義何時攔截一個方法以及做什么和在一起成為切面連接點當(dāng)代碼開始執(zhí)行,并且切點的條件滿足時,通知被調(diào)用。 前言 這篇文章會幫助你使用Spring Boot Starter AOP實現(xiàn)AOP。我們會使用AspectJ實現(xiàn)四個不同的通知(advice),并且新建一個自定義的注解來追蹤方法的執(zhí)行時間。 你將會了解 什么是交叉分割關(guān)注點(cross...

    meislzhua 評論0 收藏0
  • Spring Boot 進(jìn)階

    摘要:我們可不可以提供一個公共的入口進(jìn)行統(tǒng)一的異常處理呢當(dāng)然可以。一般我們可以在地址上帶上版本號,也可以在參數(shù)上帶上版本號,還可以再里帶上版本號,這里我們在地址上帶上版本號,大致的地址如,其中,即代表的是版本號。 上一篇帶領(lǐng)大家初步了解了如何使用 Spring Boot 搭建框架,通過 Spring Boot 和傳統(tǒng)的 SpringMVC 架構(gòu)的對比,我們清晰地發(fā)現(xiàn) Spring Boot ...

    galaxy_robot 評論0 收藏0

發(fā)表評論

0條評論

fnngj

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<