SpringMVC源码分析(使用多个视图解析器)附详细SpringMVC工作流程图

DispatherServlet类分析

首先,我们看DispatherServlet类中的初始化试图解析器的方法
在这里插入图片描述
我们逐步来看代码:

this.viewResolvers = null;
//首先上方的代码表示可以加载多个视图解析器

		//detectAllViewResolvers表示加载容器中所有的视图器
		if (this.detectAllViewResolvers) {
			// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
			在容器的上下文中寻找所有的视图解析器
			Map<String, ViewResolver> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.viewResolvers = new ArrayList<>(matchingBeans.values());
				// We keep ViewResolvers in sorted order.
				AnnotationAwareOrderComparator.sort(this.viewResolvers);
			}
		}

但是通常detectAllViewResolvers的默认值会设置成为TRUE,默认会加载所有视图解析器
在这里插入图片描述

Map<String, ViewResolver> matchingBeans这个Map集合,通常寻找的所有的视图解析器之后全部存储到Map集合中,名字和本身的对象存储,之后调用AnnotationAwareOrderComparator.sort(this.viewResolvers)方法,对所有的视图解析器进行排序,按照本身的order属性

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

之后发送请求之后,中央控制器收到请求之后,会调用service方法,紧接着调用processRequest方法,之后进入到DispatherServlet类中的doService方法中,之后调用如下图:
在这里插入图片描述

resolveViewName方法:

我们细看resolveViewName方法:

public View resolveViewName(String viewName, Locale locale) throws Exception {
		RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
		Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
		
		List<MediaType> requestedMediaTypes = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
		if (requestedMediaTypes != null) {
		
			//筛选出所有的候选视图
			List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
			//选出最好的视图
			View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);


			if (bestView != null) {
				return bestView;
			}
		}

getCandidateViews方法

进入getCandidateViews方法:

//遍历所有的视图解析器
for (ViewResolver viewResolver : this.viewResolvers) {
				//从每一个视图解析其中寻找视图
				View view = viewResolver.resolveViewName(viewName, locale);
				//如果视图不为NULL,就加入集合
				if (view != null) {
					candidateViews.add(view);
				}

在这里插入图片描述

AbstractUrlBasedView 类

AbstractUrlBasedView 类中:

	protected View loadView(String viewName, Locale locale) throws Exception {
		AbstractUrlBasedView view = buildView(viewName);
		//先构建VIEW  最后再检查
		View result = applyLifecycleMethods(viewName, view);
		//检查视图是否存在,不存在返回NULL
		return (view.checkResource(locale) ? result : null);
	}


//默认返回true,证明可能返回的view是损坏的用不了的,有风险的
public boolean checkResource(Locale locale) throws Exception {
		return true;
	}

FreeMarkerView类

FreeMarkerView类中:

public boolean checkResource(Locale locale) throws Exception {
		String url = getUrl();
		Assert.state(url != null, "'url' not set");

		try {
			// Check that we can get the template, even if we might subsequently get it again.
			getTemplate(url, locale);
			return true;
		}
		catch (FileNotFoundException ex) {
			// Allow for ViewResolver chaining...
			return false;
		}
		catch (ParseException ex) {
			throw new ApplicationContextException("Failed to parse [" + url + "]", ex);
		}
		catch (IOException ex) {
			throw new ApplicationContextException("Failed to load [" + url + "]", ex);
		}
	}

checkResource方法有非常好的检查view,Thymeleaf中并没有检查的方法

getBestView方法

进入getBestView方法:
在这里插入图片描述
当每一个视图解析器的mediaType与候选视图的ContentType相同时就返回,当有多个视图都相同时返回第一个,按视图解析器的order优先级来排序
在这里插入图片描述

详细SpringMVC工作流程图

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值