抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文分析了Spring MVC的工作流程,包括请求处理的各个阶段和核心对象的协作机制。

环境

Windows 10 企业版 LTSC 21H2
Java 1.8
Tomcat 8.5.50
Maven 3.6.3
Spring 5.3.31

1 基本流程

Spring MVC的工作流程是围绕DispatcherServlet前端控制器展开的,由它统一处理所有请求。

核心流程:
20260112103332-核心流程

说明:

  1. 发送请求。服务器接受用户请求,DispatcherServlet捕获请求。
  2. 获取处理器执行链。根据配置匹配路径,通过HandlerMapping处理器映射器获取Handler处理器和InterceptorList拦截器列表,封装为HandlerExecutionChain处理器执行链。
  3. 返回处理器执行链。返回HandlerExecutionChain处理器执行链。
  4. 获取处理器适配器。根据HandlerExecutionChain处理器执行链中的Handler处理器,匹配HandlerAdapter处理器适配器。
  5. 返回处理器适配器。返回HandlerAdapter处理器适配器。
  6. 执行业务方法。使用HandlerAdapter处理器适配器执行Handler处理器对应的业务方法,根据配置将结果封装为ModelAndView模型视图。
  7. 返回业务结果。返回ModelAndView模型视图。
  8. 处理视图。判断是否需要解析视图:如果不用解析视图,则直接返回视图;如果需要解析视图,则匹配ViewResolver视图解析器解析视图。
  9. 返回视图。使用View视图填充Model模型数据,处理响应。
  10. 响应请求。将响应返回给用户。

详细流程:
20260112103517-详细流程

2 源码分析

2.1 请求接收

根据web.xml配置文件中的配置,使用DispatcherServlet匹配/请求,所有请求都会经过DispatcherServlet处理。

2.2 准备处理请求

DispatcherServlet继承自FrameworkServlet,FrameworkServlet间接继承自HttpServlet,请求会调用service()方法。

DispatcherServlet没有实现service()方法,所以调用FrameworkServlet的service()方法:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取请求类型
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
// 根据请求类型判断是否为PATCH请求或未知请求
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
// 准备处理请求
processRequest(request, response);
} else {
// 调用相关方法处理请求
super.service(request, response);
}
}

调用HttpServlet的service()方法,根据请求类型调用方法:

java
1
2
3
4
5
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 根据请求类型调用方法
doXxx(req, resp);
}

调用FrameworkServlet的doXxx()方法,准备处理请求:

java
1
2
3
4
5
protected final void doXxx(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 准备处理请求
processRequest(request, response);
}

2.3 开始处理请求

调用FrameworkServlet的processRequest()方法,开始处理请求:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 保存当前线程原有的本地上下文
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 创建新的本地上下文
LocaleContext localeContext = buildLocaleContext(request);
// 保存当前线程原有的请求属性
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 创建新的请求属性
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
// 注册异步回调拦截器
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 绑定本地上下文和请求属性
initContextHolders(request, localeContext, requestAttributes);
// 开始处理请求
doService(request, response);
}

调用DispatcherServlet的doService()方法,执行处理请求前的设置:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
protected void doService(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 设置请求属性
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());
// 处理闪存属性
if (this.flashMapManager != null) {
// 检索并更新输入的闪存
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);
}
// 处理请求路径解析
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
// 保存原有的请求路径
previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
// 解析当前请求的路径并缓存到请求属性中
ServletRequestPathUtils.parseAndCache(request);
}
// 继续处理请求
doDispatch(request, response);
}

调用DispatcherServlet的doDispatch()方法,继续处理请求:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 处理上传请求
HttpServletRequest processedRequest = checkMultipart(request);
// 获取处理器执行链
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
// 判断是否为上传请求
boolean multipartRequestParsed = (processedRequest != request);
// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
// 获取处理器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 仅对GET和HEAD请求进行最后修改时间检查
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 使用处理器执行链中的拦截器链进行前置检查
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 处理请求业务逻辑
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 判断是否异步处理线程,如果是则立即返回,模型视图由其他线程处理
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 处理视图名称,拼接前缀后缀
applyDefaultViewName(processedRequest, mv);
// 使用处理器执行链中的拦截器链进行后置检查
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

