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

Spring MVC之DispatcherServlet请求处理(二)

 
阅读更多

     回顾一下DispatcherServlet中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);
			}
		}
	}

        可以发现对请求数据的处理是通过HandlerAdapter的handle()方法进行处理。下面将通过AnnotationMethodHandlerAdapter类来说明HandlerAdapter

 

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 获取处理器的Class对象
		Class<?> clazz = ClassUtils.getUserClass(handler);
		Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
		if (annotatedWithSessionAttributes == null) {
			// 如果有会话域的参数
			annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
			//将会话域的参数放入到缓存中
			this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
		}
		
		if (annotatedWithSessionAttributes) {
			// 总是防止缓存的情况下会话属性管理。
			checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
			//  准备缓存防止会话域参数名称
		}
		else {
			// Uses configured default cacheSeconds setting.
			checkAndPrepare(request, response, true);
		}

		// 如果有必要可以在synchronized同步代码块中执行ivokeHandlerMethod方法,默认是false
		if (this.synchronizeOnSession) {
		    // 获取当前请求的session
			HttpSession session = request.getSession(false);
			if (session != null) {
				//获取当前session的互斥锁对象
				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 {
		// 获取指定处理器的ServeltHandlerMethodResovler对象
		ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
		// 获取请求的处理方法
		Method handlerMethod = methodResolver.resolveHandlerMethod(request);
		//
		ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
		//构建一个ServletWebReqeust
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		ExtendedModelMap implicitModel = new BindingAwareModelMap();
		//指定处理
		Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
		// 获取处理后的ModleAndView
		ModelAndView mav =
				methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
		methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
		// 返回ModelAndView对象
		return mav;
	}

 

	/**
	 * 对给定的处理器类型创建一个ServeltHandlerMethodResolver
	 */
	private ServletHandlerMethodResolver getMethodResolver(Object handler) {
		// 获取用户定义的类
		Class handlerClass = ClassUtils.getUserClass(handler);
		// 从缓存中获取ServletHandlerMethodResolver
		ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);
		//如果缓存中不存在
		if (resolver == null) {
			synchronized (this.methodResolverCache) {
				resolver = this.methodResolverCache.get(handlerClass);
				if (resolver == null) {
				   // 创建一个ServletHandlerMethodResolver对象并存入缓存
					resolver = new ServletHandlerMethodResolver(handlerClass);
					this.methodResolverCache.put(handlerClass, resolver);
				}
			}
		}
		return resolver;
	}

 

 

    

 

2
0
分享到:
评论

相关推荐

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

    在Spring MVC框架中,DispatcherServlet扮演着至关重要的角色,它是整个Spring MVC的前端控制器,负责接收客户端发送的HTTP请求,并将其转发给适当的处理器进行处理。接下来我们将深入探讨DispatcherServlet的请求...

    Spring MVC 4.2.3

    9. **异步处理支持**:Spring MVC支持异步处理请求,允许在不阻塞线程的情况下执行耗时的操作,从而提高系统性能。 10. **国际化和本地化**:通过消息源和LocaleResolver,Spring MVC可以轻松实现应用的多语言支持...

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

    三、Spring MVC核心流程图:描述了Spring MVC处理请求的流程,包括前端控制器接收请求,经过分发器分发给具体的控制器,然后由控制器处理业务逻辑,最后将结果返回给用户。 四、Spring MVC DispatcherServlet说明:...

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

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

    springmvc+spring线程池处理http并发请求数据同步控制问题

    1. Spring MVC通过DispatcherServlet接收HTTP请求,然后根据映射规则将请求分发给相应的Controller进行处理。默认情况下,每个请求都在单独的线程中执行,这意味着可以并行处理多个请求,提高系统响应速度。 2. 然而...

    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; 到底做了什么工作

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

    综上所述,DispatcherServlet在Spring MVC中起着至关重要的作用,它是整个请求处理流程的入口点,负责调度和协调各个组件,使得整个框架能灵活且高效地处理HTTP请求。通过合理的配置,我们可以定制其行为以适应各种...

    最全最经典spring-mvc教程

    Spring MVC还支持数据绑定,自动将请求参数绑定到Java对象,这极大地简化了表单提交的处理。对于验证,Spring MVC提供了BindingResult和Validator接口,用于校验模型数据的正确性。 另外,Spring MVC与Spring框架的...

    Spring MVC+ Spring+ Mybatis 框架搭建

    Spring MVC通过DispatcherServlet作为前端控制器,接收请求并分发给相应的处理器(Controller)。处理器执行业务逻辑后,将结果返回给ModelAndView对象,再由视图解析器渲染视图。此外,Spring MVC还支持注解驱动,...

    Spring.MVC-A.Tutorial-Spring.MVC学习指南 高清可复制版PDF

    在Spring MVC中,每个请求都会经过DispatcherServlet,这是一个前端控制器,它会根据请求的URL和配置的映射规则将请求分发到合适的处理器。处理器可以是自定义的Controller类,Controller通过方法注解(如@...

    Spring源码学习十:DispatcherServlet请求分发源码分析1

    总的来说,Spring MVC的DispatcherServlet通过一系列步骤,从初始化时的bean扫描到请求到达时的分发处理,确保了请求能够准确地传递到正确的Controller方法。这一过程涉及到bean的扫描、请求映射的建立、拦截器的...

    spring MVC .docx

    1. **DispatcherServlet**: 它是Spring MVC的入口点,负责接收HTTP请求,并根据请求信息找到合适的处理器(Handler)进行处理。DispatcherServlet通过`web.xml`配置文件或Java配置类进行初始化配置。 2. **...

    spring mvc 4.0

    8. **异步处理**:Spring MVC 4.0引入了异步请求处理,通过@ControllerAdvice和@Async注解,可以实现后台任务的异步执行,提高响应速度。 9. **多Part文件上传**:支持多文件上传,利用MultipartFile接口处理上传...

    Mastering Spring MVC 4(2015.09)源码

    拦截器(Interceptor)是Spring MVC中的一种机制,可以在请求处理前、后执行自定义逻辑。通过实现HandlerInterceptor接口或使用@Interceptor注解,开发者可以添加全局的行为,如日志记录、权限检查等。 此外,...

    Mastering Spring MVC 3中文版

    Spring MVC通过DispatcherServlet作为入口点,统一处理所有HTTP请求,它将请求分发给相应的处理器,并管理视图的渲染。 在实际项目中,Spring MVC提供了许多高级特性,例如: 1. **配置灵活性**:可以通过XML、Java...

    两个小时学会了Spring MVC

    Spring MVC通过DispatcherServlet来担当这个角色,它负责调度请求到对应的处理器(Controller)。 Spring MVC的工作流程如下: - 用户发起HTTP请求到达DispatcherServlet。 - DispatcherServlet根据请求信息(URL、...

Global site tag (gtag.js) - Google Analytics