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

資訊專欄INFORMATION COLUMN

Spring Boot實踐——三種攔截器的創建

fnngj / 491人閱讀

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

Spring中的攔截器

  在web開發中,攔截器是經常用到的功能。它可以幫我們驗證是否登陸、權限認證、數據校驗、預先設置數據以及統計方法的執行效率等等。今天就來詳細的談一下spring中的攔截器。spring中攔截器主要分種,一個是HandlerInterceptor,一個是MethodInterceptor。

一、HandlerInterceptor攔截器

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

/** * 自定義攔截器-基于springmvc
 * @ClassName: CustomInterceptor 
 * @Description: springMVC項目中的攔截器,它攔截的目標是請求的地址,比MethodInterceptor先執行。
 *                 該攔截器只能過濾action請求,SPring允許多個攔截器同時存在,通過攔截器鏈管理。
 *                 當preHandle return true時,執行下一個攔截器,直到所有攔截器執行完,再運行被攔截的請求。
 *                 當preHandle return false時, 不再執行后續的攔截器鏈及被攔截的請求。
 * @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);
    }

}

這三個方法都是干什么的,有什么作用,什么時候調用,不同的攔截器之間是怎樣的調用順序呢?這還得參考一下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處理請求的整個過程。首先根據請求找到對應的HandlerExecutionChain,它包含了處理請求的handler和所有的HandlerInterceptor攔截器;然后在調用hander之前分別調用每個HandlerInterceptor攔截器的preHandle方法,若有一個攔截器返回false,則會調用triggerAfterCompletion方法,并且立即返回不再往下執行;若所有的攔截器全部返回true并且沒有出現異常,則調用handler返回ModelAndView對象;再然后分別調用每個攔截器的postHandle方法;最后,即使是之前的步驟拋出了異常,也會執行triggerAfterCompletion方法。關于攔截器的處理到此為止,接下來看看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;
    }

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

這里可以根據自己的需求在對應方法中寫自己業務處理邏輯

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

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

    /**
     * 當前對應的interceptor的perHandle方法的返回值為true時,postHandle執行完成并渲染頁面后執行,主要用于資源清理工作
     */
    @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版本已過時了,用官網說的新的類替換
 *
 */
@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項目中的攔截器,它攔截的目標是方法,即使不是controller中的方法。實現MethodInterceptor攔截器大致也分為兩種,一種是實現MethodInterceptor接口,另一種利用AspectJ的注解或配置。

1、實現MethodInterceptor接口
/**
 * 自定義攔截器-方法攔截器,基于spring aop
 * @ClassName: CustomMethodInterceptor 
 * @Description: AOP項目中的攔截器,它攔截的目標是方法
 *                 配置在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、配置說明

    
        
        
            
        
        
    

    
    
    
三、效果圖

四、談一談區別

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76210.html

相關文章

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

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

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

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

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

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

    meislzhua 評論0 收藏0
  • Spring Boot 進階

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

    galaxy_robot 評論0 收藏0

發表評論

0條評論

fnngj

|高級講師

TA的文章

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