处理请求是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()方法中完成的,其中主要步骤有:
- 准备ModelAndView,
- 调用getHandler来获取处理该请求的Handler,
- 然后通过handler响应请求返回一个ModelAndView 对象,
- 最后将这个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; }
相关推荐
在Spring MVC框架中,DispatcherServlet扮演着至关重要的角色,它是整个Spring MVC的前端控制器,负责接收客户端发送的HTTP请求,并将其转发给适当的处理器进行处理。接下来我们将深入探讨DispatcherServlet的请求...
Spring MVC之DispatcherServlet 使用Spring MVC,配置DispatcherServlet是第一步。 DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。 DispatcherServlet是前置控制器,配置在web.xml文件中的...
Spring MVC通过DispatcherServlet作为入口点,接收HTTP请求,然后根据请求映射信息分发到相应的处理器。 在Spring MVC 4.2.3中,主要包含了以下关键特性: 1. **类型安全的路径变量**:这个版本引入了类型安全的...
Spring MVC 是一个基于Java的轻量级Web应用框架,它为开发者提供了模型-视图-控制器(MVC)架构,使开发人员能够更好地组织和分离应用程序的业务逻辑、数据处理和用户界面。Spring MVC是Spring框架的一个核心组件,...
三、Spring MVC核心流程图:描述了Spring MVC处理请求的流程,包括前端控制器接收请求,经过分发器分发给具体的控制器,然后由控制器处理业务逻辑,最后将结果返回给用户。 四、Spring MVC DispatcherServlet说明:...
1. Spring MVC通过DispatcherServlet接收HTTP请求,然后根据映射规则将请求分发给相应的Controller进行处理。默认情况下,每个请求都在单独的线程中执行,这意味着可以并行处理多个请求,提高系统响应速度。 2. 然而...
综上所述,DispatcherServlet在Spring MVC中起着至关重要的作用,它是整个请求处理流程的入口点,负责调度和协调各个组件,使得整个框架能灵活且高效地处理HTTP请求。通过合理的配置,我们可以定制其行为以适应各种...
Spring MVC还支持数据绑定,自动将请求参数绑定到Java对象,这极大地简化了表单提交的处理。对于验证,Spring MVC提供了BindingResult和Validator接口,用于校验模型数据的正确性。 另外,Spring MVC与Spring框架的...
十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 <mvc:annotation-driven /> 到底做了什么工作 二十、...
十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 <mvc:annotation-driven /> 到底做了什么工作
Spring MVC通过DispatcherServlet作为前端控制器,接收请求并分发给相应的处理器(Controller)。处理器执行业务逻辑后,将结果返回给ModelAndView对象,再由视图解析器渲染视图。此外,Spring MVC还支持注解驱动,...
在Spring MVC中,每个请求都会经过DispatcherServlet,这是一个前端控制器,它会根据请求的URL和配置的映射规则将请求分发到合适的处理器。处理器可以是自定义的Controller类,Controller通过方法注解(如@...
8. **异步处理**:Spring MVC 4.0引入了异步请求处理,通过@ControllerAdvice和@Async注解,可以实现后台任务的异步执行,提高响应速度。 9. **多Part文件上传**:支持多文件上传,利用MultipartFile接口处理上传...
总的来说,Spring MVC的DispatcherServlet通过一系列步骤,从初始化时的bean扫描到请求到达时的分发处理,确保了请求能够准确地传递到正确的Controller方法。这一过程涉及到bean的扫描、请求映射的建立、拦截器的...
拦截器(Interceptor)是Spring MVC中的一种机制,可以在请求处理前、后执行自定义逻辑。通过实现HandlerInterceptor接口或使用@Interceptor注解,开发者可以添加全局的行为,如日志记录、权限检查等。 此外,...
1. **DispatcherServlet**: 它是Spring MVC的入口点,负责接收HTTP请求,并根据请求信息找到合适的处理器(Handler)进行处理。DispatcherServlet通过`web.xml`配置文件或Java配置类进行初始化配置。 2. **...
Spring MVC通过DispatcherServlet作为入口点,统一处理所有HTTP请求,它将请求分发给相应的处理器,并管理视图的渲染。 在实际项目中,Spring MVC提供了许多高级特性,例如: 1. **配置灵活性**:可以通过XML、Java...