Back to Javatutorial

请求执行流程(一)之获取Handler

docs/Spring全家桶/SpringMVC源码分析/请求执行流程(一)之获取Handler.md

1.0.024.7 KB
Original Source

һƪǷ RequestMapping ʼ̣Ľ spring mvc ִ̡

1. ִ

spring mvc ֮ DispatcherServlet ʼһУ servlet DispatcherServlet һϵгʼ̣ĽΧ servlet springmvc ̡

1.1 ع servlet ִڣ

ڷ DispatcherServlet ǰҪع servlet ִڡ

ʵԶ servlet ʱһʵ HttpServletȻд doGet(xxx)``doPost() ʵ servlet Ϊ HttpServlet#service(ServletRequest, ServletResponse)

public abstract class HttpServlet extends GenericServlet {
    ...

    // ˲ת
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {

        HttpServletRequest  request;
        HttpServletResponse response;

        // ﴦת
        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        service(request, response);
    }

    /**
     * ﴦ
     * ӴԿʵһתж󷽷Ȼþķִ
     */
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String method = req.getMethod();

        // жϵ󷽷ȻҵӦķȥִ
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                doGet(req, resp);
            } else {
                ...
                doGet(req, resp);
            }
        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
        } else {
            // ûжӦķ
            ...
        }
    }

}

servlet Դ룬Ƚϼ򵥣ص㲿ֶעͣҪٴǿ£

  1. servlet ִΪ HttpServlet#service(ServletRequest, ServletResponse)
  2. HttpServlet#service(HttpServletRequest, HttpServletResponse) 󷽷ҵӦĴִУһ˵Զ servletֻҪд doGet(xxx)``doPost(xxx) ȷɡ

̴£

1.2 DispatcherServlet ĸࣺFrameworkServlet

˽ servlet ں󣬽͵÷һòˣFrameworkServlet``FrameworkServlet HttpServlet ࣬ʵ HttpServlet ĸ doXxx()ͬʱҲʵ service(HttpServletRequest, HttpServletResponse)

/**
 *  FrameworkServlet̳HttpServletBeanHttpServletBean̳HttpServlet
 *  FrameworkServletҲHttpServlet
 */
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    @Override
    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected final void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected final void doPut(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
        if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
            processRequest(request, response);
        }
        else {
            // GET/POST/PUT/DELETE 󷽷ǻøķ
            super.service(request, response);
        }
    }
}

ԿϴУһij൱ߣFrameworkServlet#processRequest doXxx(xxx) service(xxx) processRequest(xxx)Ǿʲô

FrameworkServlet#processRequest

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // ¼ʼʱ
    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;
    // ¼ǰ̵߳Ϣ
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = buildLocaleContext(request);
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = buildRequestAttributes(
            request, response, previousAttributes);
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), 
             new RequestBindingInterceptor());
    initContextHolders(request, localeContext, requestAttributes);
    try {
        // Ĵ
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    catch (Throwable ex) {
        failureCause = ex;
        throw new NestedServletException("Request processing failed", ex);
    }
    finally {
        // ̰߳Ϣ
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }
        logResult(request, response, failureCause, asyncManager);
        // ¼֪ͨ
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}

Ȼе㳤󲿷̹ϵصֻмУ

    ...
    try {
        // Ĵ
        doService(request, response);
    }
    catch (ServletException | IOException ex) {
        failureCause = ex;
        throw ex;
    }
    ...

ɴ˿Կʵʴķ FrameworkServlet#doService СFrameworkServlet#doService Ǹ󷽷

protected abstract void doService(HttpServletRequest request, 
        HttpServletResponse response) throws Exception;

ʵ࣬Ҳ DispatcherServlet#doService С

1.3 DispatcherServlet#doService

DispatcherServlet#doService ɶ£

public class DispatcherServlet extends FrameworkServlet {
    @Override
    protected void doService(HttpServletRequest request, 
            HttpServletResponse response) throws Exception {
        logRequest(request);
        // ʡһ
        ...
        try {
            // Ĵ
            doDispatch(request, response);
        }
        finally {
            ...
        }
    }
}

˷Ҳûʲôʵֻǵһ doDispatch ȻûˡʵϣDispatcherServlet#doDispatch մ߼ص

