一、组件说明
- DispatcherServlet:前端控制器,用于请求到达前端控制器,由它调用其他组件处理用户的请求。
- HandlerMapping:处理器映射器,负责根据用户请求找到Handler(处理器),springmvc提供了不同的映射器实现方式。
- Handler:处理器,对具体的用户请求进行处理。
- HandlerAdapter:处理器适配器,通过HandlerAdapter对处理器进行执行。
- View Resolver:视图解析器,负责将处理结果生成view视图。View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
二、前端控制器
DispatcherServlet是springmvc的中央调度器,DispatcherServlet创建时会默认从DispatcherServlet.properties文件加载springmvc所用的各种组件。
二、处理器映射器
处理器映射器负责根据request请求找到对应的Handler处理器以及Interceptor拦截器,将它们封装在HandlerExecutionChain对象中返回给前端控制器。
下面是两种常用的处理器映射器:
1、BeanNameURLHandlerMapping:根据请求的url与spring容器中定义的bean的name进行匹配,从而从spring容器中找到bean实例。
2、simpleURLHandlerMapping:它可以将url和处理器bean的id进行统一映射配置。
三、处理器适配器
HandlerAdapter会根据适配器接口对Handler进行包装适配,包装后即可对处理器进行执行(使用了适配器模式)。
下面是两种常用的处理器适配器:
1、SimpleControllerHandlerAdapter:简单控制器处理器适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的bean通过此适配器进行适配执行。
2、HttpRequestHandlerAdapter:http请求处理器适配器,所有实现了org.springframework.web.HttpRequestHandler接口的bean通过此适配器进行适配执行。
注:处理器实现HttpRequestHandler接口,实现handleRequest方法,该方法没有返回、ModelAndView,可以通过response修改定义响应内容,比如返回json数据。
四、注解处理器映射器和适配器
可以使用组件扫描,而省去在spring容器中配置每个controller类。配置如下:
<context:component-scan base-package="com.demo.ssm.controller"></context:component-scan>
1、注解处理器映射器,对类中标记的@RequestMapping的方法进行映射,根据RequestMapping定义的url匹配RequestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
<!-- 注解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
2、注解处理器适配器,对标记的@RequestMapping的方法进行适配。
<!-- 注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
注:还可以使用下面的配置代替上面处理器映射器和适配器的配置:
<mvc:annotation-driven></mvc:annotation-driven>
五、总结
springmvc处理流程:
1、用户发送请求到DispatchServlet前端控制器。
/** * 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; 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(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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); } } } }