SpringMVC 初始化及处理流程

1 篇文章 0 订阅
1 篇文章 0 订阅

 

 

Springmvc 作为使用最为广泛的web框架,它已取代Struts2,成为Java Web领域的不二霸主;作为一名后台开发人员,熟悉它的启动流程不仅有助于我们了解springmvc框架,更能帮助我们解决很多开发中遇到的问题。

Springmvc也是基于Servlet,所以的入口也是一个Servlet即GenericServlet,框架启动时会调用init方法,进行初始化,它其实是执行的是HttpServletBean的init方法,然后会调用FrameworkServlet的initervletBean,进行SpringWeb容器的初始化

 

进行WebApplicationContext初始化时会触发DispatcherServlet的onfresh方法,进行SpringMVC框架的初始化,做了9件事,完成整个MVC环境的初始化

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

	/**
	 * Initialize the strategy objects that this servlet uses.
	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
	 */
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}

这9件事分别完成了以下事情:

initMultipartResolver(context):用于处理文件上传,如果有文件上传,会将当前的HttpServletRequest包装成DefaultMultipartHttpServletRequest,并将上传的内容封装成CommonsMultipartFile对象;
initLocaleResolver(context):处理应用的国际化问题;
initThemeResolver(context):用于定义一个主题,如:根据用户的喜好设置用户访问的页面的样式;
initHandlerMappings(context):定义用户设置的请求映射关系;
initHandlerAdapters(context):根据Handler的类型定义不同的处理规则;
initHandlerExceptionResolvers(context):当Handler出错时,会通过这个Handler来统一处理,默认实现类是SimpleMappingExceptionResolver,将错误日志记录在log文件中,并转到默认的错误页面;
initRequestToViewNameTranslator(context):将指定的ViewName按照定义的RequestToViewNameTranslator替换成想要的格式,如加上前缀或者后置;
initViewResolvers(context):用于将View解析成页面,可在ViewResolvers中设置多个解析策略;
initFlashMapManager(context):用于准备DispatcherServlet处理请求时所使用的FlashMapManager策略组件对象。

至此,SpringMVC的环境准备完成,下面就可以接收我们的Http请求了,下面看看SpringMVC处理Http的流程,http请求会通过DispatcherServlet的doService进行处理,在doService中会将框架初始化时设置的handler和view处理对象设置到HttpServletRequest对象中,之后会调用核心处理方法doDispatcher

@Override
	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);
				}
			}
		}
	}

 在doDispatch方法中主要做完成几个步骤:

(1)请求HandlerMapping查找Handler,返回包含具体的处理器handler和多个拦截器的HandlerExecutionChain对象(getHandler方法)

(2) 根据request对象获取合适的处理器适配器,然后调用拦截器的前置处理方法

(3) 调用处理器适配器去执行Handler,完成后返回视图对象

(4) 调用拦截器的后置处理方法

(5) 进行视图解析(processDispatcherResult方法),并向前端控制器返回View

(6) 在DispatcherServlet返回结果之前会执行拦截器的afterCompletion防范

(7) 前端控制器向用户响应结果

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 || mappedHandler.getHandler() == 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 = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					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 NestedServletException("Handler dispatch failed", err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", 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);
				}
			}
		}
	}

SpringMVC框架做为主流web框架,继承了spring框架的优秀设计理念,提供了许多可扩展接口,方便用户自定义扩展,但是想要深入理解它还是需要多阅读它的源码,了解它架构设计理念,学习之路还很漫长,共勉。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值