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、第二步,验证上述的三种情况