SpringMVC源码解析(二)

注意,读完本篇文章需要很长很长时间

在上篇文章SpringMVC源码解析(一)中,我们搭建了一个SpringBoot的启动demo,分析了SpringBoot中SpringMVC的自动配置原理以及DispatcherServlet的初始化流程。本篇文章就分析一次请求在SpringMVC中的处理流程

在日常开发中,我们最常用的请求方式大概就是Get和Post了,Tomcat或者Jetty等web服务器在接受到请求后会调用到DispatcherServlet对应的方法

1
2
3
4
5
6
7
8
9
10
11
@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

可以看到其实最终都是调用的同一个方法

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 final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//记录开始时间
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//记录当前线程的信息
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);

try {
//核心处理,往下看
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}

finally {//清除线程绑定信息
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}

if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
if (asyncManager.isConcurrentHandlingStarted()) {
logger.debug("Leaving response open for concurrent processing");
}
else {
this.logger.debug("Successfully completed request");
}
}
}
//发送事件通知
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}


protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}

// 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)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
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());

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);
}

try {
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}

可以看到上方的大段代码都是做的一些准备工作,具体的逻辑接着往下看吧,这个核心流程都在下面这个方法里了

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
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);

// 1.获取对应的handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
//如果没有获取到对应的handler则往response中写入错误信息
noHandlerFound(processedRequest, response);
return;
}

// 2. 获取对应的handlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 处理last-modified情况
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;
}

// 3.调用handle
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果函数调用没有返回视图则使用默认的
applyDefaultViewName(processedRequest, mv);
//执行拦截器
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//4. 处理返回结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", 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);
}
}
}
}
1. 获取handler
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
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//遍历所有的handlerMapping,这里的handlemapping就是初始化阶段构造的三个
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//这里调用具体的handler,哪个handler能够处理就直接返回
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//1. 调用具体的实现去获取handler
Object handler = getHandlerInternal(request);
//如果为空使用默认的
if (handler == null) {
handler = getDefaultHandler();
}
//没有默认的返回空
if (handler == null) {
return null;
}
// 尝试通过BeanName去获取handler
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//2. 获取handler执行链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
1. 获取具体的handler

这里以AbstractUrlHandlerMapping为例解读一下,顾明思议,这个类是根据请求url获取响应的handler的

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
104
105
106
107
108
109
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
//截取url
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
//根据url寻找handler
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
// 如果请求路径为/则使用RootHandler
Object rawHandler = null;
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
if (rawHandler == null) {
//使用默认
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
// 根据beanName尝试获取Handler
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = obtainApplicationContext().getBean(handlerName);
}//校验
validateHandler(rawHandler, request);
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Mapping [" + lookupPath + "] to " + handler);
}
else if (handler == null && logger.isTraceEnabled()) {
logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
}


protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 直接根据url匹配
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
//封装执行链
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}

// 正则匹配
List<String> matchingPatterns = new ArrayList<>();
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern +"/");
}
}
}

String bestMatch = null;
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
matchingPatterns.sort(patternComparator);
if (logger.isDebugEnabled()) {
logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestMatch = matchingPatterns.get(0);
}
if (bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
if (handler == null) {
if (bestMatch.endsWith("/")) {
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
}
if (handler == null) {
throw new IllegalStateException(
"Could not find handler for best pattern match [" + bestMatch + "]");
}
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);

// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
// for all of them
Map<String, String> uriTemplateVariables = new LinkedHashMap<>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (logger.isDebugEnabled()) {
logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
}

// No handler found...
return null;
}
2. 封装执行链

当获取到相应的handler后,查看是否存在拦截器,如果存在的话则加入执行链中

1
2
3
4
5
6
7
8
9
10
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) {

HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
}
return chain;
}
2. 获取handlerAdpter

根据handler获取匹配的handlerAdpter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter ha : this.handlerAdapters) {
if (logger.isTraceEnabled()) {
logger.trace("Testing handler adapter [" + ha + "]");
}
//不同的handlerAdapter的判断方法不同
if (ha.supports(handler)) {
return ha;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
以SimpleControllerHandlerAdapter为例,判断是否实现Controller接口
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
3. 执行请求
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
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {

return ((Controller) handler).handleRequest(request, response);
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception {

if (HttpMethod.OPTIONS.matches(request.getMethod())) {
response.setHeader("Allow", getAllowHeader());
return null;
}

// Delegate to WebContentGenerator for checking and preparing.
checkRequest(request);
prepareResponse(response);

// 如果需要同步session
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
}
调用Controller方法
return handleRequestInternal(request, response);
}
4.处理返回结果
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
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {

boolean errorView = false;
//是否包含异常信息
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {//异常视图处理
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}

if (mv != null && !mv.wasCleared()) {
// 页面跳转处理
render(mv, request, 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");
}
}

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}

if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
if (mv != null && !mv.wasCleared()) {

页面跳转的逻辑

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
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale =
(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
response.setLocale(locale);

View view;
String viewName = mv.getViewName();
if (viewName != null) {
//1.解析视图名
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}

// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}//2.跳转
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
getServletName() + "'", ex);
}
throw ex;
}
}
解析视图名称
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;
}
页面跳转