2.4 获取处理器执行链

2.4.1 匹配处理器映射器

调用DispatcherServlet的getHandler()方法,获取处理器执行链:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
protected HandlerExecutionChain getHandler(HttpServletRequest request)
throws Exception {
// 遍历所有处理器映射器,返回处理器执行链
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}

调用AbstractHandlerMapping的getHandler()方法,获取处理器执行链:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public final HandlerExecutionChain getHandler(HttpServletRequest request)
throws Exception {
// 获取处理器
Object handler = getHandlerInternal(request);
// 如果没有找到处理器,则使用默认处理器
if (handler == null) {
handler = getDefaultHandler();
}
// 如果没有默认处理器,则返回null
if (handler == null) {
return null;
}
// 如果处理器是字符串,则获取对应的处理器对象
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 缓存请求路径
if (!ServletRequestPathUtils.hasCachedPath(request)) {
initLookupPath(request);
}
// 封装普通处理器执行链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
// 判断当前处理器是否支持跨域配置,或者当前请求是否为预检请求
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
// 获取处理器级别的跨域配置
CorsConfiguration config = getCorsConfiguration(handler, request);
// 如果存在全局跨域配置,则合并配置
if (getCorsConfigurationSource() != null) {
CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
config = (globalConfig != null ? globalConfig.combine(config) : config);
}
// 验证配置中是否允许携带凭证
if (config != null) {
config.validateAllowCredentials();
}
// 封装跨域处理器执行链,确保在请求处理前进行检查
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
// 返回处理器执行链
return executionChain;
}

HandlerMapping用于根据请求获取处理器,有多种实现类:

  • SimpleUrlHandlerMapping:基于URL配置映射,需要显示配置映射,支持集中配置URL映射,支持通配符,支持批量配置。
  • RequestMappingHandlerMapping:基于@RequestMapping注解配置映射,最常用的映射器。
  • RouterFunctionMapping:基于函数式编程配置映射,支持根据请求路径动态配置映射。
  • BeanNameUrlHandlerMapping:基于对象名称配置映射,默认自带映射。
  • 也支持通过实现HandlerMapping接口的方式自定义映射器。

2.4.2 获取处理器

调用AbstractHandlerMethodMapping的getHandlerInternal()方法,获取处理器:

java
1
2
3
4
5
6
7
8
9
protected HandlerMethod getHandlerInternal(HttpServletRequest request)
throws Exception {
// 获取请求路径
String lookupPath = initLookupPath(request);
// 根据请求路径获取处理器
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
// 返回处理器
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}

调用AbstractHandlerMethodMapping的lookupHandlerMethod()方法,根据请求路径获取处理器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request)
throws Exception {
// 准备匹配列表
List<Match> matches = new ArrayList<>();
// 根据请求路径直接匹配
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
// 如果可以直接匹配,检查直接匹配的映射,添加到匹配列表中
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
// 如果不能直接匹配,检查所有注册的映射,添加到匹配列表中
if (matches.isEmpty()) {
addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
}
// 判断匹配列表是否为空
if (!matches.isEmpty()) {
// 如果匹配列表不为空,选择最佳匹配,最佳匹配如果重复抛出异常
Match bestMatch = matches.get(0);
if (matches.size() > 1) { ... }
// 设置最佳匹配的处理器
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.getHandlerMethod();
} else {
// 如果匹配列表是空的,处理无匹配情况
return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
}
}

2.4.3 封装处理器执行链

2.4.3.1 封装普通处理器