һܽ DispatcherServlet ̣

2. springmvc ַDispatcherServlet#doDispatch

һڵǷ springmvc ķ 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);
            // 1\. ȡӦhandler, 
            // HandlerаشControllerеķһHandlerInterceptor
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                // ûҵ404
                noHandlerFound(processedRequest, response);
                return;
            }
            // 2\. ȡӦhandlerAdapter handler(xxx)
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            // last-modified
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }
            // 3\. spring,  HandlerInterceptor#preHandle 
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }
            // 4\. ͨȡhandlerAdapterhandle
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }
            // ûзͼʹĬϵ
            applyDefaultViewName(processedRequest, mv);
            // 5\. ִ HandlerInterceptor#postHandle 
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }
        catch (Throwable err) {
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        // 6\. ؽȾͼԼִ HandlerInterceptor#afterCompletion
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (...) {
        // ִ HandlerInterceptor#afterCompletion
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                // صִз AsyncHandlerInterceptor#afterConcurrentHandlingStarted
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        }
        else {
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}

ڵ㳤̺springmvc ̶ˣѹؼչʾ£

  1. ȡӦ HandlerExecutionChain, ȡ HandlerExecutionChain аشController еķһ HandlerInterceptor
  2. ȡӦ handlerAdapterö handler(xxx)
  3. ִ spring HandlerInterceptor#preHandle
  4. Ҳͨȡ handlerAdapter handle(xxx)
  5. ִ spring HandlerInterceptor#postHandle
  6. ؽȾͼԼִ spring HandlerInterceptor#afterCompletion

ܵˣ̷ˡ

3. ȡ HandlerExecutionChain

ȡ HandlerExecutionChain ķ DispatcherServlet#getHandler У

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        // еhandlerMapping
        //  handlerMapping WebMvcConfigurationSupport
        for (HandlerMapping mapping : this.handlerMappings) {
            // þhandlerĸhandlerֱܹӷ
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

handlerMappings WebMvcConfigurationSupport ģһķܲο springmvc demo @EnableWebMvc עһģ handlerMappings Щɶ

RequestMappingHandlerMapping ŴѾϤ @Controller/@RequestMapping ʽʵֵ controllerӦ HandlerMapping RequestMappingHandlerMapping HandlerMappingֱӦͬʽʵֵ controllerһ㣬ȤСаٶȣͲչˡ

Ǽ AbstractHandlerMapping#getHandler

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 1\. þʵȥȡhandler
    Object handler = getHandlerInternal(request);
    // ΪʹĬϵ
    if (handler == null) {
        handler = getDefaultHandler();
    }
    // ûĬϵķؿ
    if (handler == null) {
        return null;
    }
    // ͨBeanNameȥȡhandler
    if (handler instanceof String) {
        String handlerName = (String) handler;
        handler = obtainApplicationContext().getBean(handlerName);
    }
    // 2\. ȡ executionChainʵҵ uri Ӧ Interceptors,
    // ȻҵhandlerһװHandlerExecutionChain
    // InterceptorsҲWebMvcConfigurationSupportõ
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    // 3\. ·صãCorsHandlerExecutionChain
    // ԿνcorsãҲʵֵ
    if (hasCorsConfigurationSource(handler)) {
        CorsConfiguration config = (this.corsConfigurationSource != null 
                ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        config = (config != null ? config.combine(handlerConfig) : handlerConfig);
        // صӵ InterceptorsӵListĵһ
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }
    return executionChain;
}

Ҫ£

  1. þʵȥȡ handlerص㣬
  2. ȡ executionChain executionChain ˰һ handleruri Ӧ InterceptorsȡΪȡе Interceptors ã WebMvcConfigurationSupport õģһж uri Ƿ Interceptor uri ã
  3. ȡ cors ãȻӵ executionChain е Interceptors бĵһλţûcors Ҳ WebMvcConfigurationSupport õġ

3.1 HandlerMethod

ǽ getHandlerInternal(xxx)

AbstractHandlerMethodMapping#getHandlerInternal

@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    // ȡurl
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    request.setAttribute(LOOKUP_PATH, lookupPath);
    this.mappingRegistry.acquireReadLock();
    try {
        // uriӦhandlerMethod
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        // handlerMethodΪգ´һHandlerMethod
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    finally {
        this.mappingRegistry.releaseReadLock();
    }
}

ﻹǵ lookupHandlerMethod(xxx) handlerMethod

AbstractHandlerMethodMapping#lookupHandlerMethod

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) 
        throws Exception {
    List<Match> matches = new ArrayList<>();
    // ȴurlLookupңurlLookupһmapkeyurlvalueLinkedList<RequestMappingInfo>
    List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
    if (directPathMatches != null) {
        // ڷصһ listеƥĽһmatches
        addMatchingMappings(directPathMatches, matches, request);
    }
    if (matches.isEmpty()) {
        // ͨurlûҵе mappings ƥ䣬ƥ /test/{name} url
        // mappingsҲһmapkeyRequestMappingInfo valueHandlerMethod
        addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
    }
    // ҵƥmapping,ӦHandlerMethod
    // ȽϹ RequestMappingInfo#compareTo
    if (!matches.isEmpty()) {
        Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
        matches.sort(comparator);
        Match bestMatch = matches.get(0);
        if (matches.size() > 1) {
            if (CorsUtils.isPreFlightRequest(request)) {
                return PREFLIGHT_AMBIGUOUS_MATCH;
            }
            Match secondBestMatch = matches.get(1);
            // ҵƥ䣬׳쳣
            if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                Method m1 = bestMatch.handlerMethod.getMethod();
                Method m2 = secondBestMatch.     .,m.bvc .getMethod();
                String uri = request.getRequestURI();
                throw new IllegalStateException(...);
            }
        }W
        request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
        handleMatch(bestMatch.mapping, lookupPath, request);
        return bestMatch.handlerMethod;
    }
    else {
        return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
    }
}