具体的跳转逻辑是根据当前使用的渲染引擎决定的,比如html、jsp、Thymeleaf等,这里简单 列举一个Thymeleaf的逻辑吧

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
104
105
106
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
this.renderFragment(this.markupSelectors, model, request, response);
}

protected void renderFragment(Set<String> markupSelectorsToRender, Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
ServletContext servletContext = this.getServletContext();
String viewTemplateName = this.getTemplateName();
ISpringTemplateEngine viewTemplateEngine = this.getTemplateEngine();
if (viewTemplateName == null) {
throw new IllegalArgumentException("Property 'templateName' is required");
} else if (this.getLocale() == null) {
throw new IllegalArgumentException("Property 'locale' is required");
} else if (viewTemplateEngine == null) {
throw new IllegalArgumentException("Property 'templateEngine' is required");
} else {
Map<String, Object> mergedModel = new HashMap(30);
Map<String, Object> templateStaticVariables = this.getStaticVariables();
if (templateStaticVariables != null) {
mergedModel.putAll(templateStaticVariables);
}

if (pathVariablesSelector != null) {
Map<String, Object> pathVars = (Map)request.getAttribute(pathVariablesSelector);
if (pathVars != null) {
mergedModel.putAll(pathVars);
}
}

if (model != null) {
mergedModel.putAll(model);
}

ApplicationContext applicationContext = this.getApplicationContext();
RequestContext requestContext = new RequestContext(request, response, this.getServletContext(), mergedModel);
SpringWebMvcThymeleafRequestContext thymeleafRequestContext = new SpringWebMvcThymeleafRequestContext(requestContext, request);
addRequestContextAsVariable(mergedModel, "springRequestContext", requestContext);
addRequestContextAsVariable(mergedModel, "springMacroRequestContext", requestContext);
mergedModel.put("thymeleafRequestContext", thymeleafRequestContext);
ConversionService conversionService = (ConversionService)request.getAttribute(ConversionService.class.getName());
ThymeleafEvaluationContext evaluationContext = new ThymeleafEvaluationContext(applicationContext, conversionService);
mergedModel.put("thymeleaf::EvaluationContext", evaluationContext);
IEngineConfiguration configuration = viewTemplateEngine.getConfiguration();
WebExpressionContext context = new WebExpressionContext(configuration, request, response, servletContext, this.getLocale(), mergedModel);
String templateName;
Set markupSelectors;
if (!viewTemplateName.contains("::")) {
templateName = viewTemplateName;
markupSelectors = null;
} else {
IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);

FragmentExpression fragmentExpression;
try {
fragmentExpression = (FragmentExpression)parser.parseExpression(context, "~{" + viewTemplateName + "}");
} catch (TemplateProcessingException var24) {
throw new IllegalArgumentException("Invalid template name specification: '" + viewTemplateName + "'");
}

ExecutedFragmentExpression fragment = FragmentExpression.createExecutedFragmentExpression(context, fragmentExpression);
templateName = FragmentExpression.resolveTemplateName(fragment);
markupSelectors = FragmentExpression.resolveFragments(fragment);
Map<String, Object> nameFragmentParameters = fragment.getFragmentParameters();
if (nameFragmentParameters != null) {
if (fragment.hasSyntheticParameters()) {
throw new IllegalArgumentException("Parameters in a view specification must be named (non-synthetic): '" + viewTemplateName + "'");
}

context.setVariables(nameFragmentParameters);
}
}

String templateContentType = this.getContentType();
Locale templateLocale = this.getLocale();
String templateCharacterEncoding = this.getCharacterEncoding();
Set processMarkupSelectors;
if (markupSelectors != null && markupSelectors.size() > 0) {
if (markupSelectorsToRender != null && markupSelectorsToRender.size() > 0) {
throw new IllegalArgumentException("A markup selector has been specified (" + Arrays.asList(markupSelectors) + ") for a view that was already being executed as a fragment (" + Arrays.asList(markupSelectorsToRender) + "). Only one fragment selection is allowed.");
}

processMarkupSelectors = markupSelectors;
} else if (markupSelectorsToRender != null && markupSelectorsToRender.size() > 0) {
processMarkupSelectors = markupSelectorsToRender;
} else {
processMarkupSelectors = null;
}

response.setLocale(templateLocale);
if (!this.getForceContentType()) {
String computedContentType = SpringContentTypeUtils.computeViewContentType(request, templateContentType != null ? templateContentType : "text/html;charset=ISO-8859-1", templateCharacterEncoding != null ? Charset.forName(templateCharacterEncoding) : null);
response.setContentType(computedContentType);
} else {
if (templateContentType != null) {
response.setContentType(templateContentType);
} else {
response.setContentType("text/html;charset=ISO-8859-1");
}

if (templateCharacterEncoding != null) {
response.setCharacterEncoding(templateCharacterEncoding);
}
}

viewTemplateEngine.process(templateName, processMarkupSelectors, context, response.getWriter());
}
}


640?wx_fmt=png


发布了160 篇原创文章 · 获赞 20 · 访问量 8632

猜你喜欢

转载自blog.csdn.net/javaxuexilu/article/details/100738703