调用AbstractHandlerMapping的getHandlerExecutionChain()方法,封装普通处理器执行链:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
// 封装处理器执行链
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// 遍历拦截器列表
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
// 判断拦截器是否存在映射
if (interceptor instanceof MappedInterceptor) {
// 如果存在映射,转为映射拦截器
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
// 只有映射匹配请求路径才能添加拦截器
if (mappedInterceptor.matches(request)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
// 如果不存在映射,直接添加拦截器
chain.addInterceptor(interceptor);
}
}
// 返回处理器执行链
return chain;
}
2.4.3.2 封装跨域处理器

调用AbstractHandlerMapping的getCorsHandlerExecutionChain()方法,封装跨域处理器执行链:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, @Nullable CorsConfiguration config) {
// 检查当前请求是否为预检请求
if (CorsUtils.isPreFlightRequest(request)) {
// 如果是预检请求,获取普通处理器的拦截器列表
HandlerInterceptor[] interceptors = chain.getInterceptors();
// 封装预检处理器和拦截器列表,返回处理器执行链
return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
} else {
// 如果是跨域请求,插入跨域拦截器
chain.addInterceptor(0, new CorsInterceptor(config));
// 返回处理器执行链
return chain;
}
}

2.5 获取处理器适配器

调用DispatcherServlet的getHandlerAdapter()方法,获取处理器适配器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
protected HandlerAdapter getHandlerAdapter(Object handler)
throws ServletException {
// 如果处理器适配器不为空,遍历所有处理器适配器,返回匹配的处理器适配器
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
// 如果处理器适配器不存在,则抛出异常
throw new ServletException( ... );
}

HandlerAdapter用于根据处理器执行业务逻辑,有多种实现类:

  • RequestMappingHandlerAdapter:支持基于@RequestMapping注解的使用方式。最常用的适配器。
  • HandlerFunctionAdapter:支持基于函数式编程的使用方式。
  • HttpRequestHandlerAdapter:支持实现HttpRequestHandler接口的使用方式。
  • SimpleControllerHandlerAdapter:支持实现Controller接口的使用方式,早期适配器。
  • SimpleServletHandlerAdapter:支持实现Servlet接口的使用方式,早期适配器。
  • 也支持通过实现HandlerAdapter接口的方式自定义处理。

2.6 处理业务逻辑

调用AbstractHandlerMethodAdapter的handle()方法,处理业务逻辑:

java
1
2
3
4
5
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 处理业务逻辑
return handleInternal(request, response, (HandlerMethod) handler);
}

调用RequestMappingHandlerAdapter的handleInternal()方法,处理业务逻辑:

java
1
2
3
4
5
6
7
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
throws Exception {
// 检查请求是否符合要求
checkRequest(request);
// 调用实际处理方法
return invokeHandlerMethod(request, response, handlerMethod);
}