Ǵ handler ĻȡˡĻȡΪ裺

  1. ȴ urlLookup ңurlLookup һ map``key url``value LinkedList<RequestMappingInfo> map.get(xxx)
  2. ͨ url ûҵе mappings ƥ䣬ƥ /test/{name} url``mappings Ҳһ map``key RequestMappingInfo value HandlerMethod
  3. ҵ˶ HandlerMethod RequestMappingInfo#compareTo ṩķҵѵ RequestMappingInfo Ӧ HandlerMethod

mappings ҵƥ RequestMappingInfo ģ

AbstractHandlerMethodMapping#addMatchingMappings

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, 
            HttpServletRequest request) {
    for (T mapping : mappings) {
        // ƥҵз mappings
        T match = getMatchingMapping(mapping, request);
        if (match != null) {
            matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
        }
    }
}

շƥĴ RequestMappingInfo#getMatchingCondition УRequestMappingInfo һ compareTo Ҳһ鿴£

RequestMappingInfo

/**
 * ƥ
 * ֱƥ 󷽷(get,post)ͷ
 */
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
    RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
    if (methods == null) {
        return null;
    }
    ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
    if (params == null) {
        return null;
    }
    HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
    if (headers == null) {
        return null;
    }
    ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
    if (consumes == null) {
        return null;
    }
    ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
    if (produces == null) {
        return null;
    }
    PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
    if (patterns == null) {
        return null;
    }
    RequestConditionHolder custom = this.customConditionHolder.getMatchingCondition(request);
    if (custom == null) {
        return null;
    }
    return new RequestMappingInfo(this.name, patterns,
            methods, params, headers, consumes, produces, custom.getCondition());
}

/**
 * ȽϹҵƥ
 * ֱȽ 󷽷(get,post)ͷ
 */
