SpringMVC源码分析(一)之DispatcherServlet

     我们知道SpringMVC的入口是DispatcherServlet,想进一步了解springMVC的技术内幕就得从这个servlet着手

     首先我们看下DispatcherServlet的Diagram关系图:



   HttpServletBean继承自HttpServlet  覆写了 init方法 

public final void init() throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing servlet '" + getServletName() + "'");
		}

		// Set bean properties from init parameters.
		try {
			PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);//获取配置属性
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//通过BeanWrapper构造DispatcherServlet
			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
			initBeanWrapper(bw);
			bw.setPropertyValues(pvs, true);//设置属性
		}
		catch (BeansException ex) {
			logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
			throw ex;
		}

		// Let subclasses do whatever initialization they like.
		initServletBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Servlet '" + getServletName() + "' configured successfully");
		}
	}



 initServletBean() 在 FrameworkServlet 中覆写  主要是关联servlet到spring上下文中


DispatcherServlet覆写了 FrameworkServlet的 onRefresh方法

protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context); 
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);//请求映射处理初始化
		initHandlerAdapters(context); //请求适配初始化
		initHandlerExceptionResolvers(context);//处理异常初始化
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);//视图解析 初始化
		initFlashMapManager(context);
	}



DispatcherServlet处理请求的过程

 我们知道servlet处理请求 会根据请求方式不同  调用不同的方法 例如 doGet ,doPost等等,但最终还是都调用processRequest 而该方法会调用 doService方法

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("org.springframework.web.servlet")) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// request域中设置一些属性
		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方法大概分为4步:

1,保存现场,保存request快照,以便后续可以恢复

2,将需要的对象放入request中,以便后续使用

3,分发服务

4,恢复快照

doDispatch方法:

     


HandlerMethod内部handle的时候,使用各种
HandlerMethodArgumentResolver实现类处理HandlerMethod的参数,使用各种
HandlerMethodReturnValueHandler实现类处理返回值。 最终返回值被处理成ModelAndView
对象,这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值