SpringMVC 九大组件之 ViewResolver 深入分析

  • ViewResolverComposite:这是一个组合的视图解析器,届时可以用来代理其他具体干活的视图解析器。

接下来我们就对这四个视图解析器逐一进行介绍,先从最简单的 BeanNameViewResolver 开始吧。

2.BeanNameViewResolver


BeanNameViewResolver 的处理方式非常简单粗暴,直接根据 viewName 去 Spring 容器中查找相应的 Bean 并返回,如下:

@Override

@Nullable

public View resolveViewName(String viewName, Locale locale) throws BeansException {

ApplicationContext context = obtainApplicationContext();

if (!context.containsBean(viewName)) {

return null;

}

if (!context.isTypeMatch(viewName, View.class)) {

return null;

}

return context.getBean(viewName, View.class);

}

先去判断下有没有相应的 Bean,然后再检查下 Bean 的类型对不对,都没问题,直接查找返回即可。

3.ContentNegotiatingViewResolver


ContentNegotiatingViewResolver 其实是目前广泛使用的一个视图解析器,主要是添加了对 MediaType 的支持。ContentNegotiatingViewResolver 这个是 Spring3.0 中引入的的视图解析器,它不负责具体的视图解析,而是根据当前请求的 MIME 类型,从上下文中选择一个合适的视图解析器,并将请求工作委托给它。

这里我们就先来看看 ContentNegotiatingViewResolver#resolveViewName 方法:

public View resolveViewName(String viewName, Locale locale) throws Exception {

RequestAttributes attrs = RequestContextHolder.getRequestAttributes();

List requestedMediaTypes = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());

if (requestedMediaTypes != null) {

List candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);

View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);

if (bestView != null) {

return bestView;

}

}

if (this.useNotAcceptableStatusCode) {

return NOT_ACCEPTABLE_VIEW;

}

else {

return null;

}

}

这里的代码逻辑也比较简单:

  • 首先是获取到当前的请求对象,可以直接从 RequestContextHolder 中获取。然后从当前请求对象中提取出 MediaType。

  • 如果 MediaType 不为 null,则根据 MediaType,找到合适的视图解析器,并将解析出来的 View 返回。

  • 如果 MediaType 为 null,则为两种情况,如果 useNotAcceptableStatusCode 为 true,则返回 NOT_ACCEPTABLE_VIEW 视图,这个视图其实是一个 406 响应,表示客户端错误,服务器端无法提供与 Accept-Charset 以及 Accept-Language 消息头指定的值相匹配的响应;如果 useNotAcceptableStatusCode 为 false,则返回 null。

现在问题的核心其实就变成 getCandidateViews 方法和 getBestView 方法了,看名字就知道,前者是获取所有的候选 View,后者则是从这些候选 View 中选择一个最佳的 View,我们一个一个来看。

先来看 getCandidateViews:

private List getCandidateViews(String viewName, Locale locale, List requestedMediaTypes)

throws Exception {

List candidateViews = new ArrayList<>();

if (this.viewResolvers != null) {

for (ViewResolver viewResolver : this.viewResolvers) {

View view = viewResolver.resolveViewName(viewName, locale);

if (view != null) {

candidateViews.add(view);

}

for (MediaType requestedMediaType : requestedMediaTypes) {

List extensions = this.contentNegotiationManager.resolveFileExtensions(requestedMediaType);

for (String extension : extensions) {

String viewNameWithExtension = viewName + ‘.’ + extension;

view = viewResolver.resolveViewName(viewNameWithExtension, locale);

if (view != null) {

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值