Java - SpringMvc 运行主流程

一、前端控制器

DispatcherServlet:

DispatcherServlet#doService(){
	//....
    doDispatch();//主体流程
    //....
}

DispatcherServlet#doDispatch(){
	//....
    //获取请求中指向的 Handler,返回 HandlerExecutionChain
    //HandlerExecutionChain中主要两个属性,【HandlerMapping对当前handler封装对象】+【当前Handler的拦截器数组】
    mappedHandler = getHandler(processedRequest);
    //....
    // 为当前Handler找一个合适的 HandlerAdapter,来执行此Handler
	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    //....
}
DispatcherServlet#getHandler() {
    //遍历工厂中的 HandlerMapping, HandlerMapping中记录着Handler的访问地址
    //但只有认识@RequestMapping注解的HandlerMapping,才真正记录着各个handler的访问地址
    for (HandlerMapping hm : this.handlerMappings) {
        if (logger.isTraceEnabled()) {
            logger.trace(
                "Testing handler map ...);
        }
        // 从HandlerMapping中获取 请求路径对应的Handler
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {//如果当前HandlerMapping可以识别当前请求,则返回
            return handler;
        }
    }
    return null;
}
                
DispatcherServlet#getHandlerAdapter(){
    for (HandlerAdapter ha : this.handlerAdapters) {
        // ....
        if (ha.supports(handler)) {// 遍历多个Adapter,选择一个适合当前Handler的Adapter
            return ha;
        }
    }
}
DispatcherServlet#doDispatch(){
	//....
    //获取请求中指向的 Handler,返回 HandlerExecutionChain
    //HandlerExecutionChain中主要两个属性,【HandlerMapping对当前handler封装对象】+【当前Handler的拦截器数组】
    mappedHandler = getHandler(processedRequest);
    //....
    // 为当前Handler找一个合适的 HandlerAdapter,来执行此Handler
	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    //....
    //执行拦截器的前置逻辑
    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
        return;
    }
    //紧接着,执行handler,返回一个ModelAndView
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    //.....
    //执行拦截器的后置逻辑
    mappedHandler.applyPostHandle(processedRequest, response, mv);
    //.....
    //视图渲染,在此方法内部解析完视图渲染后,会调用:
    // mappedHandler.triggerAfterCompletion(request, response, null);//拦截器的最终逻辑
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// processDispatchResult会调用此方法,进行视图渲染
DispatcherServlet#render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response){
    // ....
    // 解析出一个View对象,其实此View已经在ModelAndView中,在ha执行完handler后就存在了
    View view = resolveViewName(...);
    // ....
    // 调用View的渲染方法,内部将跳转视图,并响应请求
    view.render(....);
    // 常见的View类型:InternalResourceView用户处理转发跳转,内部使用 request.getRequestDispatcher().forward()
    //               RedirectView 用于处理重定向,内部使用 response.sendRedirect()
}

 二、启动细节

      第一次访问时,DispatcherServlet启动,启动中会初始化很多,系统组件( HandlerMapping, HandlerAdapter ... ),以及所有Controller。

ComponentScanBeanDefinitionParser 负责解析配置中的 context:component-scan,并扫描Controller,并创建 AnnotationDrivenBeanDefinitionParser 负责解析配置中的 mvc:annotation-driven,并创建对应组件

三、HandlerMapping 解析请求细节

        每种HandlerMapping都有一方法getHandlerInternal(request)为当前请求匹配并返回一个Handler,

但返回类型不一。所谓返回类型不一,是指如果找到匹配的Handler,封装的方法不同,即封装后的对象类型不同。

比如RequestMappingHandlerMapping的返回的是一个HandlerMethod

比如BeanNameUrlHandlerMapping的返回直接是一个Controller对象

 

细节:

        RequestMappingHandlerMapping中的getHandler方法,会调用getHandlerInternal()返回一个 HandlerMethod; 在getHandler方法中再封装进一个HandlerExecutionChain中。

        BeanNameUrlHandlerMapping中的getHandler方法,会调用getHandlerInternal()方法,方法中会先找到对应的Controller类,然后直接封装为HandlerExecutionChain,并返回给getHandler方法。

HandlerExecutionChain 中主要封装两类信息:当前handler 、handler的拦截器数组。

 

请求流程

一、响应正常格式

Java - SpringMvc 运行主流程_第1张图片

 

二、响应JSON格式(Json响应是靠 HttpMessageConverter,而不是View!

Java - SpringMvc 运行主流程_第2张图片

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java - SpringMvc 运行主流程)