调用RequestMappingHandlerAdapter的invokeHandlerMethod()方法,调用实际处理方法:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
throws Exception {
// 封装请求和响应对象
ServletWebRequest webRequest = new ServletWebRequest(request, response);
// 创建数据绑定工厂,绑定请求参数
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 创建模型工厂,创建数据模型
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 封装处理器作为可执行的方法
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 设置请求参数解析器
if (this.argumentResolvers != null) {
// 解析请求参数,支持多种方式解析请求参数
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 设置返回值处理器
if (this.returnValueHandlers != null) {
// 处理方法返回值,支持多种方式处理返回值
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
// 设置数据绑定工厂
invocableMethod.setDataBinderFactory(binderFactory);
// 设置参数名称发现器
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// 创建模型视图容器
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 设置输入的闪存
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
// 初始化数据模型
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
// 设置重定向忽略默认模型
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 创建异步请求对象
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
// 设置异步请求的超时时间
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
// 获取异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
// 设置任务执行器
asyncManager.setTaskExecutor(this.taskExecutor);
// 设置异步请求对象
asyncManager.setAsyncWebRequest(asyncWebRequest);
// 注册异步回调拦截器
asyncManager.registerCallableInterceptors(this.callableInterceptors);
// 注册异步延迟拦截器
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
// 是否已经异步处理
if (asyncManager.hasConcurrentResult()) {
// 获取异步处理的结果
Object result = asyncManager.getConcurrentResult();
// 获取原始的模型视图容器
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
// 清除并发结果,避免重复处理
asyncManager.clearConcurrentResult();
// 将并发结果包装为可调用的处理方法
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 执行业务逻辑
invocableMethod.invokeAndHandle(webRequest, mavContainer);
// 判断是否异步处理线程,如果是则立即返回,模型视图由其他线程处理
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 处理模型视图
return getModelAndView(mavContainer, modelFactory, webRequest);
}

2.7 执行业务逻辑

调用ServletInvocableHandlerMethod的invokeAndHandle()方法,执行业务逻辑:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs)
throws Exception {
// 调用目标方法
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 设置响应状态码
setResponseStatus(webRequest);
// 判断返回值是否为空
if (returnValue == null) {
// 如果返回值为空,如果请求未修改,或者已通过@ResponseStatus注解设置状态,或者请求已被标记为已处理
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
// 禁用响应内容缓存
disableContentCachingIfNecessary(webRequest);
// 标记不用处理返回值,后续不再进行视图解析
mavContainer.setRequestHandled(true);
return;
}
} else if (StringUtils.hasText(getResponseStatusReason())) {
// 如果返回值非空,并且@ResponseStatus注解存在原因,则直接标记请求已处理并返回
mavContainer.setRequestHandled(true);
return;
}
// 标记需要处理返回值
mavContainer.setRequestHandled(false);
// 使用返回值处理器处理返回值
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}

2.7.1 调用目标方法

调用InvocableHandlerMethod的invokeForRequest()方法,调用目标方法:

java
1
2
3
4
5
6
7
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs)
throws Exception {
// 获取方法参数值
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
// 通过反射机制执行方法调用
return doInvoke(args);
}

