美文网首页
Spring mvc之控制调度中心DispatcherServl

Spring mvc之控制调度中心DispatcherServl

作者: engineer_tang | 来源:发表于2021-03-31 06:52 被阅读0次

1. 简介

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

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

  • 它基于JavaBeans配置机制。

  • 它可以使用任何基于HandlerMapping接口的实现(预构建或作为应用程序的一部分提供)来控制请求到handler对象的路由。默认值为org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping. HandlerMapping对象可以在servlet的应用程序上下文中定义为bean,实现HandlerMapping接口,覆盖默认HandlerMapping(如果存在)。HandlerMappings可以被赋予任何bean名称(它们是按类型测试的)。

  • 它可以使用任何handleAdapter;这允许使用任何处理程序接口,默认适配器为org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter, org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,Spring的org.springframework.web.HttpRequestHandler和org.springframework.web.servlet.mvc.Controller 接口。违约org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter文件也将注册。handleAdapter对象可以作为bean添加到应用程序上下文中,从而覆盖默认的handleAdapter。与HandlerMappings一样,HandlerAdapter可以被赋予任何bean名称(它们是按类型测试的)。

  • 调度器的异常解决策略可以通过HandlerExceptionResolver指定,例如将某些异常映射到错误页。默认值为org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver, org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,以及org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver。这些handlerExceptionResolver可以通过应用程序上下文重写。HandlerExceptionResolver可以被赋予任何bean名称(它们是按类型测试的)。

  • 它的视图解析策略可以通过ViewResolver实现指定,将符号视图名称解析为视图对象。默认值为org.springframework.web.servlet.view.InternalResourceViewResolver. ViewResolver对象可以作为bean添加到应用程序上下文中,从而覆盖默认的ViewResolver。ViewResolver可以被赋予任何bean名称(它们是按类型测试的)。

  • 如果用户未提供视图或视图名称,则配置的RequestToViewNameTranslator将当前请求转换为视图名称。对应的bean名称是“viewNameTranslator”;默认值是org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator.

  • 调度器解决multipart 请求的策略由MultipartResolver 实现决定。包括Apache Commons FileUpload 和 Servlet 3的实现;典型的选择是org.springframework.web.multipart.commons.CommonsMultipartResolver. MultipartResolver 名称是“multipartResolver”;默认值是none。

  • 它的locale解析策略由LocaleResolver决定。开箱即用的实现通过HTTP接受头、cookie或会话工作。LocaleResolver bean名称是“localeResolver”;默认值是org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver。

  • 它的主题分解策略由主题求解器决定。包括固定主题、cookie和会话存储的实现。ThemeResolver bean名称是“themeResolver”;默认值是org.springframework.web.servlet.theme.FixedThemeResolver.

注意:@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);
                }
            }
        }
    }

相关文章

网友评论

      本文标题:Spring mvc之控制调度中心DispatcherServl

      本文链接:https://www.haomeiwen.com/subject/dizwhltx.html