SpingMVC解析

SpingMVC解析_第1张图片
springMVC (2).jpg

这是一个最经典的SpringMVC执行流程图,其中最核心的三个地方是: HandlerMappingHandlerAdapterHttpMessageConverter

首先,从DispatcherServlet入手,先看下DispatcherServlet继承图:

SpingMVC解析_第2张图片
DispatcherServlet.png

从图可以得知,DispatcherServlet本质上就是Servlet,那么Servlet生命周期最主要的的三个方法时:void init(ServletConfig config),void service(ServletRequest request,ServletResponse response),void destroy()。
看了源代码之后发现DispatcherServlet里面根本没有service这个方法,这个时候找到它的父类FrameworkServlet ,


SpingMVC解析_第3张图片
sercice.png
SpingMVC解析_第4张图片
processRequest.png
SpingMVC解析_第5张图片
doService.png

doDispatch,最主要的方法,用来分发请求,核心的逻辑都在这里面(截图有限,自己看源码吧)

SpingMVC解析_第6张图片
doDispatcher.png
SpingMVC解析_第7张图片
doDispatcher2.png

主要的:
1.checkMultipart方法检查是否是二进制的请求(文件上传的请求)

SpingMVC解析_第8张图片
checkMultipart.png

2.mappingHandler=getHandler(request)

SpingMVC解析_第9张图片
doDispatcher (2).png

返回的是HandlerExecutionChain(处理执行链)

SpingMVC解析_第10张图片
DispatcherServlet (2).png

再看DispatcherServlet.properties其实就是包装了不同的Mapping来判断通过何种方式来配置。

HandlerExecutionChain(处理执行链)包含两部分内容,一部分是请求对应的控制器,一部分是拦截器,真正执行handle之前,有一系列操作,例如数据转换,格式化,数据验证这些,都是由拦截器来做的

另外需要注意的是,假如你自定义了n个拦截器,会发现HandlerExecutionChain会有n+1个拦截器,说明有一个是他内部有的,从这里我们可以知道它的执行顺序,比如这里要先执行拦截器,再执行我们控制器,所以这个东西被称为处理执行链

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

![Uploading applyPreHandler_524696.png . . .]

SpingMVC解析_第11张图片
getHandlerAdapter.png

HandlerAdapater(处理器适配器),用来执行handler(控制器,即contorller)
这里判断handler适不适合这个RequestMappingAdapter,适合就返回

if(ha.supports(handler))
         return ha;

获取方法类型

String method = reqyest,getMethod();
 if(!mappedHandler.applyPreHandle(processedRequest, response)){
            return;
  }
SpingMVC解析_第12张图片
applyPreHandler.png

这里主要遍历拦截器。

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

这里去调用handler方法,这个方法会做很多事情,比如参数自动装入。

然后是

    @RequestMapping(value = "/golist.do")
    public ModelAndView golist(HttpServletRequest request) {
        return new ModelAndView("/views/module/advise/list.jsp");
    }

再继续

//默认视图名称
 applyDefaultViewName(request, mv);

像下面这个 返回的只有model 没有 view

@RequestMapping(value = "/saveEntity.do")
    public @ResponseBody AjaxResult saveByEntity(HttpServletRequest request, Advise entity) {
        LoginUser loginUser = LoginUserUtil.getCurrentUser(request);
        adviseService.saveEntity(loginUser, entity);
        return AjaxResult.warpAjaxResult(true);
}

继续往下

 mappedHandler.applyPostHandle(processedRequest, response, mv);
 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)
        throws Exception
    {
        if(getInterceptors() == null)
            return;
        for(int i = getInterceptors().length - 1; i >= 0; i--)
        {
            HandlerInterceptor interceptor = getInterceptors()[i];
            interceptor.postHandle(request, response, handler, mv);
        }
    }

从这里我们知道,Interceptor的执行顺序是反过来的:如图

SpingMVC解析_第13张图片
Interceptor.png

再继续

 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 ? null : mappedHandler.getHandler();
                mv = processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        if(mv != null && !mv.wasCleared())
        {
            render(mv, request, response);
            if(errorView)
                WebUtils.clearErrorRequestAttributes(request);
        } else
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Null ModelAndView returned to DispatcherServlet with name '").append(getServletName()).append("': assuming HandlerAdapter completed request handling").toString());
        if(WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted())
            return;
        if(mappedHandler != null)
            mappedHandler.triggerAfterCompletion(request, response, null);
    }
 protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        Locale locale = 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((new StringBuilder()).append("Could not resolve view with name '").append(mv.getViewName()).append("' in servlet with name '").append(getServletName()).append("'").toString());
        } else
        {
            view = mv.getView();
            if(view == null)
                throw new ServletException((new StringBuilder()).append("ModelAndView [").append(mv).append("] neither contains a view name nor a ").append("View object in servlet with name '").append(getServletName()).append("'").toString());
        }
        if(logger.isDebugEnabled())
            logger.debug((new StringBuilder()).append("Rendering view [").append(view).append("] in DispatcherServlet with name '").append(getServletName()).append("'").toString());
        try
        {
            //这里决定究竟是转发还是重定向,或者说变成其他视图
            view.render(mv.getModelInternal(), request, response);
        }
        catch(Exception ex)
        {
            if(logger.isDebugEnabled())
                logger.debug((new StringBuilder()).append("Error rendering view [").append(view).append("] in DispatcherServlet with name '").append(getServletName()).append("'").toString(), ex);
            throw ex;
        }
    }
  public void render(Map model, HttpServletRequest request, HttpServletResponse response)
        throws Exception
    {
        if(logger.isTraceEnabled())
            logger.trace((new StringBuilder()).append("Rendering view with name '").append(beanName).append("' with model ").append(model).append(" and static attributes ").append(staticAttributes).toString());
        Map mergedModel = createMergedOutputModel(model, request, response);
        prepareResponse(request, response);
        renderMergedOutputModel(mergedModel, request, response);
    }

你可能感兴趣的:(SpingMVC解析)