Spring MVC(2) - DispatcherServlet运行

Spring MVC(2) - DispatcherServlet运行流程

 

再次看一下类的继承结构



 

http请求在Servlet的业务处理流程

 

// Called by the servlet container to allow the servlet to respond to a request.
// javax.servlet.Servlet中定义的接口service,由 servlet container 调用
// 具体实现在HttpServlet类中
public void service(ServletRequest req, ServletResponse res) {
	HttpServletRequest	request;
	HttpServletResponse	response;
	
	try {
	    request = (HttpServletRequest) req;
	    response = (HttpServletResponse) res;
	} catch (ClassCastException e) {
	    throw new ServletException("non-HTTP request or response");
	}
	service(request, response);
    }
// HttpServlet类 此方法会将 请求转至 doGet doPost doDelete 等 方法
protected void service(HttpServletRequest req, HttpServletResponse resp){
}

// 类 FrameworkServlet 
protected final void doGet(HttpServletRequest request, HttpServletResponse response) {
      processRequest(request, response);
}
// 类 FrameworkServlet 
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) {
    try {
      // 此方法的实现在子类 DispatcherServlet
      doService(request, response);
    }
}

// 类 DispatcherServlet
protected void doService(HttpServletRequest request, HttpServletResponse response)  {

    // 核心逻辑
    doDispatch(request, response);
}

 

下面讲 DispatcherServlet的的核心处理流程

 

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
    // step1, 检查是否是文件上传,如果是,则由相应的bean对request转换
    processedRequest = checkMultipart(request);
    // step2, 根据request,获取 handler,在初始化过程中,
    // 会把url和对应的Controller和method映射关系存好
    // 在getHandler过程中,会遍历初始化时注册 HandlerMapping 的bean,
    // HandlerMapping会根据自己的规则去获取hander,即Controller和对应的method
    // 实际上一般是会遍历映射关系表获取的,获取不到会出错返回
    // 这一步还会吧所有的interceptor封装到handler中
    mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null || mappedHandler.getHandler() == null) {
        noHandlerFound(processedRequest, response);
        return;
    }

    // step3,获取支持第二步中的handler的HandlerAdapter, 
    // 实际就是从注册HandlerAdapter中选一个支持当前handler的
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    // 对 Get和Head请求,如果当前HandlerAdapter支持,则处理 last-modified
  
    // step4,应用handler的所有拦截器的preHandle方法,有一个false则返回
    // 注意如果有一个拦截器false,则会保证调用所有已经执行的拦截器的afterCompletion方法
    // 注意: preHandle 执行顺序 和 postHandle afterCompletion正好相反
    if (!mappedHandler.applyPreHandle(processedRequest, response)) { 
        return; 
    }

    // step5, handleradapter 触发 handler的方法调用,真正的url方法处理
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    // 如果view是空,设置默认view
    applyDefaultViewName(processedRequest, mv); 

    // step6, 应用拦截器的 postHandle 方法,
    // 注意: postHandle 方法可以处理 ModelAndView
    mappedHandler.applyPostHandle(processedRequest, response, mv);

    // step7, 对 ModelAndView 进行最后的渲染工作
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException) {
        // 进行渲染工作,具体过程为 使用Servlet初始化时注册的 ViewResolver,比如 InternalResourceViewResolver
        // 根据viewName,生成不同的view对象(通常是AbstractUrlBasedView子类 InternalResourceView )
        // 其中,会对viewName中的 “redirect:xx” 和 “forward:xx” 生成不通view类
        // 然后进行view类的属性填充,比如 suffix 和 prefix 加到url并设置到view类的属性中
        // View类具体处理是,最终会把Model中的属性设置到request中,根据url找到对应的RequestDispather
        // RequestDispather会把当前request和response关联到对应的资源,即Jsp文件
        render(mv, request, response);
        // 进行拦截器的afterCompletion调用
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
    // 最外侧的catch仍然保证拦截器的afterCompletion调用 
    catch(Excepton e) {
        // 进行拦截器的afterCompletion调用 
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
    
}

 

 

猜你喜欢

转载自ballenlee.iteye.com/blog/2395252