在javax.servlet.http.HttpServlet的基础上添加额外功能,包括参数解析、请求拦截器、异常处理、视图渲染等。
Handler
springframework中对http request的最细粒度的处理者,类似于javax中的Servlet。类型有:
org.springframework.web.HttpRequestHandler:接口,有很多实现类,如ResourceHttpRequestHandler专门用于处理静态资源请求。
org.springframework.web.servlet.mvc.Controller:接口,有很多实现类,如ServletWrappingController。
org.springframework.web.method.HandlerMethod:类,springframework的@Controller中带有@RequestMapping的方法默认为此类的handler。
HandlerExecutionChain
对Handler的进一步封装,将一个handler及与该handler相关的各interceptor封装在一起。
HandlerAdapter
具体执行handler方法者,DispatcherServlet会根据handler的类型交由相应的handler adapter执行。
默认的HandlerAdapter类型
默认会添加三个HandlerAdapter到application context:
class org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,处理interface org.springframework.web.HttpRequestHandler类型的handler
class org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,处理interface org.springframework.web.servlet.mvc.Controller类型的handler
class org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,处理class org.springframework.web.method.HandlerMethod类型的handler,@Controller中的handler通过此adapter处理。
@ControllerAdvice + RequestBodyAdvice/ResponseBodyAdvice/@ModelAttribute/@InitBinder 的全局处理功能也是由RequestMappingHandlerAdapter来实现的。详情可参阅:https://blog.csdn.net/andy_zhang2007/article/details/100041219
handler方法的执行过程
(参阅:https://blog.csdn.net/andy_zhang2007/article/details/99689573)
Spring MVC中,一般来讲,控制器指的是开发人员使用了注解@Controller这样的类,而控制器方法,是控制器类中使用了注解@RequestMapping的那些方法。控制器方法能处理哪些请求,就是通过这些@RequestMapping注解信息来定义的,DispatcherServlet会把这些信息加载保存到一个RequestMappingHandlerMapping对象中,当相应的请求到达时,DispatcherServlet会通过该信息找到相应的控制器方法,然后通过调用RequestMappingHandlerAdapter执行控制器方法,完成对请求的处理。
handler方法的执行逻辑主要在RequestMappingHandlerAdapter中。
1 RequestMappingHandlerAdapter整体处理流程的相关源码:
1 // RequestMappingHandlerAdapter 代码片段 2 // 返回值是一个 ModelAndView 3 // 如果需要调用者后续解析和渲染视图,则该返回值 ModelAndView 不会为 null 4 // 如果请求已经被该方法完全处理,不需要调用者后续解析和渲染视图,则返回值 ModelAndView 会是 null 5 @Nullable 6 protected ModelAndView invokeHandlerMethod(HttpServletRequest request, 7 HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { 8 9 // 将 HttpServletRequest/HttpServletResponse 对象包装成一个 ServletWebRequest 对象 10 ServletWebRequest webRequest = new ServletWebRequest(request, response); 11 try { 12 // 准备工作,设置调用控制器方法所需要的各种数据,或者工具组件 13 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); 14 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); 15 16 // 将目标控制器方法 handlerMethod 包装成一个 ServletInvocableHandlerMethod, 17 // 这里主要是针对 Servlet 环境的一些特殊处理和包装,参数传递 18 ServletInvocableHandlerMethod invocableMethod = 19 createInvocableHandlerMethod(handlerMethod); 20 if (this.argumentResolvers != null) { 21 invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); 22 } 23 if (this.returnValueHandlers != null) { 24 invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); 25 } 26 invocableMethod.setDataBinderFactory(binderFactory); 27 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); 28 29 // ModelAndViewContainer 是一个调用目标控制器方法过程中,记录参数解析,返回值处理的一些 30 // 决策信息的一个容器类型/持有器类型,这里准备出这样一个对象,供控制器方法调用过程中使用 31 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); 32 // 将请求中可能存在的 FlashMap 属性添加到 mavContainer 33 mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); 34 // 1. 获取所有 @SessionAttributes 属性到 mavContainer 35 // 2. 执行所有 @ModelAttribute 方法 36 // 3. 找到所有使用了注解 @ModelAttribute 并且也属于 @SessionAttributes 列表的 37 // 参数将其添加到 mavContainer 38 modelFactory.initModel(webRequest, mavContainer, invocableMethod); 39 // 设置重定向时如果 RedirectAttributes 属性未设置,是否要使用缺省 Model, 40 // 缺省值为 false, 表示即使重定向时 RedirectAttributes 属性未设置,也不要使用缺省 Model 41 mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); 42 43 // 对异步Web请求的处理的准备工作,本系列文章中只介绍同步请求处理,所以这里忽略对这一部分的介绍 44 AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); 45 asyncWebRequest.setTimeout(this.asyncRequestTimeout); 46 47 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 48 asyncManager.setTaskExecutor(this.taskExecutor); 49 asyncManager.setAsyncWebRequest(asyncWebRequest); 50 asyncManager.registerCallableInterceptors(this.callableInterceptors); 51 asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); 52 53 if (asyncManager.hasConcurrentResult()) { 54 Object result = asyncManager.getConcurrentResult(); 55 mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0]; 56 asyncManager.clearConcurrentResult(); 57 LogFormatUtils.traceDebug(logger, traceOn -> { 58 String formatted = LogFormatUtils.formatValue(result, !traceOn); 59 return "Resume with async result [" + formatted + "]"; 60 }); 61 invocableMethod = invocableMethod.wrapConcurrentResult(result); 62 } 63 64 65 // 万事俱备,现在执行目标控制器方法,从此入口进去,会看到具体执行过程的更多步骤逻辑, 66 // 这里也是我们将要展开介绍的地方 67 invocableMethod.invokeAndHandle(webRequest, mavContainer); 68 if (asyncManager.isConcurrentHandlingStarted()) { 69 return null; 70 } 71 72 // 目标控制器方法执行完结,请求处理已经完成,执行过程中的各种决定信息都记录在了 73 // mavContainer 中,现在结合相关组件构造一个 ModelAndView 对象,后续调用者 74 // 有可能还有基于这些信息解析和渲染视图 75 // 如果控制器方法已经完全处理了该请求,无需后续处理,则 mavContainer 会包含 76 // 这样的信息 : #isRequestHandled == true, 从而这里的 ModelAndView 返回值 77 // 会是 null 78 return getModelAndView(mavContainer, modelFactory, webRequest); 79 } 80 finally { 81 webRequest.requestCompleted(); 82 } 83 }