关于前端:springMVC执行流程详解

2次阅读

共计 3479 个字符,预计需要花费 9 分钟才能阅读完成。

springMVC 执行流程

一,springMVC 执行流程

1,MVC 架构的由来

次要由 model 层,view 层和 controller 层组成。

1.1,jsp 模型

次要是构造简略,开发这个小型我的项目的效率高,次要是由这个 jsp 和 javaBean 组成。然而 jsp 同时负责了 controller 层和 view 层,因而所有的代码都写在这个 jsp 外面,导致这个代码的重用性很低,保护不不便,因而这种架构被淘汰。

1.2,servlet 模型

对上一个模型进行了一次改进,将这个 controller 层和 view 层进行了这个拆散,让每个局部各司其职。申请由 controller 控制器实现,jsp 就是专门用来展现数据,进步了代码可重用性和易维护性。

2,springMVC 执行流程

1,客户端发送申请到这个 DispatcherServlet 前端控制器

2,前端控制器会通过这个 HandlerMapping 处理器映射器,找到适合的处理器,就是通过这个输出的 url,找到对应的 handler

3,返回处理器的执行链,外面会蕴含多个拦截器的信息,以及须要查找的处理器 handler 的信息

4,找处理器适配器 HandlerAdapter,这一步开始就会去调用 handler 外面的办法

5,通过执行这个 handler 外面的办法,会去找具体的 controller 办法

6,找到具体的 controller 之后,会返回一个 modelAndView 给这个 HanderAdapter 给处理器适配器

7,处理器适配器获取到 ModelAndView 之后,会将这个后果返回给 DispatcherServlet 前端控制器

8,通过这个 ViewResolver 视图解析器进行解析这个 ModelAndView

9,解析实现之后,会将这个 view 返回给前端 DispatcherServlet 前端控制器

10,将 model 中的数据填充到这个 view 视图外面,最初去渲染视图

二,源码剖析

1,首先关上这个 DispatcherServlet 类,能够发现这个类是继承了 FrameworkServlet

public class  DispatcherServlet  extends  FrameworkServlet{...}

2,这个类外面有一个 doService 办法,外面有一个比拟重要的办法,叫 doDispatch 办法

doDispatch(request, response);

3,进入这个 doDispatch() 办法外面,能够看到以下几行代码,次要是来返回这个处理器执行链,处理器适配器等操作。

// 处理器执行链
HandlerExecutionChain mappedHandler = null;
// 检测以后申请是否须要做文件上传
processedRequest = checkMultipart(request);
// 获取须要的映射器以及拦截器等
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {noHandlerFound(processedRequest, response);
    return;
}
// 找这个处理器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 调用拦截器 
mappedHandler.applyPreHandle(processedRequest, response);
// 适配器开始调用这个 handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 解决这个后果集
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

4,接下来所有的剖析都基于这个 doDispatch() 办法,来对外面的办法做一个具体的形容。

接下来看看这个 getHandler 办法,次要是通过这个 request 申请,来获取对应 handler。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) { 
        // 遍历全副获取到的处理器映射器
        for (HandlerMapping hm : this.handlerMappings) { 
            // 通过这个申请进行匹配,找到这个 handler
            HandlerExecutionChain handler = hm.getHandler(request);
            // 找到则返回
            if (handler != null) {return handler;}
        }
    }
    return null;
}

5,接下来看看这个获取处理器适配器 getHandlerAdapter 的办法,适配器也有多种,会依据不同的 handler 适配不同的适配器。

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {if (this.handlerAdapters != null) {for (HandlerAdapter ha : this.handlerAdapters) {if (ha.supports(handler)) {return ha;}
        }
    }
    throw new ServletException();}

6,再看这个 doDispatch 办法中的 handle 办法,能够点进去发现具体的实现如下。最终会以一个 controller 的对象返回

public  ModelAndView  handle(HttpServletRequest request,  HttpServletResponse response,  Object handler)  throws  Exception  { 
    // 以一个 controller 的形式返回 
    return ((Controller) handler).handleRequest(request, response);
}

7,能够自定义重写这个 handleRequest 办法,最初以一个 ModelAndView 的格局返回给这个解决适配器,处理器适配器将这个 ModelAndView 返回给前端控制器。

@Override
public  ModelAndView  handleRequest(HttpServletRequest request,  HttpServletResponse response)  throws  Exception  {ModelAndView mv = new ModelAndView();
    mv.setViewName("success");
    mv.addObject("hello","zhs");
    return mv;
}

8,接下来看看这个前端控制器解决这个 ModelAndView 的视图解析,次要是通过这个 processDispatchResult 办法来实现。

if (mv != null && !mv.wasCleared()) { 
    // 如果这个 modelAndView 不为空,就会开始进入正式的解析
    render(mv, request, response);
    if (errorView) {WebUtils.clearErrorRequestAttributes(request);
    }
}

再进入这个 render 办法外面,能够发现这个视图解析器会对这个视图进行一个具体的解析,并且会将解析的 view 返回给这个 DispatcherServlet 外面,最终会将这个数据进行一个转发或者重定向,对这个 view 进行一个渲染,最终响应到这个客户端。

// 会进行一个具体的解析
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
// 解析
view.render(mv.getModelInternal(), request, response);
// 输入
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
// 对这个获取的数据进行转发或者重定向
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
正文完
 0