最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文了解Spring中攔截器的原理與使用

 更新時(shí)間:2022年06月27日 11:46:38   作者:WX7251  
在web開(kāi)發(fā)中,攔截器是經(jīng)常用到的功能。它可以幫我們預(yù)先設(shè)置數(shù)據(jù)以及統(tǒng)計(jì)方法的執(zhí)行效率等等。今天就來(lái)詳細(xì)的談一下spring中的攔截器,需要的可以參考一下

1.Spring中的攔截器

在web開(kāi)發(fā)中,攔截器是經(jīng)常用到的功能。它可以幫我們預(yù)先設(shè)置數(shù)據(jù)以及統(tǒng)計(jì)方法的執(zhí)行效率等等。

今天就來(lái)詳細(xì)的談一下spring中的攔截器。spring中攔截器主要分兩種,一個(gè)是HandlerInterceptor,一個(gè)是MethodInterceptor。

1.1HandlerInterceptor攔截器

HandlerInterceptor是springMVC項(xiàng)目中的攔截器,它攔截的目標(biāo)是請(qǐng)求的地址,比MethodInterceptor先執(zhí)行。其工作原理是當(dāng)請(qǐng)求來(lái)時(shí)先進(jìn)性預(yù)處理,如下。

這里我們可以實(shí)現(xiàn)一個(gè)通過(guò)HandlerInterceptor實(shí)現(xiàn)打印請(qǐng)求開(kāi)始和結(jié)束的日志,如下。

1.依賴(lài)引入

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.實(shí)現(xiàn)類(lèi)

攔截器類(lèi)

@Component
public class EasyLogControllerInterceptor implements HandlerInterceptor {
 
    /**
     * 在controller調(diào)用之前執(zhí)行
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println(request.getRequestURI()+"開(kāi)始執(zhí)行");
        return true;
    }
 
    /**
     * 在controller調(diào)用中執(zhí)行
     */
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }
 
    /**
     * 在controller調(diào)用后執(zhí)行
     */
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println(request.getRequestURI()+"執(zhí)行結(jié)束");
    }
 
}

controller類(lèi)

@RestController
public class TestController {
 
    @GetMapping("/hello")
    public Map<String,String> hello(){
        Map<String,String> response=new HashMap<>();
        response.put("msg","hello");
        return response;
    }
 
}

配置類(lèi)

@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
 
    @Autowired
    private EasyLogControllerInterceptor easyLogControllerInterceptor;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //addPathPatterns用于添加攔截路徑
        //excludePathPatterns用于添加不攔截的路徑
        registry.addInterceptor(easyLogControllerInterceptor).addPathPatterns("/hello");
 
    }
 
 
    //此方法用于配置靜態(tài)資源路徑
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/my/");
    }
}

3.運(yùn)行效果

1.1.1HandlerInterceptor講解

實(shí)現(xiàn)一個(gè)HandlerInterceptor攔截器可以直接實(shí)現(xiàn)HandlerInterceptor接口,也可以繼承HandlerInterceptorAdapter類(lèi)。這兩種方法殊途同歸,其實(shí)HandlerInterceptorAdapter也就是聲明了HandlerInterceptor接口中所有方法的默認(rèn)實(shí)現(xiàn),而我們?cè)诶^承他之后只需要重寫(xiě)必要的方法。

下面就是HandlerInterceptorAdapter的代碼,可以看到一個(gè)方法只是默認(rèn)返回true,另外兩個(gè)是空方法:

public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {  
  
 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  
        throws Exception {  
        return true;  
    }  
 
    public void postHandle(  
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
            throws Exception {  
    }  
  
 
    public void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
            throws Exception {  
    }  
  
}  

這三個(gè)方法都是干什么的,有什么作用,什么時(shí)候調(diào)用,不同的攔截器之間是怎樣的調(diào)用順序呢?

先補(bǔ)一張圖:

這還得參考一下DispatcherServlet的doDispatch方法: 

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
        HttpServletRequest processedRequest = request;  
        HandlerExecutionChain mappedHandler = null;  
        int interceptorIndex = -1;  
  
        try {  
            ModelAndView mv;  
            boolean errorView = false;  
  
            try {  
                processedRequest = checkMultipart(request);  
  
                // Determine handler for the current request.  
                mappedHandler = getHandler(processedRequest, false);  
                if (mappedHandler == null || mappedHandler.getHandler() == 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()) {  
                        String requestUri = urlPathHelper.getRequestUri(request);  
                        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
                    }  
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
                        return;  
                    }  
                }  
  
                // Apply preHandle methods of registered interceptors.  
                HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();  
                if (interceptors != null) {  
                    for (int i = 0; i < interceptors.length; i++) {  
                        HandlerInterceptor interceptor = interceptors[i];  
                        if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {  
                            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
                            return;  
                        }  
                        interceptorIndex = i;  
                    }  
                }  
  
                // Actually invoke the handler.  
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  
                // Do we need view name translation?  
                if (mv != null && !mv.hasView()) {  
                    mv.setViewName(getDefaultViewName(request));  
                }  
  
                // Apply postHandle methods of registered interceptors.  
                if (interceptors != null) {  
                    for (int i = interceptors.length - 1; i >= 0; i--) {  
                        HandlerInterceptor interceptor = interceptors[i];  
                        interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);  
                    }  
                }  
            }  
            catch (ModelAndViewDefiningException ex) {  
                logger.debug("ModelAndViewDefiningException encountered", ex);  
                mv = ex.getModelAndView();  
            }  
            catch (Exception ex) {  
                Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);  
                mv = processHandlerException(processedRequest, response, handler, ex);  
                errorView = (mv != null);  
            }  
  
            // Did the handler return a view to render?  
            if (mv != null && !mv.wasCleared()) {  
                render(mv, processedRequest, response);  
                if (errorView) {  
                    WebUtils.clearErrorRequestAttributes(request);  
                }  
            }  
            else {  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +  
                            "': assuming HandlerAdapter completed request handling");  
                }  
            }  
  
            // Trigger after-completion for successful outcome.  
            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
        }  
  
        catch (Exception ex) {  
            // Trigger after-completion for thrown exception.  
            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);  
            throw ex;  
        }  
        catch (Error err) {  
            ServletException ex = new NestedServletException("Handler processing failed", err);  
            // Trigger after-completion for thrown exception.  
            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);  
            throw ex;  
        }  
  
        finally {  
            // Clean up any resources used by a multipart request.  
            if (processedRequest != request) {  
                cleanupMultipart(processedRequest);  
            }  
        }  
    }

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

1.2 MethodInterceptor攔截器

MethodInterceptor是AOP項(xiàng)目中的攔截器,它攔截的目標(biāo)是方法,即使不是controller中的方法。具體使用方式可以參考SpringBoot中利用AOP和攔截器實(shí)現(xiàn)自定義注解

2.二者的區(qū)別

上面的兩種攔截器都能起到攔截的效果,但是他們攔截的目標(biāo)不一樣,實(shí)現(xiàn)的機(jī)制不同,所以有的時(shí)候適用不同的場(chǎng)景。

HandlerInterceptoer攔截的是請(qǐng)求地址,所以針對(duì)請(qǐng)求地址做一些驗(yàn)證、預(yù)處理等操作比較合適。當(dāng)你需要統(tǒng)計(jì)請(qǐng)求的響應(yīng)時(shí)間時(shí)MethodInterceptor將不太容易做到,因?yàn)樗赡芸缭胶芏喾椒ɑ蛘咧簧婕暗揭呀?jīng)定義好的方法中一部分代碼。MethodInterceptor利用的是AOP的實(shí)現(xiàn)機(jī)制,在本文中只說(shuō)明了使用方式,關(guān)于原理和機(jī)制方面介紹的比較少,因?yàn)橐f(shuō)清楚這些需要講出AOP的相當(dāng)一部分內(nèi)容。在對(duì)一些普通的方法上的攔截HandlerInterceptoer就無(wú)能為力了,這時(shí)候只能利用AOP的MethodInterceptor。

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

另外的另外,用過(guò)人人網(wǎng)的ROSE框架的人都會(huì)非常喜歡它的攔截器功能。因?yàn)樗鼘?shí)現(xiàn)了全注解的方式,只要在類(lèi)的名字上加上攔截器的注解即表示這是一個(gè)攔截器。而使用這個(gè)攔截器的方法或者controller也只需在方法或controller的上面加上這個(gè)攔截器的注解。其實(shí)這是一個(gè)關(guān)注點(diǎn)的轉(zhuǎn)變,spring的切面控制在配置文件中,配置文件關(guān)注哪些地方需要攔截。而在ROSE中,則是在需要攔截的地方關(guān)注我要被誰(shuí)攔截。