调用InvocableHandlerMethod的getMethodArgumentValues()方法,获取方法参数值:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs)
throws Exception {
// 获取方法参数
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
// 初始化参数值数组
Object[] args = new Object[parameters.length];
// 遍历方法参数,添加参数值
for (int i = 0; i < parameters.length; i++) {
// 获取当前参数
MethodParameter parameter = parameters[i];
// 初始化参数名称发现器
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// 在预定义的参数值中查找匹配的参数值
args[i] = findProvidedArgument(parameter, providedArgs);
// 如果是预定义的参数值则直接使用,跳过后续处理
if (args[i] != null) {
continue;
}
// 判断是否存在支持当前参数的解析器,如果存在则放入缓存,如果没有则抛出异常
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
// 调用解析器解析参数值
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
// 返回参数值数组
return args;
}

调用HandlerMethodArgumentResolverComposite的resolveArgument()方法,解析参数值:

java
1
2
3
4
5
6
7
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)
throws Exception {
// 获取参数解析器
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
// 调用解析器解析参数值,使用消息转换器读取参数值
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
2.7.1.1 获取参数解析器

调用HandlerMethodArgumentResolverComposite的getArgumentResolver()方法,获取参数解析器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
// 从缓存中获取参数解析器
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
// 判断是否存在支持当前参数的解析器
if (result == null) {
// 遍历所有解析器,查找匹配的解析器,将解析器放入缓存中
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
// 返回参数解析器
return result;
}

HandlerMethodArgumentResolver用于将请求参数转换为方法参数值,有多种实现类:

  • RequestParamMethodArgumentResolver:支持处理使用@RequestParam注解的简单类型的参数。
  • RequestParamMapMethodArgumentResolver:支持处理使用@RequestParam注解的Map类型的参数。
  • PathVariableMethodArgumentResolver:支持处理使用@PathVariable注解的简单类型的参数。
  • PathVariableMapMethodArgumentResolver:支持处理使用@PathVariable注解的Map类型的参数。
  • RequestHeaderMethodArgumentResolver:支持处理使用@RequestHeader注解的简单类型的参数。
  • RequestHeaderMapMethodArgumentResolver:支持处理使用@RequestHeader注解的Map类型的参数。
  • ServletModelAttributeMethodProcessor:支持处理使用@ModelAttribute注解的参数。
  • ServletCookieValueMethodArgumentResolver:支持处理使用@CookieValue注解的参数。
  • RequestResponseBodyMethodProcessor:支持处理使用@RequestBody注解的参数。
  • HttpEntityMethodProcessor:支持处理使用RequestEntity类型的参数。
  • ModelMethodProcessor:支持处理使用Model类型的参数。
  • MapMethodProcessor:支持处理使用Map类型的参数。
2.7.1.2 解析参数值
2.7.1.2.1 解析请求体

如果是@RequestBody注解的参数,需要使用RequestResponseBodyMethodProcessor解析参数值。

调用RequestResponseBodyMethodProcessor的resolveArgument()方法,解析请求体:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory)
throws Exception {
// 如果是Optional类型的参数,需要获取实际参数类型
parameter = parameter.nestedIfOptional();
// 读取请求体参数值
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
// 获取参数名称
String name = Conventions.getVariableNameForParameter(parameter);
// 如果存在数据绑定器工厂,则进行数据绑定
if (binderFactory != null) {
// 创建数据绑定器
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
// 如果参数值不为空,则校验数据绑定
if (arg != null) {
// 校验数据绑定
validateIfApplicable(binder, parameter);
// 如果校验失败,且需要抛出异常,则抛出异常
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
// 如果存在模型视图容器,则将绑定结果添加到模型中,供视图使用
if (mavContainer != null) {
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
}
// 如果是Optional类型的参数,需要转换参数值
return adaptArgumentIfNecessary(arg, parameter);
}

调用RequestResponseBodyMethodProcessor的readWithMessageConverters()方法,读取请求体参数值:

java
1
2
3
4
5
6
7
8
9
10
11
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter, Type paramType)
throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
// 获取原生HttpServletRequest对象
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
// 创建ServletServerHttpRequest对象
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
// 读取请求体参数值
Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
// 返回参数值
return arg;
}

调用AbstractMessageConverterMethodArgumentResolver的readWithMessageConverters()方法,读取请求体参数值:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType)
throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
// 获取请求头中的媒体类型
MediaType contentType = inputMessage.getHeaders().getContentType();
// 标记是否缺失媒体类型
boolean noContentType = false;
// 如果请求头中没有媒体类型,使用二进制流媒体类型
if (contentType == null) {
noContentType = true;
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
// 获取参数类型
Class<?> contextClass = parameter.getContainingClass();
// 获取目标类型
Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
// 如果目标类型为空,解析泛型获取目标类型
if (targetClass == null) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
targetClass = (Class<T>) resolvableType.resolve();
}
// 获取HTTP方法
HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null);
// 初始化参数值为NO_VALUE
Object body = NO_VALUE;
// 定义空请求体检查类
EmptyBodyCheckingHttpInputMessage message = null;
try {
// 创建空请求体检查类
message = new EmptyBodyCheckingHttpInputMessage(inputMessage);
// 遍历消息转换器列表,找到能解析参数值的消息转换器,设置参数值
for (HttpMessageConverter<?> converter : this.messageConverters) {
// 获取消息转换器类型
Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
// 获取泛型消息转换器
GenericHttpMessageConverter<?> genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
// 判断消息转换器能否解析返回值,如果是泛型消息转换器判断是否能解析参数类型和媒体类型,如果不是泛型消息转换器判断是否能解析媒体类型
if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) : (targetClass != null && converter.canRead(targetClass, contentType))) {
// 判断请求体是否有内容
if (message.hasBody()) {
// 允许`@ControllerAdvice`注解在读之前处理参数值
HttpInputMessage msgToUse = getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
// 调用消息转换器读取参数值
body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) : ((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
// 允许`@ControllerAdvice`注解在读取参数值后处理参数值
body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
} else {
// 允许`@ControllerAdvice`注解处理参数值
body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
}
// 跳出循环,返回参数值
break;
}
}
} catch (IOException ex) {
// 抛出异常
throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage);
} finally {
// 关闭流,防止资源泄漏
if (message != null && message.hasBody()) {
closeStreamIfNecessary(message.getBody());
}
}
// 判断请求体参数值是否为空
if (body == NO_VALUE) {
// 如果请求体参数值为空,并且无需请求体
if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) || (noContentType && !message.hasBody())) {
return null;
}
// 否则抛出异常,提示不支持的媒体类型
throw new HttpMediaTypeNotSupportedException(contentType, getSupportedMediaTypes(targetClass != null ? targetClass : Object.class));
}
// 返回参数值
return body;
}

