zoukankan      html  css  js  c++  java
  • Spring源码分析-SpringMVC核心功能DispatcherServlet

    SpringMVC的核心功能是DispatcherServlet

     
    执行步骤:
    (1)用户发送请求至前端控制器DispatcherServlet(调用doDispatch方法);
    (2)DispatcherServlet 通过 HandlerMapping 找到与Request请求URL相匹配的HandlerExecutionChain,并返回给DispatcherServlet(HandlerExecutionChain封装了Handler对象);
    (3)DispatcherServlet 通过 handler 找到相应的 HandlerAdapter 处理器适配器,并返回给DispatcherServlet;
    (4)DispatcherServlet 通过 HandlerAdapter 调用具体处理器,即执行Controller 中相应的处理方法,并返回ModelAndView给DispatcherServlet(ModelAndView:Model用于视图渲染,View用于视图解析) ;
    (5)DispatcherServlet 通过 ViewResolver 找到与viewName匹配的 View,并返回给DispatcherServlet(视图解析);
    (6)DispatcherServlet 通过 View 将Model数据进行内容填充,生成新的结果页面 View(视图渲染);
    (7)DispatcherServlet 将结果页面返回给用户(返回响应)。

    1.用户发送请求,执行DispatchServlet 中的doService方法

        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);
    
                    // 2.去HandlerMapping中拿到 handler
                    mappedHandler = getHandler(processedRequest);
                    // 如果HandlerMapping没有这个请求映射,则直接返回。如静态资源的拦截
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // 3.通过handler来拿到HandlerAdapter
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                    
                    // 省略部分代码
                    
                    // 4.通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView
                    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);
                }
                // 处理转发结果,包括出现异常时异常视图的解析及渲染
                // 5.视图解析,通过 ViewResolver 返回View对象
                // 6.视图渲染,通过 view.render 方法将Model渲染成视图
                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            }
            // 省略部分代码
        }

    2.映射处理器,去HandlerMapping中拿到 handler

    这一步是执行 mappedHandler = getHandler(processedRequest); 

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化
        for (HandlerMapping hm : this.handlerMappings) {
            // 
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

    3.处理适配器,通过handler来拿到HandlerAdapter

    这一步执行的是 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化
        for (HandlerAdapter ha : this.handlerAdapters) {
            // 
            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");
    }

    4.调用处理器相应功能方法,通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView

    这里执行的是 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

    @Override
    protected ModelAndView handleInternal(HttpServletRequest request,
                                          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
        ModelAndView mav;
        checkRequest(request);
        // 省略部分代码...
        // Execute invokeHandlerMethod in synchronized block if required.
        if (this.synchronizeOnSession) {
            // 
        } else {
            // 代码关键部分
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }
        // 省略部分代码...
    
        return mav;
    }
    
    
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                               HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        try {
            // 省略部分代码...
    
            // 代码关键部分:方法调用,执行Controller 中的方法
            invocableMethod.invokeAndHandle(webRequest, mavContainer);
            if (asyncManager.isConcurrentHandlingStarted()) {
                return null;
            }
            return getModelAndView(mavContainer, modelFactory, webRequest);
        }
        finally {
            webRequest.requestCompleted();
        }
    }

     下面这个方法就是 视图解析 + 视图渲染

    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

    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");
            }
        }
        // 省略部分代码...
    }

    5.视图解析,通过 ViewResolver 返回View对象

    这一步执行的是 view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); 

    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // Determine locale for request and apply it to the response.
        Locale locale = this.localeResolver.resolveLocale(request);
        response.setLocale(locale);
    
        View view;
        if (mv.isReference()) {
            // 代码关键部分:通过 ViewResolver 返回View对象
            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() + "'");
            }
        }
        // 省略部分代码...
    }
    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;
    }

    6.视图渲染,通过 view.render 方法将Model渲染成视图

    这一步调用的是 view.render(mv.getModelInternal(), request, response);

    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // Determine locale for request and apply it to the response.
        Locale locale = this.localeResolver.resolveLocale(request);
        response.setLocale(locale);
    
        View view;
        // 省略部分代码...
        try {
            if (mv.getStatus() != null) {
                response.setStatus(mv.getStatus().value());
            }
            // 通过 view.render 方法将Model渲染成视图,及将新的视图返回给页面
            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;
        }
    }
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (logger.isTraceEnabled()) {
            logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
                         " and static attributes " + this.staticAttributes);
        }
    
        Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
        prepareResponse(request, response);
        // 将Model渲染成新的视图并响应请求
        renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
    }
  • 相关阅读:
    Spring MVC 入门示例讲解
    使用Word2013,发布博文到博客园
    走过2103,迈向2014
    C#中的字符串拼接@,$
    ORA-22922:nonexistent LOB value问题及listagg()函数
    证明一个数是不是存在于该数组中
    论java中System.arrayCopy()与Arrays.copyOf()的区别
    JSP中获取各种路径的方法
    JavaScript中变量声明有var和没var的区别
    JavaScript:理解事件循环
  • 原文地址:https://www.cnblogs.com/caoxb/p/12379977.html
Copyright © 2011-2022 走看看