SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)

getHandler(processedRequest);

  • 为此请求返回HandlerExecutionChain。按顺序尝试所有的handler mapping
  • SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)
  • 获取当前请求对应的处理类,在这个处理链中会包含对应的拦截器的信息。HandlerExecutionChain这个类中包含变和不变量的两部分内容
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

循环handlerMappings,然后获取对应的执行链,只要找到一个对应的执行链就返回


SpringMVC默认加载三个请求处理映射类:


RequestMappingHandlerMapping

SimpleUrlHandlerMapping

BeanNameUrlHandlerMapping

这三个类有一个共同的父类:AbstractHandlerMapping。


hm.getHandler(request)这个getHandler方法在AbstractHandlerMapping中,它的子类都没有重写这个方法。

AbstractHandlerMethodMapping#getHandler

@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 两个子类重写该方法:AbstractHandlerMethodMapping和AbstractUrlHandlerMapping
    Object handler = getHandlerInternal(request);
    // 如果没有找到的话,默认处理类
    if (handler == null) {
        handler = getDefaultHandler();
    }
    // 如果没有默认的处理类,返回null
    if (handler == null) {
        return null;
    }
    // Bean name or resolved handler?
    if (handler instanceof String) {
        String handlerName = (String) handler;
        handler = getApplicationContext().getBean(handlerName);
    }
    // 包装为执行器链
    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    // 是不是跨域请求
    if (CorsUtils.isCorsRequest(request)) {
        CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
        CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
        CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    }
    return executionChain;
}

AbstractHandlerMethodMapping#getHandlerInternal

    @Override
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        // 得到请求 url 的查询路径
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        }
        // 获取并发读锁
        this.mappingRegistry.acquireReadLock();
        try {
            // 得到查询路径对应的处理器方法
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
            return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
        }
        finally {
            this.mappingRegistry.releaseReadLock();
        }
    }

getHandlerExecutionChain

创建执行器链的内容:

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    //判断handler是不是执行器链,如果不是创建一个执行器链
    HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
            (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;
}

这个方法主要是创建执行器链,添加拦截器.

判断

if (mappedHandler == null || mappedHandler.getHandler() == null) {
    noHandlerFound(processedRequest, response);
    return;
}

如果没有找到对应的处理类的话,这里通常会返回404,如果throwExceptionIfNoHandlerFound属性值为true的情况下会抛出异常。

我们继续往下分析:

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

getHandlerAdapter

获取处理适配器

SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)

SimpleControllerHandlerAdapter

适配SimpleUrlHandlerMapping和BeanNameUrlHandlerMapping的映射的,也就是实现Controller接口的Handler

AbstractHandlerMethodAdapter

适配RequestMappingHandlerMapping,也就是我们常用的RequestMapping注解

HttpRequestHandlerAdapter

适配远程调用的

SimpleServletHandlerAdapter

适配Servlet实现类的

supports

SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)

supportsInternal

总是返回true ,因为任何方法参数和返回值类型会以某种方式加以处理。

不被任何HandlerMethodArgumentResolver识别的方法参数被解释为一个请求参数,如果它是一个简单的类型,或者作为模型属性否则。

没有任何HandlerMethodReturnValueHandler识别的返回值将被解释为一个模型属性

SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)

如果是GET请求,内容没有变化则直接返回

applyPreHandle

  • 应用已注册的preHandle拦截方法
  • SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)
  • SpringMVC源码解析DispatcherServlet#doDispatch方法流程(下)

handle()

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

执行handle

applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);

如果返回的mv不为null,并且没有设置view,则设置默认的view

应用postHandle拦截器。

processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
        HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
 
    boolean errorView = false;
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        }
        else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }
    //返回的ModelAndView不为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 (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        // Concurrent handling started during a forward
        return;
    }
    // 调用处理拦截器的afterCompletion
    if (mappedHandler != null) {
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

如果


出现异常,返回异常页面

没有异常,ModelAndView不为null,则正常渲染页面,调用拦截器的afterCompletion方法


上一篇:compass tables 表格 表格常见样式[Sass和compass学习笔记]


下一篇:mysql5.7安装审计插件libaudit_plugin.so