2.7.2 处理返回值

调用HandlerMethodReturnValueHandlerComposite的handleReturnValue()方法,使用返回值处理器处理返回值:

java
1
2
3
4
5
6
7
8
9
10
11
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception {
// 获取返回值处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
// 如果没有合适的处理器,则抛出异常
if (handler == null) {
throw new IllegalArgumentException( ... );
}
// 设置响应内容
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
2.7.2.1 获取返回值处理器

调用HandlerMethodReturnValueHandlerComposite的selectHandler()方法,获取返回值处理器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
// 判断返回值是否为异步类型
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
// 遍历所有返回值处理器,返回匹配的返回值处理器
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
// 如果是异步返回值,但是当前处理器不是异步处理器,则跳过
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
// 如果当前返回值处理器支持该返回类型,则返回第一个匹配的处理器
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
// 没有找到合适的返回值处理器
return null;
}

HandlerMethodReturnValueHandler用于根据返回类型处理返回值,有多种实现类:

  • ModelAndViewMethodReturnValueHandler:支持处理使用ModelAndView类型的返回值,用于返回使用数据的视图页面。
  • ViewMethodReturnValueHandler:支持处理使用View类型的返回值,用于返回视图页面。
  • ViewNameMethodReturnValueHandler:支持处理使用String类型的返回值,用于返回视图页面。
  • ModelMethodProcessor:支持处理使用Model类型的返回值,用于返回模型数据。
  • MapMethodProcessor:支持处理使用Map类型的返回值,用于返回模型数据。
  • RequestResponseBodyMethodProcessor:支持处理使用@ResponseBody注解的返回值,用于返回JSON数据。
  • HttpEntityMethodProcessor:支持处理使用HttpEntity类型的返回值,用于返回响应实体。
  • AsyncTaskMethodReturnValueHandler:支持处理使用WebAsyncTask类型的返回值,用于异步处理返回值。
  • DeferredResultMethodReturnValueHandler:支持处理使用DeferredResult类型的返回值,用于异步处理返回值。
  • CallableMethodReturnValueHandler:支持处理使用Callable类型的返回值,用于异步处理返回值。
  • ModelAttributeMethodProcessor:支持处理使用@ModelAttribute注解的返回值,用于设置模型数据。
  • 也支持通过实现HandlerMethodReturnValueHandler接口的方式自定义处理器。
2.7.2.2 设置响应内容
2.7.2.2.1 普通视图

如果是普通视图的返回类型,使用ViewNameMethodReturnValueHandler处理返回值。

调用ViewNameMethodReturnValueHandler的handleReturnValue()方法,处理视图:

java
1
2
3
4
5
6
7
8
9
10
11
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception {
// 转换视图
String viewName = returnValue.toString();
// 设置视图
mavContainer.setViewName(viewName);
// 如果是重定向视图,则设置重定向模型场景
if (isRedirectViewName(viewName)) {
mavContainer.setRedirectModelScenario(true);
}
}
2.7.2.2.2 内容协商