public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
    int result;
    if (HttpMethod.HEAD.matches(request.getMethod())) {
        result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
        if (result != 0) {
            return result;
        }
    }
    result = this.patternsCondition.compareTo(other.getPatternsCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.paramsCondition.compareTo(other.getParamsCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.headersCondition.compareTo(other.getHeadersCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.consumesCondition.compareTo(other.getConsumesCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.producesCondition.compareTo(other.getProducesCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.methodsCondition.compareTo(other.getMethodsCondition(), request);
    if (result != 0) {
        return result;
    }
    result = this.customConditionHolder.compareTo(other.customConditionHolder, request);
    if (result != 0) {
        return result;
    }
    return 0;
}

ƥ䣬DZȽϣ󷽷 (get,post )ͷһһд

Ǿ springmvc ҵ HandlerMethod ˡ

3.2 Interceptors

ǻص AbstractHandlerMapping#getHandlerλȡ Interceptor ģ

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    ...
    // 2\. ȡ executionChainʵҵ uri Ӧ Interceptors,
    // ȻҵhandlerһװHandlerExecutionChain
    // InterceptorsҲWebMvcConfigurationSupportõ
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    ...
    return executionChain;
}

getHandlerExecutionChain

AbstractHandlerMapping#getHandlerExecutionChain

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, 
            HttpServletRequest request) {
    HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
            (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    // ȡǰ·
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
    for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
        if (interceptor instanceof MappedInterceptor) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
            // жϵǰ·Ƿinterceptorõ·
            if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
        else {
            chain.addInterceptor(interceptor);
        }
    }
    return chain;
}

Ƚϼ򵥣ѾڴעͣͲ˵

3.3 cors

õĴ

public final HandlerExecutionChain getHandler(HttpServletRequest request) 
        throws Exception {
    ...
    // 3\. ·صãCorsHandlerExecutionChain
    // ԿνcorsãҲʵֵ
    if (hasCorsConfigurationSource(handler)) {
        // ȡ
        CorsConfiguration config = (this.corsConfigurationSource != null 
                ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        config = (config != null ? config.combine(handlerConfig) : handlerConfig);
        // صӵ InterceptorsӵListĵһ
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }
    return executionChain;
}

Ҳ WebMvcConfigurationSupport ã

protected void addCorsMappings(CorsRegistry registry) {
    ...
}

springmvc ȡú󣬻ӵ HandlerExecutionChain У

# AbstractHandlerMapping#getCorsHandlerExecutionChain
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
        HandlerExecutionChain chain, @Nullable CorsConfiguration config) {
    if (CorsUtils.isPreFlightRequest(request)) {
        HandlerInterceptor[] interceptors = chain.getInterceptors();
        chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
    }
    else {
        // ӵInterceptorsλ
        chain.addInterceptor(0, new CorsInterceptor(config));
    }
    return chain;
}

# HandlerExecutionChain#addInterceptor(int, HandlerInterceptor)
public void addInterceptor(int index, HandlerInterceptor interceptor) {
    // ʵDzһlist
    initInterceptorList().add(index, interceptor);
}

HandlerExecutionChain Уһ List InterceptorȡĿãӵ List index=0 λá

handler ͻȡˣ handler ֣

  • HandlerMethod: ķڱֻ @Controller ʽ controllerԼΪ @RequestMapping עķ
  • List<Interceptor>: пãôû List ĵһλ

4. ȡ HandlerAdapter

ٻص DispatcherServlet#doDispatch ȡ HandlerAdapter ķ

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) 
        throws Exception {
            ...
    // 2\. ȡӦhandlerAdapter handler(xxx)
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    ...

getHandlerAdapter(xxx)

DispatcherServlet#getHandlerAdapter

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    // handlerAdapters beanҲWebMvcConfigurationSupport
    if (this.handlerAdapters != null) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            // ͬhandlerAdapterжϷͬ
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }
    throw new ServletException(...);
}

Կҵǰе adapterȻжǷܴǰ handlerе adapter £

жǷܴǰ handler ģǿһ handler AbstractHandlerMethodAdapter#supports

AbstractHandlerMethodAdapter#supports

@Override
public final boolean supports(Object handler) {
    // жhandlerǷΪHandlerMethodʵ
    return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

һ򵥵жϣȻٵ supportsInternal

RequestMappingHandlerAdapter#supportsInternal

protected boolean supportsInternal(HandlerMethod handlerMethod) {
    return true;
}

ֱӷ true, ڿɼ handler ʵ HandlerMethodôͻ᷵ RequestMappingHandlerAdapter.

һҵ adapter Ϊ RequestMappingHandlerAdapter adapter ʲôأƪľȵˣʣµƪ¼


ԭӣhttps://my.oschina.net/funcy/blog/4717420 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע