源码梳理(2)SpringMVC的执行流程及涉及到的相关组件

1,Spring MVC核心组件DispatcherServlet

所有源码都来自springboot3.0.2,spring-webmvc-6.0.4

1.1 DispatcherServlet的继承关系

DispatcherServlet的继承关系

HttpServlet是抽象类,用于处理基于HTTP协议的请求和响应。

package jakarta.servlet.http;

public abstract class HttpServlet extends GenericServlet

HttpServletBean是Spring Framework中提供的一个抽象基类,用于简化开发自定义的Servlet类在 Spring环境中的配置和使用。

public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware

FrameworkServlet是Spring MVC框架中的一个重要组件,它是 DispatcherServlet的抽象基类之一。作为一个抽象类,FrameworkServlet提供了一些基本的功能,比如Servlet生命周期管理等

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware

DispatcherServlet是Spring MVC 框架中的核心组件,实现整个请求处理的流程,接下来会做详细分析

public class DispatcherServlet extends FrameworkServlet
1.2 DispatcherServlet的doDispatch方法

当HTTP请求打到服务器后,会先经过HttpServlet的service方法,然后执行到FrameworkServlet重写的service方法

	// HttpServlet.class
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {
        HttpServletRequest  request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        // FrameworkServlet重写了这个方法
        service(request, response);
    }

FrameworkServlet的service方法,如果是"DELETE", “HEAD”, “GET”, “OPTIONS”, “POST”, “PUT”, "TRACE"方法的请求会交给父类也就是HttpServlet的另一个(参数是HttpServletRequest,HttpServletResponse重载的)service方法,该service方法会根据请求类型,将任务再分发给doGet(),doPost()等方法,而这写方法都被FrameworkServlet重写了

	// FrameworkServlet.class
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		if (HTTP_SERVLET_METHODS.contains(request.getMethod())) {
			super.service(request, response);
		}
		else {
			processRequest(request, response);
		}
	}

FrameworkServlet重写的doGet,doPost等方法都是调用了processRequest方法

	// FrameworkServlet.class
	@Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

FrameworkServlet的核心方法processRequest,作用于处理客户端请求的整个流程,包括初始化上下文、调用doService方法处理请求、记录请求处理的结果和时间、无论结果如何发布请求处理完毕事件等。其中处理请求的核心方法doService由子类DispatcherServlet重写实现

	// FrameworkServlet.class
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 省略...
		try {
			// DispatcherServlet重写了这个方法
			doService(request, response);
		}
		// 省略...
	}

DispatcherServlet的doService方法的核心环节doDispatch方法

	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 省略...
		try {
			doDispatch(request, response);
		}
		// 省略...
	}

DispatcherServlet的doDispatch方法

	// DispatcherServlet.class
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		try {
			ModelAndView mv = null;
			Exception dispatchException = null;
			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);
				// 根据当前请求的特征来寻找并返回与之匹配的处理器执行链
				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
				// 确定当前请求的处理器适配器
				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				// 实际调用处理程序
				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new ServletException("Handler dispatch failed: " + err, err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new ServletException("Handler processing failed: " + err, err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}
2,核心组件HandlerMapping(处理器映射器)

HandlerMapping是处理器映射器,其作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器(Handler)信息。

	HandlerExecutionChain mappedHandler = null;
	// 省略...
	mappedHandler = getHandler(processedRequest);

在doDispatcher方法中,通过执行getHandler方法,获取到HandlerExecutionChain处理器执行链,并且准备好了针对当前请求最佳的处理器(比如自定义Controller组件中请求映射符合当前请求URL路径的某个方法),以及拦截器集合

	// DispatcherServlet.class
	@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

HandlerExecutionChain的主要属性

// 处理器执行链
public class HandlerExecutionChain {
	// 处理器
	private final Object handler;
	// 拦截器集合
	private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
	// 拦截器索引
	private int interceptorIndex = -1;
	// 省略...
}
3,核心组件HandlerAdapter(处理器适配器)

HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

在doDispatcher方法中,通过执行getHandlerAdapter方法,遍历所有处理器适配器,返回支持当前处理器的HandlerAdapter处理器适配器

	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

HandlerAdapter接口的两个方法

public interface HandlerAdapter {
	// 配置当前处理器适配器是否支持传入的处理器
	boolean supports(Object handler);
	// 执行处理
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
4,HandlerInterceptor拦截器

HandlerInterceptor的三个方法:
preHandle方法在处理程序执行之前被调用。它可以拦截请求,并在处理程序执行之前进行一些预处理操作。方法返回一个布尔值,如果是true,则继续执行处理程序;如果是false,则终止请求的处理。
postHandle 方法在处理程序执行之后、视图渲染之前被调用。它允许拦截并修改处理程序的结果模型和视图。您可以在此方法中添加一些公共的模型数据、修改视图或进行一些资源清理操作。
afterCompletion 方法是在整个请求处理完成后被调用,包括视图渲染完毕。此时拦截器可以进行一些资源清理工作,或者进行一些日志记录等。它接收一个 Exception 参数,用于捕获并处理请求处理过程中的异常。

public interface HandlerInterceptor {
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	}
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}
}

