Spring MVC 执行流程源码解析

本文详细解析了Spring MVC的工作流程,包括客户端请求如何流转到DispatcherServlet,如何通过HandlerMapping找到处理器、HandlerAdapter执行以及拦截器的介入。重点讲解了处理器适配器、注解实现和拦截器处理的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

执行流程

总流程图

执行流程

1.客户端发送请求request到DispatcherServlet

2.DispatcherServlet根据请求url去HandlerMapping查找处理器handler,HandlerMapping会返回处理器执行链HandlerExecutionChain(其中包括拦截器和处理器)

3.DispatcherServlet通过handler去获取支持的处理器适配器HandlerAdapter

4.DispatcherServlet通过HandlerAdapter去执行处理器handler的方法

5.处理器handler执行方法后会返回ModelAndView

6.DispatcherServlet处理结果集,视图解析返回view,并填充model数据到view中渲染视图

前置流程

DispatcherServlet是Servlet,继承关系如下:

image-20211129092458417

Servlet中的service方法用于应答浏览器请求,每次请求都会调用该方法。由于DispatcherServlet中没有service方法,所以会调用父类FrameworkServlet#service方法,就从该方法入手:

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
       ...
          //调用父类HttpServlet#service
          super.service(request, response);
       }
    }

	//HttpServlet#service
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException{
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            //以处理get请求为例,调用doGet
                doGet(req, resp);
            ...
    //回到FrameworkServlet#doGet方法            
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}   
            
	//FrameworkServlet#processRequest
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		...
            //调用到子类DispatcherServlet#doService,由此进入核心流程代码
			doService(request, response);
		...

核心流程

    //DispatcherServlet
	@Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
       ...
          doDispatch(request, response);
       ...
    }
	
	//流程核心代码
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
        //处理器执行链    
		HandlerExecutionChain mappedHandler = null;
		...
				// 根据请求request去HandlerMapping查找处理器handler,返回处理器执行链HandlerExecutionChain
				mappedHandler = getHandler(processedRequest);
				...

				// 查找处理器适配器HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				...

				// 通过适配器去调用处理器方法,返回ModelAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				...
            //处理结果集,视图解析返回view,并填充model数据到view中渲染视图        
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		...
	}


	@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
                //根据请求去HandlerMapping中查找处理器Handler
				HandlerExecutionChain handler = mapping.getHandler(request);
				...
	}


	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
                //判断HandlerAdapter是否支持调用handler,如果支持就返回
				if (adapter.supports(handler)) {
					return adapter;
				...
	}
                

	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {
		...
			render(mv, request, response);
			...
    }
                
                
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
		String viewName = mv.getViewName();
		if (viewName != null) {
			// 解析视图名,返回视图对象view
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			...
            //将model数据填充到view中    
			view.render(mv.getModelInternal(), request, response);
		...
	}
                

标准控制器,SimpleControllerHandlerAdapter#handle,返回ModelAndView。这种控制器需要实现Controller,重写handleRequest方法

    @Override
    @Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
	   //调用处理器方法,返回ModelAndView
       return ((Controller) handler).handleRequest(request, response);
    }

视图对象,AbstractView#render

@Override
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
   ...    
   renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

InternalResourceView#renderMergedOutputModel

    @Override
    protected void renderMergedOutputModel(
          Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
       ...

       // Servlet的API,Servlet转发器
       RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
       ...
       if (useInclude(request, response)) {
          ...
          rd.include(request, response);
       }
       else {
          ...
          //跳到页面    
          rd.forward(request, response);
       }
    }

处理器实现方式

实现Controller

上述示例中的处理器实现方式,处理器适配器是SimpleControllerHandlerAdapter。

注解实现

目前最常用的是注解的实现方式@Controller,此时的处理器适配器而是RequestMappingHandlerAdapter,用于处理基于@requestMapping对应方法。

当调用到mv = ha.handle时,并没有RequestMappingHandlerAdapter对应的实现,而是调用AbstractHandlerMethodAdapter#handle方法

    @Override
    @Nullable
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       return handleInternal(request, response, (HandlerMethod) handler);
    }

