第11章 Spring MVC执行流程

第十一章 SpringMVC 执行流程

11.1 从源码角度看执行流程

以下是核心代码:

java 复制代码
public class DispatcherServlet extends FrameworkServlet {
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 根据请求对象request获取
        // 这个对象是在每次发送请求时都创建一个,是请求级别的
        // 该对象中描述了本次请求应该执行的拦截器是哪些,顺序是怎样的,要执行的处理器是哪个
        HandlerExecutionChain mappedHandler = getHandler(processedRequest);

        // 根据处理器获取处理器适配器。(底层使用了适配器模式)
        // HandlerAdapter在web服务器启动的时候就创建好了。(启动时创建多个HandlerAdapter放在List集合中)
        // HandlerAdapter有多种类型:
        // RequestMappingHandlerAdapter:用于适配使用注解 @RequestMapping 标记的控制器方法
        // SimpleControllerHandlerAdapter:用于适配实现了 Controller 接口的控制器
        // 注意:此时还没有进行数据绑定(也就是说,表单提交的数据,此时还没有转换为pojo对象。)
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        // 执行请求对应的所有拦截器中的 preHandle 方法
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
        }

        // 通过处理器适配器调用处理器方法
        // 在调用处理器方法之前会进行数据绑定,将表单提交的数据绑定到处理器方法上。(底层是通过WebDataBinder完成的)
        // 在数据绑定的过程中会使用到消息转换器:HttpMessageConverter
        // 结束后返回ModelAndView对象
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        //  执行请求对应的所有拦截器中的 postHandle 方法
        mappedHandler.applyPostHandle(processedRequest, response, mv);

        // 处理分发结果(在这个方法中完成了响应)
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }

    // 根据每一次的请求对象来获取处理器执行链对象
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
            // HandlerMapping在服务器启动的时候就创建好了,放到了List集合中。HandlerMapping也有多种类型
            // RequestMappingHandlerMapping:将 URL 映射到使用注解 @RequestMapping 标记的控制器方法的处理器。
            // SimpleUrlHandlerMapping:将 URL 映射到处理器中指定的 URL 或 URL 模式的处理器。
			for (HandlerMapping mapping : this.handlerMappings) {
                // 重点:这是一次请求的开始,实际上是通过处理器映射器来获取的处理器执行链对象
                // 底层实际上会通过 HandlerMapping 对象获取 HandlerMethod对象,将HandlerMethod 对象传递给 HandlerExecutionChain对象。
                // 注意:HandlerMapping对象和HandlerMethod对象都是在服务器启动阶段创建的。
                // RequestMappingHandlerMapping对象中有多个HandlerMethod对象。
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {
        // 渲染
        render(mv, request, response);
        // 渲染完毕后,调用该请求对应的所有拦截器的 afterCompletion方法。
        mappedHandler.triggerAfterCompletion(request, response, null);
    }

    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 通过视图解析器返回视图对象
        view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
        // 真正的渲染视图
        view.render(mv.getModelInternal(), request, response);
    }

    protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
			Locale locale, HttpServletRequest request) throws Exception {
        // 通过视图解析器返回视图对象
        View view = viewResolver.resolveViewName(viewName, locale);
	}
}
java 复制代码
public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;
}
java 复制代码
public interface View {
    void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
			throws Exception;
}

11.2 从图片角度看执行流程

11.3 WEB服务器启动时都做了什么

先搞明白核心类的继承关系:

DispatcherServlet extends FrameworkServlet extends HttpServletBean extends HttpServlet extends GenericServlet implements Servlet

服务器启动阶段完成了:

  1. 初始化Spring上下文,也就是创建所有的bean,让IoC容器将其管理起来。
  2. 初始化SpringMVC相关的对象:处理器映射器,处理器适配器等。
相关推荐
小白的一叶扁舟7 分钟前
深入剖析 JVM 内存模型
java·jvm·spring boot·架构
sjsjsbbsbsn15 分钟前
基于注解实现去重表消息防止重复消费
java·spring boot·分布式·spring cloud·java-rocketmq·java-rabbitmq
苹果醋316 分钟前
golang 编程规范 - Effective Go 中文
java·运维·spring boot·mysql·nginx
chengpei1471 小时前
实现一个自己的spring-boot-starter,基于SQL生成HTTP接口
java·数据库·spring boot·sql·http
等一场春雨2 小时前
Java设计模式 十二 享元模式 (Flyweight Pattern)
java·设计模式·享元模式
qw9493 小时前
Spring 6 第6章——单元测试:Junit
spring·junit·单元测试
努力搬砖的程序媛儿3 小时前
uniapp悬浮可拖拽按钮
java·前端·uni-app
上海拔俗网络4 小时前
“AI开放式目标检测系统:开启智能识别新时代
java·团队开发
Leaf吧4 小时前
springboot 配置多数据源以及动态切换数据源
java·数据库·spring boot·后端
荆州克莱4 小时前
Golang的网络编程安全
spring boot·spring·spring cloud·css3·技术