在javax.servlet.http.HttpServlet的基础上添加额外功能,包括参数解析、请求拦截器、异常处理、视图渲染等。

 Spring Web MVC工作原理

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     }
RequestMappingHandlerAdapter#invodeHandlerMethod

相关文章:

  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2018-05-31
  • 2021-11-08
  • 2021-12-22
相关资源
相似解决方案