后端——框架——视图层框架——spring_mvc——《官网》阅读笔记——第一章节11(核心对象,视图解析器,ContentNegotiatingViewResolver)

1、概念

  它本身不进行视图解析过程(viewName--->View对象的转换过程),它拥有ViewResolver集合,根据响应的Media-type查找ViewResolver。

  当没有找到ViewResolver时,依据useNotAcceptableStatusCode,defaultView的值分为以下三种情形

  1. 当defaultView存在时,无论useNotAcceptableStatusCode的值为true 或false,始终使用defaultView,响应码为200
  2. 当defaultView不存在时,userNotAcceptableStatusCode的值为true时,使用NOT_ACCEPTABLE_VIEW,不支持的类型,响应码为406。
  3. 当defaultView不存在,userNotAcceptableStatusCode的值为false时,抛出异常,无法解析。

  源码如下:

@Override
@Nullable
public View resolveViewName(String viewName, Locale locale) throws Exception {
    // 从请求中获取请求
	RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
	Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
	// 从请求中获取Media type的类型
	List<MediaType> requestedMediaTypes = 
getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
	// 从候选的viewResolver选出最优的视图解析器
	if (requestedMediaTypes != null) {
		List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
		View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);
		if (bestView != null) {
			return bestView;
		}
	}
	String mediaTypeInfo = logger.isDebugEnabled() && requestedMediaTypes != null ?" given " + requestedMediaTypes.toString() : "";
	// Media-type无法处理,返回406
	if (this.useNotAcceptableStatusCode) {
		if (logger.isDebugEnabled()) {
			logger.debug("Using 406 NOT_ACCEPTABLE" + mediaTypeInfo);
		}
		return NOT_ACCEPTABLE_VIEW;
	}
	else {
	// 找不到对应的viewResolver,继续ViewResolver链的下一个视图解析器
		logger.debug("View remains unresolved" + mediaTypeInfo);
		return null;
	}
}

2、使用

  它的使用步骤如下

  1. 第一步:注册ContentNegotiatingViewResolver,把它的优先级设置为最高,即Order的值设置为最小Integer.min。
  2. 第二步:注册其他ViewResolver,它会根据响应的内容查找对应的ViewResolver。后续PDF,Excel时会看到它的用法。

3、示例

  1、第一步,注册ContentNegotiatingViewResolver,第一个参数是useNotAcceptableStatusCode的值,第二个参数是defaultView的值,它是View接口类结构中的任意一个实现类。

/**
 * 配置视图解析器
 */
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
	// 注册ContentNegotiatingViewResolver
	registry.enableContentNegotiation(false,new MyView());
}

  2、第二步,验证上述的三种情况

原文地址:https://www.cnblogs.com/rain144576/p/12903050.html