如果是@ResponseBody注解的返回类型,使用RequestResponseBodyMethodProcessor处理返回值。

调用RequestResponseBodyMethodProcessor的handleReturnValue()方法,处理内容协商:

java
1
2
3
4
5
6
7
8
9
10
11
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 标记不用处理返回值
mavContainer.setRequestHandled(true);
// 创建输入消息
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
// 创建输出消息
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 处理内容协商,写入返回值
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

调用AbstractMessageConverterMethodProcessor的writeWithMessageConverters()方法,处理内容协商,写入返回值:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 定义返回值
Object body;
// 定义返回值类型
Class<?> valueType;
// 定义目标类型
Type targetType;
// 判断返回值是否是CharSequence类型
if (value instanceof CharSequence) {
// 如果是CharSequence类型,直接转换为字符串类型
body = value.toString();
valueType = String.class;
targetType = String.class;
} else {
// 如果不是CharSequence类型,根据返回值类型获取返回值类型和目标类型
body = value;
valueType = getReturnValueType(body, returnType);
targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());
}
// 判断返回值是否是Resource类型
if (isResourceType(value, returnType)) {
...
}
// 选择媒体类型
MediaType selectedMediaType = null;
// 获取响应头中的媒体类型
MediaType contentType = outputMessage.getHeaders().getContentType();
// 是否已经设置了媒体类型
boolean isContentTypePreset = contentType != null && contentType.isConcrete();
// 判断是否已经设置了媒体类型
if (isContentTypePreset) {
// 如果已经设置了媒体类型,直接使用
selectedMediaType = contentType;
} else {
// 如果没有设置媒体类型,根据请求头中的媒体类型进行内容协商
HttpServletRequest request = inputMessage.getServletRequest();
// 获取客户端支持的媒体类型,默认根据请求头获取
List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);
// 获取服务端能解析返回值的消息转换器支持的媒体类型
List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);
// 通过双重循环,找到合适的媒体类型
List<MediaType> mediaTypesToUse = new ArrayList<>();
for (MediaType requestedType : acceptableTypes) {
for (MediaType producibleType : producibleTypes) {
if (requestedType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
}
}
}
// 对媒体类型列表进行排序
MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
// 遍历媒体类型列表,选择首个合适的媒体类型
for (MediaType mediaType : mediaTypesToUse) {
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
} else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
}
// 如果选择了媒体类型,根据媒体类型选择消息转换器,写入返回值
if (selectedMediaType != null) {
// 移除媒体类型的权重
selectedMediaType = selectedMediaType.removeQualityValue();
// 遍历消息转换器列表,找到能解析返回值的消息转换器,将返回值和媒体类型设置到响应
for (HttpMessageConverter<?> converter : this.messageConverters) {
// 获取泛型消息转换器
GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
// 判断消息转换器能否解析返回值,如果是泛型消息转换器判断是否能解析返回值和目标类型,如果不是泛型消息转换器判断是否能解析返回值
if (genericConverter != null ? ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) : converter.canWrite(valueType, selectedMediaType)) {
// 允许`@ControllerAdvice`注解在写之前处理返回值
body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType, (Class<? extends HttpMessageConverter<?>>) converter.getClass(), inputMessage, outputMessage);
// 如果返回值不为空,写入响应
if (body != null) {
// 修改响应头
addContentDispositionHeader(inputMessage, outputMessage);
// 判断是否泛型消息转换器
if (genericConverter != null) {
// 如果是泛型消息转换器,根据返回值和目标类型,将媒体类型写入响应
genericConverter.write(body, targetType, selectedMediaType, outputMessage);
} else {
// 如果不是泛型消息转换器,根据返回值,将媒体类型写入响应
((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
}
}
// 设置响应结束,正常返回
return;
}
}
}
// 如果没有找到合适的媒体类型,抛出异常
if (body != null) {
Set<MediaType> producibleMediaTypes = (Set<MediaType>) inputMessage.getServletRequest().getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (isContentTypePreset || !CollectionUtils.isEmpty(producibleMediaTypes)) {
throw new HttpMessageNotWritableException("No converter for [" + valueType + "] with preset Content-Type '" + contentType + "'");
}
throw new HttpMediaTypeNotAcceptableException(getSupportedMediaTypes(body.getClass()));
}
}

