springmvc处理请求源码

2020-09-11  本文已影响0人  sunpy
springmvc处理请求.jpg

1. FrameworkServlet抽象类设计

DispatcherServlet继承抽象类FrameworkServlet,最终父类为HttpServlet,本质上还是Servlet来处理请求。


代码结构设计思路:实现处理请求的doGet方法,其中doGet方法共性的流程都是doGet方法委派给processRequest方法,processRequest方法委派给doService方法。而doService是抽象方法,由继承FrameworkServlet的个性子类来实现doService的个性化内容方法(模板方法模式)。

    // 处理请求,将请求委派给processRequest和doService
    @Override
    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        processRequest(request, response);
    }
    // 处理请求
    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 ex) {
            failureCause = ex;
            throw ex;
        }
        catch (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();
            }

            if (logger.isDebugEnabled()) {
                if (failureCause != null) {
                    this.logger.debug("Could not complete request", failureCause);
                }
                else {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        logger.debug("Leaving response open for concurrent processing");
                    }
                    else {
                        this.logger.debug("Successfully completed request");
                    }
                }
            }

            publishRequestHandledEvent(request, startTime, failureCause);
        }
    }

2.DispatcherServlet处理请求入口(doService方法)

如果后面需要处理国际化和一些主题样式等,先在向后传的reuqest请求中,设置themeResolver主题样式解析器和localeResolver国际化解析器等属性。主要还是将请求委派到doDispatch方法去实现。

// 确定请求request的一些属性并且委派给doDispatch方法处理请求
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isDebugEnabled()) {
        String requestUri = urlPathHelper.getRequestUri(request);
        String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
        logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
                " processing " + request.getMethod() + " request for [" + requestUri + "]");
    }

    // 保留请求属性的快照,将当前的属性遍历保存到attributesSnapshot
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        logger.debug("Taking snapshot of request attributes before include");
        attributesSnapshot = new HashMap<String, Object>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }

    // 确保框架对象对于处理器和视图对象可用
    // 请求中保存一些主题属性和国际化解析器属性等
    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

    FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
    if (inputFlashMap != null) {
        request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
    }
    request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
    request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

    try {
        doDispatch(request, response);
    }
    finally {
        if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            return;
        }

        // 还原请求的属性快照
        if (attributesSnapshot != null) {
            restoreAttributesAfterInclude(request, attributesSnapshot);
        }
    }
}

3. doDispatch方法核心处理:处理请求,派发到不同的handler处理器

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.
            // 1 根据请求获取对应处理器映射HandlerMapping
            // 返回执行链
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // 2 获取处理器适配器
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // 3 请求是否发生修改,未修改采取本地缓存
            
            // 获取请求方法
            String method = request.getMethod();
            // 判断请求是否为GET请求
            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;
                }
            }

            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            try {
                // 4 真正调用处理请求程序,返回ModelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            }
            finally {
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
            }
            
            // 重置为默认的视图名称
            applyDefaultViewName(request, mv);
            // 调用已注册拦截器的方法
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }
        // 5 ViewResolver解析视图
        // 调用render方法渲染物理视图View
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception ex) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    catch (Error err) {
        triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            // Instead of postHandle and afterCompletion
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            return;
        }
        // Clean up any resources used by a multipart request.
        if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
        }
    }
}

说明,粗略地分为5个步骤:
① 根据请求获取对应处理器映射HandlerMapping,返回执行链
② 获取处理器适配器
③ 请求是否发生修改,未修改直接返回,采取本地缓存
④ 真正调用处理请求程序,返回ModelAndView
⑤ ViewResolver解析视图,渲染物理视图View


// 获取请求对应的HandlerExecutionChain
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
        if (logger.isTraceEnabled()) {
            logger.trace(
                    "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
        }
        // 获取请求对应的HandlerExecutionChain处理器执行链
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

// 获取请求对应的HandlerExecutionChain处理器执行链
// 如果不存在,那么返回特定的处理器执行链
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 根据请求获取处理器执行链
    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);
    }
    // 封装处理器为处理器执行链并返回
    return getHandlerExecutionChain(handler, request);
}
// 获取handler处理器对应的HandlerAdapter适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    for (HandlerAdapter ha : this.handlerAdapters) {
        if (logger.isTraceEnabled()) {
            logger.trace("Testing handler adapter [" + ha + "]");
        }
        // 判断HandlerAdapter是否支持handler处理器
        if (ha.supports(handler)) {
            return ha;
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this 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;
    }
}

// 检查是否修改过请求,通过ETAG确定资源,lastmodifiedtime来确定修改时间
@Override
public boolean checkNotModified(long lastModifiedTimestamp) {
    if (lastModifiedTimestamp >= 0 && !this.notModified &&
            (this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) {
        long ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);
        this.notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000));
        if (this.response != null) {
            if (this.notModified && METHOD_GET.equals(getRequest().getMethod())) {
                this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
            else {
                this.response.setDateHeader(HEADER_LAST_MODIFIED, lastModifiedTimestamp);
            }
        }
    }
    return this.notModified;
}
@Override
protected final ModelAndView handleInternal(HttpServletRequest request,
        HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
    // 检查支持的方法和所需的会话,并应用给定的缓存秒数
    if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
        
        checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
    }
    else {
        // Uses configured default cacheSeconds setting.
        checkAndPrepare(request, response, true);
    }

    // Session互斥锁
    if (this.synchronizeOnSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object mutex = WebUtils.getSessionMutex(session);
            synchronized (mutex) {
                return invokeHandleMethod(request, response, handlerMethod);
            }
        }
    }

    // 为视图解析做准备
    return invokeHandleMethod(request, response, handlerMethod);
}

通过反射的方式调用请求的方法,譬如我们Controller定义的方法

// 在给定请求的上下文中解析其参数值后调用该方法。
public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    // 获取当前请求方法的参数
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        StringBuilder sb = new StringBuilder("Invoking [");
        sb.append(this.getBeanType().getSimpleName()).append(".");
        sb.append(getMethod().getName()).append("] method with arguments ");
        sb.append(Arrays.asList(args));
        logger.trace(sb.toString());
    }
    // 反射方式,使用参数调用给定的方法
    Object returnValue = invoke(args);
    if (logger.isTraceEnabled()) {
        logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
    }
    return returnValue;
}
// 渲染视图
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) {
            logger.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 returned 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) {
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

// 渲染ModelAndView
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 解析请求中的国际化
    Locale locale = this.localeResolver.resolveLocale(request);
    // 设置到响应中
    response.setLocale(locale);

    View view;
    if (mv.isReference()) {
        // 解析视图名称
        view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException(
                    "Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +
                            getServletName() + "'");
        }
    }
    else {
        // No need to lookup: the ModelAndView object contains the actual View object.
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
                    "View object in servlet with name '" + getServletName() + "'");
        }
    }

    // Delegate to the View object for rendering.
    if (logger.isDebugEnabled()) {
        logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
    }
    try {
        // 将model填充到view即可
        view.render(mv.getModelInternal(), request, response);
    }
    catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '"
                    + getServletName() + "'", ex);
        }
        throw ex;
    }
}

// 遍历视图解析器,将视图解析为物理视图
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
        HttpServletRequest request) throws Exception {

    for (ViewResolver viewResolver : this.viewResolvers) {
        View view = viewResolver.resolveViewName(viewName, locale);
        if (view != null) {
            return view;
        }
    }
    return null;
}
上一篇下一篇

猜你喜欢

热点阅读