SpringMVC源码深度解析之DispatcherServlet源码分析

DispatcherServlet源码分析

SpringMVC核心就是DispatcherServlet,所有得请求都会转发到DispatcherServlet,然后再通过DispatcherServlet执行具体得控制层(Handler)返回ModelAndView给客户端视图展示。

// 3. 将我们的DispatcherServlet 注入到 serlvet容器中
ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(app));
// 4.填写url路径映射
dynamic.addMapping("/");

DispatcherServlet其实就是一个Servlet类,无非就是包装一层,通过url能够映射找到我们得SpringMvc中定义得请求方法。

源代码分析:

  1. 类的集成关系

DispatcherServlet继承FrameworkServlet继承HttpServlet 面向基本上思想 重写 先走父类 ,在走子类。 得出答案:先看HttpServlet在找到我们最后的子类

protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

DispatcherServlet与Servlet关系

关系:DispatcherServlet继承FrameworkServlet继承HttpServlet

流程执行关系:

HttpServlet service方法 判断请求方法的类型 FrameworkServlet doService DispatcherServlet doService

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  ...
    try {
        try {
     ...
                mappedHandler = this.getHandler(processedRequest);    //通过url路径地址去查找控制层类方法,如果没有找到的化,直接返回404
    ....
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
               ....
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
          ....
                mappedHandler.applyPostHandle(processedRequest, response, mv);
....
}

SpringMVC源码之定位Handler原理

private List<HandlerMapping> handlerMappings;
mappedHandler = this.getHandler(processedRequest);
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}
/**
 * 请求方法前置拦截,如果返回true 表示会执行到目标方法(请求方法) 如果返回false的情况下 则不会执行目标方法。
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String token = request.getParameter("token");
    System.out.println(">>>>token<<<<:" + token);
    if (StringUtils.isEmpty(token)) {
        response.setStatus(500);
        response.getWriter().print(" token is null");
        return false;
    }
    // 执行我们的请求方法
    return true;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

执行目标方法:

@RequestMapping("/pageIndex")
public String pageIndex() {
    System.out.println(">>>pageIndex<<<<");
    return "pageIndex";
}
mappedHandler.applyPostHandle(processedRequest, response, mv);
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("<<<postHandle>>>>");
    // 请求之后执行。
}

DispatcherServlet源码流程分析

1.执行doDispatch 2.调用getHandler方法获取请求目标的方法 也就是 请求url映射路径对应的控制层具体的方法 handlerMappings的作用查找控制器位置,比如xml和注解方式。 3.调用getHandlerAdapter获取控制层适配器 RequestMappingHandlerAdapter 4.执行拦截器前置方法 preHandle() 如果返回为true的话 5.执行实际请求目标方法 返回modeAndView对象 6.执行拦截器PostHandle()方法 7.设置渲染视图层内容 8.执行拦截器afterCompletion方

SpringMVC控制层容器初始化

  1. HttpServletBean init ()方法
  2. FrameworkServlet initServletBean方法→ initWebApplicationContext();
  3. DispatcherServlet onRefresh方法→ initStrategies()方法
protected void onRefresh(ApplicationContext context) {
    this.initStrategies(context);
}

当我们servlet容器初始化的时候初始化

this.initHandlerMappings(context);

protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); //初始化上传文件解析器(或者是多部分请求解析器) initLocaleResolver(context);//初始化本地化解析器 initThemeResolver(context);//初始化主题解析器 initHandlerMappings(context);//初始化处理器映射器 initHandlerAdapters(context);//初始化处理器适配器 initHandlerExceptionResolvers(context);//初始化处理器异常解析器 initRequestToViewNameTranslator(context);//初始化请求到视图名翻译器 initViewResolvers(context);//初始化视图解析器 initFlashMapManager(context);//初始化重定向数据管理器 }

本文参考

蚂蚁课堂

http://www.mayikt.com/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券