SpringMVC源码学习

一、SpringMVC请求处理流程

在这里插入图片描述

二、SpringMVC各组件功能说明

名称中文含义提供者说明
DispatcherServlet前端控制器框架提供负责请求分发,处理响应结果,相当于是SpringMVC的总管家,本质是个Servlet
HanlerMapping处理器映射器框架提供负责URL到Controller的映射,根据request查找处理的Handler
HandlerAdapter处理器适配器框架提供负责执行对应的处理器Handler或Controller
Handler处理器用户提供处理器又名Controller,接收请求数据,进行业务处理,返回响应结果
ViewResolver视图解析器框架提供解析物理视图,返回逻辑视图对象View
View渲染后的视图用户提供如HTML、JSP、FreeMarker,将数据展现给用户

三、SpringMVC主要源码解读

3.1、DispatcherServlet组件详解

在这里插入图片描述

DispatcherServlet作为SpringMVC的总管家,根据继承关系,它继承自HttpServlet,那么它其实是一个Servlet,既然是Servlet类,那么他有一个最终的方法,就是service()方法,他是Servlet最核心的方法。查看代码可知,其中关键的核心实现主要集中在DispatcherServlet.doService方法上

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isDebugEnabled()) {
			String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
			logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
					" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
		}

		// Keep a snapshot of the request attributes in case of an include,
		// to be able to restore the original attributes after the include.
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// Make framework objects available to handlers and view objects.
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		if (inputFlashMap != null) {
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

		try {
			doDispatch(request, response);
		}
		finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// Restore the original attribute snapshot, in case of an include.
				if (attributesSnapshot != null) {
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
		}
	}

doService方法内,主要看doDispatch(request, response)方法,该方法首先根据当前请求,循环所有的处理器映射器this.handlerMappings,得到一个HandlerExecutionChain对象

mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
	noHandlerFound(processedRequest, response);
	return;
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

HandlerExecutionChain对象从名字上看是对执行链的封装,我们看下HandlerExecutionChain定义:

public class HandlerExecutionChain {

	private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);

	private final Object handler;

	private HandlerInterceptor[] interceptors;
	

在这里插入图片描述

1、一个Object handler,对执行器的一个封装,里面包含了本次请求对应的Controller等信息。
2、一个拦截器数组HandlerInterceptor[] interceptors,拦截器HandlerInterceptor提供了3个方法preHandle、postHandle、afterCompletion

  • preHandle:在处理器handler处理请求之前被调用。相当于预处理,可以进行编码、安全控制、权限校验等处理。
  • postHandle:在业务处理器handler处理请求执行完成后,生成视图之前执行。
  • afterCompletion:在DispatcherServlet完全处理完请求后(已经渲染了页面)被调用,可用于清理资源等。

回到主线代码,在得到一个HandlerExecutionChain对象后,然后执行了getHandlerAdapter(mappedHandler.getHandler()),通过此方法来获得一个处理器适配器对象HandlerAdapter

// 确定当前请求的处理器适配器
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
			if (ha.supports(handler)) {
				return ha;
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

getHandlerAdapter(Object handler)其方法内部也是通过循环所有的处理器适配器,来确定将由哪个适配器来负责处理,该方法返回一个HandlerAdapter对象。
通过HandlerAdapter中的handle方法处理handler对象,并返回ModelAndView这个包含了视图和数据的对象。

可见在DispatcherServlet中,除了HandlerMapping列表,也有HandlerAdapter列表

ModelAndView mv = null;
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

得到ModelAndView对象后,后续就是渲染视图了

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
/**
 * Handle the result of handler selection and handler invocation, which is
 * either a ModelAndView or an Exception to be resolved to a ModelAndView.
 */
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
		HandlerExecutionChain mappedHandler, ModelAndView mv, 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.isDebugEnabled()) {
			logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
					"': assuming HandlerAdapter completed request handling");
		}
	}

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

	if (mappedHandler != null) {
		mappedHandler.triggerAfterCompletion(request, response, null);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值