handleInternal是抽象方法,由RequestMappingHandlerAdapter实现

    @Override
    protected ModelAndView handleInternal(HttpServletRequest request,
          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
       ...
           	 //调用handle方法,返回ModelAndView
             mav = invokeHandlerMethod(request, response, handlerMethod);
       ... 
           
	@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		...
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			...
	}
        
	//ServletInvocableHandlerMethod#invokeAndHandle
	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//调用处理器方法,returnValue是处理器返回值
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		...
	}        
        
	@Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		...
		return doInvoke(args);
	}  
        
	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		...
            //getBridgedMethod返回method实例,通过反射调用方法;
            //getBean返回对应的controller
			return getBridgedMethod().invoke(getBean(), args);
	}        

后续处理流程相同。

实现HttpRequestHandler

实现HttpRequestHandler,重写handleRequest,但是没有返回值void。处理器适配器是HttpRequestHandlerAdapter。

    @Override
    @Nullable
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
       ((HttpRequestHandler) handler).handleRequest(request, response);
       return null;
    }

拦截器处理

拦截器调用流程

拦截器处理 (1)

源码

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
       ...
             // 调用HandlerExecutionChain中的拦截器preHandle
             if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
             }

             // 通过适配器去调用处理器方法,返回ModelAndView
             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
             ...

             // 调用HandlerExecutionChain中的拦截器postHandle    
			 mappedHandler.applyPostHandle(processedRequest, response, mv);                 		   
      			...
    //调用HandlerExecutionChain中的拦截器afterCompletion          
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);   
    ...  
    
                 
    // HandlerExecutionChain#applyPreHandle         
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 获取所有的拦截器interceptors,遍历调用preHandle
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
                // preHandle返回true表示放行;返回false不放行
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}     
 
    // HandlerExecutionChain#applyPostHandle     
	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
			throws Exception {
		// 获取所有的拦截器interceptors,遍历调用postHandle
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}        

参数解析

注解实现方式其中调用方法的过程

    @Nullable
    public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
          Object... providedArgs) throws Exception {
	   //获取方法参数,以此为入口进入,不同参数方式的实现不同	
       Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
       ...
### JVM 类加载过程详解 #### 加载(Loading) 当 Java 应用启动时,类加载器子系统会将 `.class` 文件从磁盘读取到内存中。此阶段不仅限于找到所需的类文件并将其字节码加载到方法区,在必要情况下还会创建对应的 `java.lang.Class` 实例对象[^1]。 ```java // 假设有一个名为 MyClass 的类 public class MyClass { static { System.out.println("MyClass is being loaded."); } } ``` 上述代码展示了静态初始化块会在类首次加载时被执行一次。 #### 验证(Verification) 为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并不会危害虚拟机自身的安全,JVM 对输入的字节流进行数据流和语义分析[^2]。这一步骤对于防止恶意代码破坏现有程序逻辑至关重要。 #### 准备(Preparation) 在此阶段,JVM 将为类变量分配内存空间,并设置默认初始值(例如整数类型的零值)。需要注意的是实例字段并不会在这个阶段初始化其显式赋给它们的具体值;这一操作将在稍后的初始化阶段完成[^3]。 #### 解析(Resolution) 这是将常量池内的符号引用替换为直接引用的过程。所谓符号引用是以一组符号来描述目标,而直接引用则是指向方法区内存布局中的具体位置。解析工作可能发生在初始化之前或期间,取决于具体的实现方式和支持动态绑定的语言特性需求[^4]。 #### 初始化(Initialization) 此时才真正开始执行类中定义的 Java 程序代码(即常量赋值、静态代码块等),目的是让类达到预期的工作状态以便后续正常使用。只有经过正确初始化后,用户自定义的行为才会生效。 #### 使用(Using)与卸载(Unloading) 一旦类已经成功加载并通过了前面提到的所有步骤,它就可以被应用程序所用了。而在某些条件下——比如应用关闭或是永久代/元空间不足的情况下,不再需要的类可以从 JVM 中移除以释放资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值