`
zhangwei_david
  • 浏览: 468794 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring MVC之DispatcherServlet请求处理

阅读更多

    处理请求是MVC中的C(Control)部分,他是MVC的核心内容。在初始化上下文是将所有的HandlerMapping都加载到handlerMappings中且根据Order排序。每个HandlerMapping 都持有URL到Controller的映射关系。

在MVC初始化完成之后,对Http请求的处理是在doService()方法中完成的。DispatcherServlet是HttptServlet的子类,对Http请求的处理是在doService()方法中完成的。

       在初始化完成时,在上下文中配置的所有HandlerMapping都已经被加载了,(HandlerMap初始化) 并被排序后放在一个List中。HandlerMapping存储着Http请求和对应的处理器的映射数据。

   

/**
 *实现Http请求和handler对象映射关系的接口 *这个接口可以被应用开发者实现,虽然这不是必须的,因为在框架中包含了BeanNameUrlHanlderMapping和SimpleUrlHandlerMapping。同*时如果没有注册任何HandlerMapping上述连个HandlerMapping是默认的HandlerMapping
 * *HandlerMapping实现类支持拦截器的映射,但不是必要的。一个Handler始终包含在HandlerExutionChain实例中,也可以选择伴随一些拦*截器。DispatcherServlet首先按照顺序调用每个拦截器的preHandler方法,如果所有拦截器的的preHandler方法都返回true,最后将调**用handler自身。
 **/
 public interface HandlerMapping {

	
	String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

	
	String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

	
	String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

	
	String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

	
	String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

	/**
	 返回一个请求的处理器和所有的拦截器。该选择可以基于请求的URL,会话状态或实现类的任何因素。
	 返回的HandlerExecutionChain包含一个处理器对象,而不是一个标签接口,处理器没有任何形式的限制
	   如果没有匹配的处理器则返回null,这不是一个错误。
	   DispatcherServlet将会查询所有注册的HanlderMapping去查找匹配的Handler,如果没有找到任何处理器只能判定有误
	 */
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}

 

      对请求的实际处理是在doDispatche()方法中完成的,其中主要步骤有:

 

  1. 准备ModelAndView, 
  2. 调用getHandler来获取处理该请求的Handler, 
  3. 然后通过handler响应请求返回一个ModelAndView 对象,
  4. 最后将这个ModelAndView交给视图对象去呈现。

 

 

 doService 接收到HttpServletRequest请求,在进行请求参数初始化后就直接将请求委派给doDispatch(),线面是doService源码:

 

/**
	 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
	 * for the actual dispatching.
	 */
	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isDebugEnabled()) {
			String requestUri = urlPathHelper.getRequestUri(request);
			logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
					" request for [" + requestUri + "]");
		}

		// 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)) {
			logger.debug("Taking snapshot of request attributes before include");
			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));
				}
			}
		}

		// 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 {
			// Restore the original attribute snapshot, in case of an include.
			if (attributesSnapshot != null) {
				restoreAttributesAfterInclude(request, attributesSnapshot);
			}
		}
	}

 

doDispatch()是HttpServletRequest请求真正被处理的类,

在该类中首先是从HandlerMappings中按照顺序检查是否有匹配的处理方法。如果在HandlerMappings中所有的handlerMap都没有匹配的处理方法则返回一个404.下面是doDispatch源码的分析:

 

/**
	 * Process the actual dispatching to the handler.
	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 * to find the first that supports the handler class.
	 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
	 * themselves to decide which methods are acceptable.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @throws Exception in case of any kind of processing failure
	 */
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		int interceptorIndex = -1;

		try {
			ModelAndView mv;
			boolean errorView = false;

			try {
				// 判断请求是否是多媒体请求
				processedRequest = checkMultipart(request);

				// 获取当前请求的处理器HandlerExecutionChain
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
				//如果没有处理器,则返回一个404
					noHandlerFound(processedRequest, response);
					return;
				}

				// 获取当前请求的Handler适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
				//获取当前请求的请求方法
				String method = request.getMethod();
				// 判断当前请求方法是否是GET请求
				boolean isGet = "GET".equals(method);
				// 如果是GET请求或者是HEAD
				if (isGet || "HEAD".equals(method)) {
					//获取最后修改时间
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				// 获取拦截器
				HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
				//如果拦截器不为空
				if (interceptors != null) {
					for (int i = 0; i < interceptors.length; i++) {
						HandlerInterceptor interceptor = interceptors[i];
						//如果处理请求被拦截,则结束请求,否则继续
						if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
							triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
							return;
						}
						interceptorIndex = i;
					}
				}

				// 调用处理器获取一个视图
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				//如果视图不为空,且有view,则设置默认视图名称
				if (mv != null && !mv.hasView()) {
					mv.setViewName(getDefaultViewName(request));
				}

				// Apply postHandle methods of registered interceptors.
				if (interceptors != null) {
					for (int i = interceptors.length - 1; i >= 0; i--) {
						HandlerInterceptor interceptor = interceptors[i];
						interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
					}
				}
			}
			catch (ModelAndViewDefiningException ex) {
				logger.debug("ModelAndViewDefiningException encountered", ex);
				mv = ex.getModelAndView();
			}
			catch (Exception ex) {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(processedRequest, response, handler, ex);
				errorView = (mv != null);
			}

			// 渲染视图
			if (mv != null && !mv.wasCleared()) {
				render(mv, processedRequest, 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");
				}
			}

			// Trigger after-completion for successful outcome.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
		}

		catch (Exception ex) {
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}
		catch (Error err) {
			ServletException ex = new NestedServletException("Handler processing failed", err);
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}

		finally {
			// Clean up any resources used by a multipart request.
			if (processedRequest != request) {
				cleanupMultipart(processedRequest);
			}
		}
	}

 getHandler 就是遍历handlerMappings的过程,如果其中有一个handlerMappings 中有匹配的处理方法则返回该HandlerExecutionChain.

	/**
	 * Return the HandlerExecutionChain for this request.
	 * <p>Tries all handler mappings in order.
	 * @param request current HTTP request
	 * @return the HandlerExecutionChain, or <code>null</code> if no handler could be found
	 */
	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;
	}

 

	/**
	 * 查找一个给定请求的处理器,如果没有找到特定的处理器则返回一个默认处理器
	 * @param request current HTTP request
	 * @return the corresponding handler instance, or the default handler
	 * @see #getHandlerInternal
	 */
	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);
		// 如果没有找到处理器则使用默认值
		if (handler == null) {
			handler = getDefaultHandler();
		}
		// 如果也没有默认处理器则返回null
		if (handler == null) {
			return null;
		}
		// 找到处理器Bean的名称
		if (handler instanceof String) {
			String handlerName = (String) handler;
			// 从上下文中获取处理器
			handler = getApplicationContext().getBean(handlerName);
		}
		return getHandlerExecutionChain(handler, request);
	}

 

 HandlerExeutionChain 包含了Hnadler对象和一些列的拦截器

/**
 * Handler execution chain, consisting of handler object and any handler interceptors.
 * Returned by HandlerMapping's {@link HandlerMapping#getHandler} method.
 *
 * @author Juergen Hoeller
 * @since 20.06.2003
 * @see HandlerInterceptor
 */
public class HandlerExecutionChain {

	private final Object handler;

	private HandlerInterceptor[] interceptors;

	private List<HandlerInterceptor> interceptorList;

 

  在HandlerMapping中找到了当前请求的处理Handle以后,HandlerAdapter将会调用这个处理器处理请求

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		//获取处理器类
		Class<?> clazz = ClassUtils.getUserClass(handler);
		//从缓存中获取这个处理器的值,
		Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
		//如果缓存中没有值,则判断这个处理器即controller上是否有@SessionAttribute注解,并将其放入到缓存中
		if (annotatedWithSessionAttributes == null) {
			annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
			this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
		}
		
		if (annotatedWithSessionAttributes) {
			
			checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
			
		}
		else {
			
			checkAndPrepare(request, response, true);
		}

		
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return invokeHandlerMethod(request, response, handler);
				}
			}
		}

		return invokeHandlerMethod(request, response, handler);
	}

	//处理器调用处
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
		//获取处理方法
		Method handlerMethod = methodResolver.resolveHandlerMethod(request);
		ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		ExtendedModelMap implicitModel = new BindingAwareModelMap();
		//反射调用处理方法
		Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
		ModelAndView mav =
				methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
		methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
		return mav;
	}

 

0
0
分享到:
评论

相关推荐

    Spring MVC学习之DispatcherServlet请求处理详析

    主要给大家介绍了关于Spring MVC学习教程之DispatcherServlet请求处理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    Spring MVC之DispatcherServlet详解_动力节点Java学院整理

    DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。 具体请参考第二章的图2-1。  ...

    Spring MVC之DispatcherServlet_动力节点Java学院整理

    Spring MVC之DispatcherServlet 使用Spring MVC,配置DispatcherServlet是第一步。 DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。 DispatcherServlet是前置控制器,配置在web.xml文件中的...

    Spring MVC入门教程

    十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 &lt;mvc:annotation-driven /&gt; 到底做了什么工作 二十、...

    Spring MVC 教程 快速入门 深入分析

    十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 &lt;mvc:annotation-driven /&gt; 到底做了什么工作

    SpringMVC框架架构介绍

    十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 &lt;mvc:annotation-driven /&gt; 到底做了什么工作 二十...

    Spring MVC 入门实例

    然后我们再配置 Servlet 映射(servlet-mapping 标签), 也就是你希望哪些请求被DispatcherServlet处理. 这里, 我们设置后缀名为 do(*.do) 的所有URL请求都被名为 ideawu 的 DispatcherServlet 的程序处理. 选择 .do ...

    全面掌握Spring MVC:从基础到高级的实践指南

    在Spring MVC中,DispatcherServlet作为前端控制器,负责请求的接收和响应结果的处理。处理器映射器(HandlerMapping)和处理器适配器(HandlerAdapter)是核心组件,负责找到和调用适当的处理器(Controller)。 ...

    java spring mvc

    首先客户端发出spring mvc请求,请求到达DispatcherServlet主控制器处理(前端控制器) b.主控制器调用HandlerMapping组件,根据请求不同调用Controller处理器 c.主控制器调用Controller方法处理请求,(对DB操作可以...

    入门案例-SpringMVC技术架构图

    Spring MVC以DispatcherServlet为核心,众多组件如HandlerMapping为辅助,为用户封装了请求映射等底层逻辑,让用户可以更专注与业务逻辑的处理。本文会对Spring MVC整体结构做简单介绍。 Spring MVC结构图 Spring ...

    spring MVC架构

    Spring MVC 是一个模型 - 视图 - 控制器(MVC)的Web框架建立在中央前端控制器servlet(DispatcherServlet),它负责发送每个请求到合适的处理程序,使用视图来最终返回响应结果的概念。Spring MVC 是 Spring 产品...

    SpringMVC入门教程

    十五、 spring mvc 处理ajax请求 十六、 spring mvc 关于写几个配置文件的说明 十七、 spring mvc 如何取得Spring管理的bean 十八、 spring mvc 多视图控制器 十九、 &lt;mvc:annotation-driven /&gt; 到底做了什么工作 ...

    Spring MVC 员工管理系统

    Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet的作用是截获请求并组织一系列组件共同完成请求的处理工作。 JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它...

    spring mvc 3.2 参考文档

    Spring Web model-view-controller (MVC)框架是围绕 DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置...

    Spring_MVC_教程_快速入门_深入分析

    spring mvc 核心类与接口 spring mvc 核心流程图 spring mvc DispatcherServlet说明 spring mvc 双亲上下文的说明 ...spring mvc 处理ajax请求 spring mvc 转发与重定向 如何给spring3 MVC中的Action做JUnit单元测试?

    spring mvc 思维导图

    Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。...

    Spring MVC简介.docx

    Spring MVC的设计是围绕DispatcherServlet展开的,DispatcherServlet负责将请求派发到特定的handler。通过可配置的handler mappings、view resolution、locale以及theme resolution来处理请求并且转到对应的视图。

    test-mvc:使用 Spring MVC 测试框架进行测试

    该项目的目标是证明: 如何使用 DispatcherServlet 为控制器编写单元测试来处理请求,从而在不需要运行 Servlet 容器的情况下近似完整的集成测试; 如何编写集成测试来测试所有应用程序层的集成,而无需运行 ...

    springmvc demo

    Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发...

    Spring Web MVC入门教程

    第一章:Spring Web MVC入门 包括:是什么、能干什么、有什么、各个组成部分的功能、HelloWorld等 第二章:理解DispatcherServlet 包括:功能、配置、上下文关系、初始化顺序等 第三章:注解式控制器开发详解 ...

Global site tag (gtag.js) - Google Analytics