以上就是一文了解Spring中攔截器的原理與使用的詳細(xì)內(nèi)容,更多關(guān)于Spring攔截器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java集合中的Collection接口總結(jié)

    Java集合中的Collection接口總結(jié)

    這篇文章主要介紹了Java集合中的Collection接口總結(jié),Collection 接口是 List和Set接口的父接口,該接口里定義的方法既可用于操作 Set 集合,也可用于操作 List 集合,需要的朋友可以參考下
    2023-11-11
  • java求100之內(nèi)的素?cái)?shù)(質(zhì)數(shù))簡(jiǎn)單示例

    java求100之內(nèi)的素?cái)?shù)(質(zhì)數(shù))簡(jiǎn)單示例

    這篇文章主要介紹了java求100之內(nèi)的素?cái)?shù)簡(jiǎn)單示例,素?cái)?shù)是一個(gè)大于1的自然數(shù),如果除了1和它自身外,不能被其他自然數(shù)整除的數(shù);否則稱(chēng)為合數(shù)
    2014-04-04
  • Java中5種方式實(shí)現(xiàn)String反轉(zhuǎn)

    Java中5種方式實(shí)現(xiàn)String反轉(zhuǎn)

    下面小編就為大家?guī)?lái)一篇Java中5種方式實(shí)現(xiàn)String反轉(zhuǎn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。
    2016-06-06
  • mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn)

    mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn)

    XML 文件在解析時(shí)會(huì)將五種特殊字符進(jìn)行轉(zhuǎn)義,本文主要介紹了mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • JSON字符串中獲取一個(gè)指定字段的值四種方式

    JSON字符串中獲取一個(gè)指定字段的值四種方式

    在Java開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到需要從JSON數(shù)據(jù)中提取特定字段值的情況,這篇文章主要給大家介紹了關(guān)于JSON字符串中獲取一個(gè)指定字段的值四種方式,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • springboot日志文件名稱(chēng)叫l(wèi)ogback-spring.xml的原因解析

    springboot日志文件名稱(chēng)叫l(wèi)ogback-spring.xml的原因解析

    這篇文章主要介紹了springboot日志文件名稱(chēng)為什么叫l(wèi)ogback-spring.xml,本文給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • java 定時(shí)器Timer和TimerTask的使用詳解(執(zhí)行和暫停)

    java 定時(shí)器Timer和TimerTask的使用詳解(執(zhí)行和暫停)

    這篇文章主要介紹了java 定時(shí)器Timer和TimerTask的使用詳解(執(zhí)行和暫停),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • 詳解如何提升SpringBoot項(xiàng)目的吞吐量

    詳解如何提升SpringBoot項(xiàng)目的吞吐量

    吞吐量是指系統(tǒng)在單位時(shí)間內(nèi)成功處理請(qǐng)求的數(shù)量,當(dāng)吞吐量不足以應(yīng)對(duì)業(yè)務(wù)需求時(shí),會(huì)導(dǎo)致請(qǐng)求Pile Up的情況發(fā)生,使系統(tǒng)不可用甚至宕機(jī),所以提高吞吐量是保證系統(tǒng)可用性的有效手段之一,本文就給大家講講如何提升SpringBoot項(xiàng)目的吞吐量
    2023-07-07
  • Mybatis generator修改Mapper.java文件實(shí)現(xiàn)詳解

    Mybatis generator修改Mapper.java文件實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了Mybatis generator修改Mapper.java文件實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程

    在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程

    這篇文章主要介紹了在SpringBoot: SpringBoot里面創(chuàng)建導(dǎo)出Excel的接口教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10

最新評(píng)論

英德市| 聂拉木县| 双峰县| 平凉市| 昭苏县| 施甸县| 德庆县| 凤冈县| 吴桥县| 朝阳区| 咸阳市| 永年县| 长泰县| 东丽区| 浦北县| 长海县| 三明市| 盐源县| 黄骅市| 通河县| 建瓯市| 新蔡县| 江北区| 玛曲县| 永靖县| 读书| 谷城县| 高陵县| 仁怀市| 乐昌市| 乐陵市| 安新县| 漾濞| 大埔区| 宣汉县| 上饶市| 运城市| 古丈县| 台安县| 沐川县| 常山县|