1、概念
它本身不进行视图解析过程(viewName--->View对象的转换过程),它拥有ViewResolver集合,根据响应的Media-type查找ViewResolver。
当没有找到ViewResolver时,依据useNotAcceptableStatusCode,defaultView的值分为以下三种情形
- 当defaultView存在时,无论useNotAcceptableStatusCode的值为true 或false,始终使用defaultView,响应码为200
- 当defaultView不存在时,userNotAcceptableStatusCode的值为true时,使用NOT_ACCEPTABLE_VIEW,不支持的类型,响应码为406。
- 当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、使用
它的使用步骤如下
- 第一步:注册ContentNegotiatingViewResolver,把它的优先级设置为最高,即Order的值设置为最小Integer.min。
- 第二步:注册其他ViewResolver,它会根据响应的内容查找对应的ViewResolver。后续PDF,Excel时会看到它的用法。
3、示例
1、第一步,注册ContentNegotiatingViewResolver,第一个参数是useNotAcceptableStatusCode的值,第二个参数是defaultView的值,它是View接口类结构中的任意一个实现类。
/**
* 配置视图解析器
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// 注册ContentNegotiatingViewResolver
registry.enableContentNegotiation(false,new MyView());
}
2、第二步,验证上述的三种情况