DispatcherServlet ---探险历程

1.springMVC的基本配置,我们都知道当我们搭建springMVC时都会去在web.xml中编写DispatcherServlet的配置,如下:

<!-- springMvc的核心前端控制器DispatcherServlet -->
  <servlet>
     <servlet-name>springMvc</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	     <init-param>
	      <!-- 必须指定springmvc的初始化路径  参数为contextConfigLocation  -->
	      <!-- 可以自定义servlet.xml配置文件的位置和名称,默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如springMvc-servlet.xml-->
			<param-name>contextConfigLocation</param-name>
			<!-- 此处为空会报错 Could not open ServletContext resource [/WEB-INF/springMvc-servlet.xml] -->
			<!--  如果配置了spring的ContextLoaderListener监听器会默认去找/WEB-INF/applicationContext.xml-->
			<!-- spring是父容器,springmvc是子容器 -->
			<!-- 此处作为spring的简单实现  ,必须在配置文件中指定扫描包让spring可以找到容器 -->
			<param-value>classpath:springMvc-servlet.xml</param-value>
		</init-param>
     <load-on-startup>1</load-on-startup>
	  </servlet>
	  <!-- 拦截路径 -->
	  <servlet-mapping>
	      <servlet-name>springMvc</servlet-name>
	      <url-pattern>/</url-pattern>
	  </servlet-mapping>

那么DispatcherServlet到底是什么,做了些什么,让我们来一起探索

2.DispatcherServlet本质上可以说是一个Servlet,我们来看一下它的结构

在这里插入图片描述
我们都知道写一个Servlet都是继承HttpServlet,重写doGet和doPost方法,那HttpServeltBean又为我们做了什么呢,我们分析一下

我们这里先从源头分析DispatcherServlet说起,我们只截取部分核心的代码

1.首先加载DispatcherServlet.properties配置文件中的默认属性

private static final Properties defaultStrategies;
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
	static {
		try {
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
		}
	}

2.请求调用doService方法在request中设置一些属性

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) + "]");
	}
	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);
			}
		}
	}
}

3.核心方法 doDispatch,这里才是Dispatcher的核心逻辑

  • 3.1 getHandler(request) 通过request中的@RequestMapping获取到 请求的路径交给handerMapping处理,返回HandlerExecutionChain 请求链对象 (交给请求处理器处理)
    3.2 getHandlerAdapter(HandlerExecutionChain) 通过 HandlerExecutionChain找到对应的handlerDispatcher处理
    (交给处理器适配器处理) 找到对应的handerDispather
    3.3 handle(processedRequest, response, mappedHandler.getHandler());
    handlerDispatcher处理请求
    3.4 applyDefaultViewName(processedRequest, mv);
    将request中的名称和modelAndView绑定到一块
    getDefaultViewName(HttpServletRequest request) 将请求转换成视图名称
    3.5 View resolveViewName(String viewName, Map<String, Object> model, Locale locale,HttpServletRequest request)

    将给定的视图名称解析为View对象(要渲染)
    3.6 render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
    渲染请求,返回到jsp

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

    }
    4.最后上一张流程图帮助大家理解springMvc的大致流程
    在这里插入图片描述

根据上图可以更加清楚springMvc的流程
1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、 执行处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值