DispatcherServlet的doServlet方法中拦截器的处理时机

	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 省略...
		try {
			// 省略...
			try {
				// 省略...
				// 执行HandlerInterceptor的preHandle方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
				// 执行处理程序
				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				applyDefaultViewName(processedRequest, mv);
				//  执行HandlerInterceptor的postHandle方法
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			// 省略...
			// 在processDispatchResult方法最后调用了mappedHandler.triggerAfterCompletion(request, response, null)执行HandlerInterceptor的afterCompletion方法
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		// 省略
	}
5,核心组件Handler(处理器)

Handler是处理器,和Java Servlet扮演的角色一致。HandlerAdapter接口的handle方法通过Handler执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至ModelAndView对象中。

	ModelAndView mv = null;
	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

RequestMappingHandlerAdapter的继承关系

举例当HandlerAdapter的实现类RequestMappingHandlerAdapter调用handle方法时,因为自身没有实现handle方法,所以会执行父类AbstractHandlerMethodAdapter的handle方法,这个handle的类型是HandlerMethod。

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

RequestMappingHandlerAdapter实现了handleInternal方法,走后面的处理逻辑最终处理并返回ModelAndView

	@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// No synchronization on session demanded at all...
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}
6,ModelAndView(模型和视图)

handle处理程序返回的模型和视图,该模型和视图将由 DispatcherServlet 解析。视图可以是String 类型的视图名称,该名称需要由ViewResolver对象解析也可以直接指定View对象。该模型是一个 Map用于存储传输数据。

public class ModelAndView {

	/** View instance or view name String. */
	@Nullable
	private Object view;

	/** Model Map. */
	@Nullable
	private ModelMap model;

	/** Optional HTTP status for the response. */
	@Nullable
	private HttpStatusCode status;
}
7,核心组件HandlerExceptionResolver(异常处理器解析器)

HandlerExceptionResolver
异常处理器解析器是用于处理全局异常的组件,它可以捕获和处理控制器抛出的异常,然后决定如何对异常进行处理,例如返回错误页面、返回 JSON 错误信息等。
HandlerExceptionResolver接口就一个resolveException方法,通过这个方法来进行异常处理。

public interface HandlerExceptionResolver {
	@Nullable
	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}

在DispatcherServlet的doDispatch执行到processDispatchResult方法的时候,会在前面处理请求过程中捕获的可能出现的异常作为参数传递进去

	// DispatcherServlet.class
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			ModelAndView mv = null;
			Exception dispatchException = null;
			try {
				// 省略...
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new ServletException("Handler dispatch failed: " + err, err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		// 省略...
	}

如果传递的异常参数不为null,且不属于ModelAndViewDefiningException,则走processHandlerException方法的异常处理逻辑,并通过异常处理结果获得新的ModelAndView

	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;

		if (exception != null) {
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				// 异常处理
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			// Exception (if any) is already handled..
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

在processHandlerException方法中将遍历HandlerExceptionResolver并执行resolveException方法进行实际异常逻辑的处理,整个方法执行完则返回一个新的ModelAndView

	@Nullable
	protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
			@Nullable Object handler, Exception ex) throws Exception {
		// Success and error responses may use different content types
		request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
		// Check registered HandlerExceptionResolvers...
		ModelAndView exMv = null;
		if (this.handlerExceptionResolvers != null) {
			for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
				// 核心环节,遍历并执行HandlerExceptionResolver的resolveException方法
				exMv = resolver.resolveException(request, response, handler, ex);
				if (exMv != null) {
					break;
				}
			}
		}
		if (exMv != null) {
			if (exMv.isEmpty()) {
				request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
				return null;
			}
			// We might still need view name translation for a plain error model...
			if (!exMv.hasView()) {
				String defaultViewName = getDefaultViewName(request);
				if (defaultViewName != null) {
					exMv.setViewName(defaultViewName);
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using resolved error view: " + exMv, ex);
			}
			else if (logger.isDebugEnabled()) {
				logger.debug("Using resolved error view: " + exMv);
			}
			WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
			return exMv;
		}

		throw ex;
	}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>