HttpMessageConverter用于设置返回值和媒体类型,有多种实现类:

  • ByteArrayHttpMessageConverter:用于处理字节数组。
  • StringHttpMessageConverter:用于处理字符串。
  • MappingJackson2HttpMessageConverter:用于处理JSON格式的响应,需要导入JSON依赖:
    pom.xml
    1
    2
    3
    4
    5
    6
    <!-- Jackson -->
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.5</version>
    </dependency>
  • MappingJackson2XmlHttpMessageConverter:用于处理XML格式的响应,需要导入XML依赖。
    pom.xml
    1
    2
    3
    4
    5
    6
    <!-- Jackson XML -->
    <dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.5</version>
    </dependency>

2.8 处理模型视图

调用RequestMappingHandlerAdapter的getModelAndView()方法,处理模型视图:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest)
throws Exception {
// 使用模型工厂更新模型数据
modelFactory.updateModel(webRequest, mavContainer);
// 如果请求已经被处理,比如@ResponseBody注解,则返回null
if (mavContainer.isRequestHandled()) {
return null;
}
// 获取模型数据
ModelMap model = mavContainer.getModel();
// 创建模型视图
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
// 处理视图
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
// 处理重定向视图用到的闪存属性
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (request != null) {
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
}
// 返回模型视图
return mav;
}

2.9 处理视图

2.9.1 准备视图

调用DispatcherServlet的processDispatchResult()方法,处理视图:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception)
throws Exception {
// 判断是否需要渲染视图
if (mv != null && !mv.wasCleared()) {
// 渲染视图
render(mv, request, response);
}
// 判断是否异步处理线程,如果是则立即返回,模型视图由其他线程处理
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
return;
}
// 使用处理器执行链中的拦截器链进行结束处理
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}

调用DispatcherServlet的render()方法,渲染视图:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 本地化
Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);
// 准备视图
View view;
// 获取视图名称
String viewName = mv.getViewName();
// 判断视图名称是否存在
if (viewName != null) {
// 通过名称获取视图
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
} else {
// 通过对象获取视图
view = mv.getView();
}
// 如果指定了HTTP状态码,则将其设置到响应中
if (mv.getStatus() != null) {
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, mv.getStatus());
response.setStatus(mv.getStatus().value());
}
// 渲染视图
view.render(mv.getModelInternal(), request, response);
}

2.9.2 获取视图

2.9.2.1 通过名称获取视图

调用DispatcherServlet的resolveViewName()方法,通过名称获取视图:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model, Locale locale, HttpServletRequest request)
throws Exception {
// 遍历所有视图解析器,返回视图对象
if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}

ViewResolver用于将视图名称解析为视图对象,有多种实现类:

  • InternalResourceViewResolver:支持解析JSP页面。最常见的解析器。
  • BeanNameViewResolver:支持将逻辑视图名解析为Bean对象。
  • XmlViewResolver:支持解析XML文件。
  • ResourceBundleViewResolver:支持解析属性文件。
  • 也支持通过实现ViewResolver接口的方式自定义处理。
2.9.2.2 通过对象获取视图

调用ModelAndView的getView()方法,通过对象获取视图:

java
1
2
3
4
public View getView() {
// 返回视图对象
return (this.view instanceof View ? (View) this.view : null);
}

2.9.3 渲染视图

调用AbstractView的render()方法,渲染视图:

java
1
2
3
4
5
6
7
8
9
public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 合并模型数据
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
// 准备响应
prepareResponse(request, response);
// 实际渲染逻辑
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

评论