Spring MVC 的调用(12)

目录

 SpringMVC流程

源码分析

 第一步:用户发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找 

1. 根据请求的uri拿到对应的HandlerMethod对象

第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)

第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)

第五步:处理器适配器去执行Handler 

ModelAndView演示 :


 SpringMVC流程

Spring MVC 的调用(12)_第1张图片

第一步:用户发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找

第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)

第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)

第五步:处理器适配器去执行Handler

第六步:Handler执行完给处理器适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView

第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析

第九步:视图解析器像前端控制器返回View

第十步:前端控制器对视图进行渲染

第十一步:前端控制器向用户响应结果

 此处需要强调的是

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

源码分析

 第一步:用户发起请求到前端控制器(DispatcherServlet)

其实就是前端请求调用到了DispatcherServlet的doService方法,而doService方法又调用到了doDispatch 核心方法:

Spring MVC 的调用(12)_第2张图片

而 doDispatch 方法负责整个Spring MVC的调度与响应,是核心中的核心:

Spring MVC 的调用(12)_第3张图片

第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找 

 其实,就是在doDispatch内部调用了 getHandler 方法,它会获取到所有的handlerMapping对象进行遍历,找到符合匹配规则的handlerMapping就直接返回:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//handlerMappering实例
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				//获取HandlerMethod和过滤器链的包装类
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

注意: 以上的for循环遍历所有的handlerMapping类,并且调用每个类的都调用了getHandler方法,是一个策略设计模式,可以避免大量的 if 判断。

这里,我们需要关注一下requestMappingHandlerMapping这个对象,因为上一篇博客中,我们提到了是在requestMappingHandlerMapping创建完以后建立映射关系的。遍历到requestMappingHandlerMapping对象后进入getHanlder方法 内部:

Spring MVC 的调用(12)_第4张图片

1. 根据请求的uri拿到对应的HandlerMethod对象

其实,就是调用 getHandlerInternal 方法的过程,上一讲我们提到根据 URL 和 requestMappingInfo建立了映射,而requestMappingInfo又和HandlerMethod建立了映射,此处肯定也是按照这个规则逐步去查找HandlerMethod对象的。 下面进行源码验证:

Spring MVC 的调用(12)_第5张图片

进入这个方法内部:

首先,我们发现它根据URL 拿到了 requestMappingInfo 对象:

Spring MVC 的调用(12)_第6张图片

 其次,根据requestMappingInfo拿HandlerMethod对象,进入这个方法内部进行确认:

Spring MVC 的调用(12)_第7张图片

第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
 

 主方法:

Spring MVC 的调用(12)_第8张图片

 进入这个方法内部,看看具体是如何 获取 HandlerExecutionChain 对象的
Spring MVC 的调用(12)_第9张图片

补充说明一下:拦截器是我们自己定义的,它有3个方法分别问前置过滤器、中置过滤器 和 后置过滤器:

package com.xiangxue.jack.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class UserInterceptor implements HandlerInterceptor {
    //前置过滤器
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("======UserInterceptor用户权限校验=========");
        return true;
    }

    //中置过滤器
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("========UserInterceptor修改modelAndView======");
    }

    //后置过滤器
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("========UserInterceptor资源释放======");
    }
}

 而拦截器是在 有 @EnableWebMvc的类, 并且这个类继承了 WebMvcConfigurerAdapter类 中添加进去的。

Spring MVC 的调用(12)_第10张图片

第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
 

回到核心方法 doDispatch 中,在这个方法内部调用了 getHandlerAdapter 进行获取处理器适配器的:

Spring MVC 的调用(12)_第11张图片

进入这个方法内部, 看看具体是如何获取到处理器适配器的:

Spring MVC 的调用(12)_第12张图片

第五步:处理器适配器去执行Handler 

第三步的时候说到了拦截器,其实在执行handler方法之前会进行 拦截器 中的前置过滤器的调用:

Spring MVC 的调用(12)_第13张图片

成功进入到了我们自己写的拦截器类中,并且调用到了前置过滤器方法:

Spring MVC 的调用(12)_第14张图片

 言归正传,处理器去执行handler,其实就是调用到我们的Controller类的对应方法而已。就是进入到业务类中,进行实际的业务调用。

Spring MVC 的调用(12)_第15张图片

还需要补充一点,中置过滤器的调用时序, 是当 ha.handle 掉完以后, 也就是 Controller 里面具体方法调用完以后才轮到中置过滤器调用。 而中置拦截器可以修改 modelAndView。

Spring MVC 的调用(12)_第16张图片

成功调到中置过滤器 Spring MVC 的调用(12)_第17张图片

ModelAndView就是最原始的Spring MVC返回值,如果使用了@ResponseBody注解或者其他注解改变返回值,那就没有ModelAndView了。

Spring MVC 的调用(12)_第18张图片

ModelAndView演示

首先定义jsp, 因为ModelAndView需要按照特定的规则去解析,需要有对应的jsp文件

Spring MVC 的调用(12)_第19张图片

 重写中置过滤器

Spring MVC 的调用(12)_第20张图片

设置MVC 的jsp路径:

Spring MVC 的调用(12)_第21张图片

Controller 类:

Spring MVC 的调用(12)_第22张图片

 

调用结果:

URL:  http://localhost:9090/user/queryUser?language=tw

页面:Spring MVC 的调用(12)_第23张图片

 URL: http://localhost:9090/user/queryUser?language=zh

页面:

Spring MVC 的调用(12)_第24张图片

 接下来的步骤分析很长,我们下一批博客继续分析。

你可能感兴趣的:(Spring源码,spring,mvc,java)