Spring mvc之控制调度中心DispatcherServl

2021-03-31  本文已影响0人  engineer_tang

1. 简介

HTTP请求处理程序/控制器的中央调度器,例如用于web UI控制器或基于HTTP的远程服务导出器。分派给已注册的处理程序以处理web请求,从而提供方便的映射和异常处理工具。

这个servlet非常灵活:它可以用于任何工作流,并安装适当的适配器类。它提供了以下功能,使其区别于其他请求驱动的web MVC框架:

注意:@RequestMapping注释只有在调度器中存在相应的HandlerMapping(对于类型级注释)和/或HandlerAdapter(对于方法级注释)时才会被处理。这是默认情况。但是,如果要定义自定义HandlerMappings或HandlerAdapter,则需要确保也定义了相应的自定义RequestMappingHandlerMapping和/或RequestMappingHandlerAdapter,前提是要使用@RequestMapping。

web应用程序可以定义任意数量的Dispatchers服务。每个servlet都将在自己的命名空间中运行,并用映射、处理程序等加载自己的应用程序上下文通过org.springframework.web.context.ContextLoaderListener,如果有,将共享。

从Spring3.1开始,DispatcherServlet现在可以注入web应用程序上下文,而不是在内部创建自己的上下文。这在Servlet3.0+环境中非常有用,它支持对Servlet实例进行编程注册。有关详细信息,请参阅DispatcherServlet(WebApplicationContext)javadoc。

2. 类结构

image.png

处理实际分派给handler程序。
handler程序将通过按顺序应用servlet的HandlerMappings来获得。handleAdapter将通过查询servlet安装的handleAdapter来获得,以找到第一个支持处理程序类的handleAdapter。所有HTTP方法都由此方法处理。由handleAdapter或处理程序自己决定哪些方法是可接受的。

    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.
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == 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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

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

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                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) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读