Spring MVC Handlerinterceptor Implementation principle (source code)

Source: Internet
Author: User
Tags addall arrays throwable
recently, not in the csdn to write articles, go to * Jane Book *, interested can pay attention to.

In the previous article, we introduced the use and application scenarios of spring MVC handlerinterceptor, and in this article we will study its internal implementation in conjunction with the Spring MVC source code.

This article analyzes the use of the spring Framework source code for the Spring Framework 4.3.4.RELEASE .

First, let's take a look at the Org.springframework.web.servlet.DispatcherServlet Dodispatch method:

    protected void Dodispatch (HttpServletRequest request, httpservletresponse response) throws Exception {Httpse
        Rvletrequest 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 | | Mappedhandler.gethandler () = = null) {Nohandlerfound (processedrequest, re
                    Sponse);
                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 [" + GETR
                    Equesturi (Request) + "] is:" + lastmodified);
                        } if (new Servletwebrequest (request, Response). Checknotmodified (lastmodified) && isget) {
                    Return }}//Call registered Handlerinterceptor's Prehandle () method if (!mappedhandler.applyprehan
                Dle (processedrequest, Response)) {return; }//Real execution Controller correspondenceMethod mv = Ha.handle (processedrequest, Response, Mappedhandler.gethandler ());
                if (asyncmanager.isconcurrenthandlingstarted ()) {return;
                } applydefaultviewname (Processedrequest, MV);
            Call the registered Handlerinterceptor Posthandle () method 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) {//Call registered HandlErinterceptor aftercompletion () method Triggeraftercompletion (processedrequest, Response, Mappedhandler, ex); } catch (Throwable err) {//Call the Aftercompletion () method of the registered Handlerinterceptor Triggerafterco Mpletion (processedrequest, Response, Mappedhandler, New Nestedservletexception ("Handler processing FAI
        Led ", err));  } finally {if (asyncmanager.isconcurrenthandlingstarted ()) {//Instead of Posthandle and aftercompletion if (mappedhandler! = null) {//calls the Afterconcu of registered Handlerinterceptor Rrenthandlingstarted () method mappedhandler.applyafterconcurrenthandlingstarted (processedrequest, response)
                ;
                }} else {//clean up any of the resources used by a multipart request.
                if (multipartrequestparsed) {Cleanupmultipart (processedrequest);
    }        }}}/** * Handle The result of handler selection and handler invocation, which is * ei
     Ther a modelandview or an Exception to is resolved to a modelandview. */private void Processdispatchresult (HttpServletRequest request, httpservletresponse response, Handlerexe

        Cutionchain Mappedhandler, Modelandview mv, Exception Exception) throws Exception {Boolean errorview = false; if (Exception! = null) {if (Exception instanceof Modelandviewdefiningexception) {log
                Ger.debug ("Modelandviewdefiningexception encountered", exception);
            MV = ((modelandviewdefiningexception) exception). Getmodelandview ();
                } else {Object handler = (Mappedhandler! = null? Mappedhandler.gethandler (): null);
                MV = processhandlerexception (request, response, handler, exception);
            Errorview = (mv! = null);

        }
        }Did the handler return a view to render?
            if (mv! = null &&!mv.wascleared ()) {render (MV, request, response);
            if (Errorview) {webutils.clearerrorrequestattributes (request); }} else {if (logger.isdebugenabled ()) {Logger.debug ("Null Modelandview Retu Rned to Dispatcherservlet with Name ' "+ getservletname () +" ': Assuming Handleradapter completed
            Request Handling ");  }} if (Webasyncutils.getasyncmanager (Request). Isconcurrenthandlingstarted ()) {//Concurrent
        Handling started during a forward return; if (Mappedhandler! = null) {//invokes the Aftercompletion () method of the registered Handlerinterceptor Mappedhandle
        R.triggeraftercompletion (request, response, NULL); }
    }

Next, let's take a look at the Applyprehandle method implementation of Handlerexecutionchain:

    /** * Performs the Prehandle method of registering all handlerinterceptor on the request */Boolean applyprehandle (HttpServletRequest request
        , httpservletresponse response) throws Exception {handlerinterceptor[] interceptors = getinterceptors (); if (! Objectutils.isempty (interceptors)) {for (int i = 0; i < interceptors.length; i++) {Handle
                Rinterceptor interceptor = interceptors[i]; if (!interceptor.prehandle (Request, Response, This.handler)) {triggeraftercompletion (Request, respons
                    e, NULL);
                return false;
            } this.interceptorindex = i;
    }} return true; } public handlerinterceptor[] Getinterceptors () {if (this.interceptors = = null && This.interceptorli St! = null) {this.interceptors = This.interceptorList.toArray (New Handlerinterceptor[this.interceptorlist.siz
        E ()]); } return This.interceptors;
 }

Handlerexecutionchain's Applyposthandle method implementation:

    /**
     * Performs the Posthandle method of registering all handlerinterceptor on the request *
    /void Applyposthandle (HttpServletRequest request, HttpServletResponse response, Modelandview mv) throws Exception {
        handlerinterceptor[] interceptors = Getinterceptors ();
        if (! Objectutils.isempty (interceptors)) {for
            (int i = interceptors.length-1; I >= 0; i--) {
                handlerinterceptor in Terceptor = Interceptors[i];
                Interceptor.posthandle (Request, Response, This.handler, MV);}}}
    

Handlerexecutionchain's Triggeraftercompletion method implementation:

    /**
     * Performs the Aftercompletion method of registering all handlerinterceptor on the request *
    /void Triggeraftercompletion ( HttpServletRequest request, HttpServletResponse response, Exception Ex)
            throws Exception {

        Handlerinterceptor [] interceptors = Getinterceptors ();
        if (! Objectutils.isempty (interceptors)) {for
            (int i = this.interceptorindex; I >= 0; i--) {
                Handlerinterceptor int Erceptor = Interceptors[i];
                try {
                    interceptor.aftercompletion (request, Response, This.handler, ex);
                }
                catch (Throwable ex2) {
                    logger.error ("Handlerinterceptor.aftercompletion threw exception", EX2);
                }
            }
        }
    }

Finally, Handlerexecutionchain's Applyafterconcurrenthandlingstarted method is implemented:

/** * Execute Asynchandlerinterceptor method of all afterconcurrenthandlingstarted registered to the request */ void applyafterconcurrenthandlingstarted (HttpServletRequest request, httpservletresponse response) {Handlerinte
        Rceptor[] interceptors = getinterceptors (); if (! Objectutils.isempty (interceptors)) {for (int i = interceptors.length-1; I >= 0; i--) {i F (interceptors[i] instanceof Asynchandlerinterceptor) {try {Asynchandlerint
                        Erceptor asyncinterceptor = (asynchandlerinterceptor) interceptors[i];
                    asyncinterceptor.afterconcurrenthandlingstarted (Request, response, This.handler); } catch (Throwable ex) {Logger.error ("interceptor [" + Interceptors[i] + "] f
                    Ailed in Afterconcurrenthandlingstarted ", ex); }
                }
            }
        }
    }

I add comments to the above methods, and the code is better understood, I will not talk nonsense.

Next, the interceptor array inside the Handlerexecutionchain is initialized at what time.

Look at the definition of Handlerexecutionchain class, the source code is as follows:

Package org.springframework.web.servlet;
Import java.util.ArrayList;
Import Java.util.Arrays;
Import java.util.List;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import Org.apache.commons.logging.Log;
Import Org.apache.commons.logging.LogFactory;
Import Org.springframework.util.CollectionUtils;

Import Org.springframework.util.ObjectUtils; public class Handlerexecutionchain {private static final Log logger = Logfactory.getlog (Handlerexecutionchain.class)

    ;

    Private final Object handler;

    Private handlerinterceptor[] interceptors;

    Private list 

Handlerexecutionchain provides the Addinterceptors () method to add Handlerinterceptor, where addinterceptors is called.

We return to Dispatcherservlet's Dodispatch method, as follows:

    protected void Dodispatch (HttpServletRequest request, httpservletresponse response) throws Exception {Httpse
        Rvletrequest 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);
                Gets the current request corresponding to the handler Mappedhandler = GetHandler (processedrequest); if (Mappedhandler = = NULL | | Mappedhandler.gethandler () = = null) {Nohandlerfound (processedrequest, re
                    Sponse);
                Return
            }
                ...
            }
      catch (Exception ex) {dispatchexception = ex;      } catch (Throwable 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 {...}  }/** * Gets the current request for the corresponding Handlerexecutionchain */protected Handlerexecutionchain gethandler (httpservletrequest Request) throws Exception {for (handlermapping hm:this.handlerMappings) {if (logger.istraceenable D ()) {Logger.trace ("Testing handler map [" + HM + "] in Dispatcherservlet with n
            Ame ' "+ getservletname () +" ' "); } HandlerexeCutionchain handler = Hm.gethandler (request);
            if (handler! = NULL) {return handler;
    }} return null; }

Then take a look at the GetHandler (request) method of handlermapping, Handlermapping is an interface, gethandler (request) The method is implemented in Abstracthandlermapping, as follows:

    @Override Public final Handlerexecutionchain gethandler (HttpServletRequest request) throws Exception {//
        Gets the request corresponding to the handler Object handler = gethandlerinternal (request);
        if (handler = = null) {handler = Getdefaulthandler ();
        } if (handler = = null) {return null;
        }//Bean name or resolved handler?
            if (handler instanceof string) {string handlerName = (string) handler;
        Handler = Getapplicationcontext (). Getbean (HandlerName); }//According to handler construction Handlerexecutionchain handlerexecutionchain executionchain = Gethandlerexecutionchain (Handl
        er, request); if (corsutils.iscorsrequest (Request)) {Corsconfiguration GlobalConfig = This.corsConfigSource.getCorsConfigur
            ation (Request);
            Corsconfiguration handlerconfig = getcorsconfiguration (handler, request); corsconfiguration config = (GlobalConfig! = null? globalconfig.combiNE (handlerconfig): Handlerconfig);
        Executionchain = Getcorshandlerexecutionchain (request, Executionchain, config);
    } return Executionchain; }/** * Constructs Handlerexecutionchain and initializes handlerinterceptor */protected Handlerexecutionchain Gethandlerex Ecutionchain (Object handler, HttpServletRequest request) {Handlerexecutionchain chain = (Handler instanceof Handl
                Erexecutionchain?

        (Handlerexecutionchain) Handler:new Handlerexecutionchain (handler));
        String Lookuppath = this.urlPathHelper.getLookupPathForRequest (request); for (Handlerinterceptor interceptor:this.adaptedInterceptors) {if (Interceptor instanceof Mappedinterceptor
                ) {Mappedinterceptor Mappedinterceptor = (mappedinterceptor) interceptor; if (Mappedinterceptor.matches (Lookuppath, This.pathmatcher)) {Chain.addinterceptor (mappedinterceptor.
                Getinterceptor ()); }
            } else {chain.addinterceptor (Interceptor);
    }} return chain; }

The

Source code analysis is here to end.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.