diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java index 142b4e949c..5110e3f7ce 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java @@ -53,6 +53,7 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.support.WebApplicationObjectSupport; import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.SmartView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.util.UrlPathHelper; @@ -476,29 +477,32 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport } private View getBestView(List candidateViews, List requestedMediaTypes) { - MediaType bestRequestedMediaType = null; - View bestView = null; - for (MediaType requestedMediaType : requestedMediaTypes) { + for (View candidateView : candidateViews) { + if (candidateView instanceof SmartView) { + SmartView smartView = (SmartView) candidateView; + if (smartView.isRedirectView()) { + if (logger.isDebugEnabled()) { + logger.debug("Returning redirect view [" + candidateView + "]"); + } + return candidateView; + } + } + } + for (MediaType mediaType : requestedMediaTypes) { for (View candidateView : candidateViews) { if (StringUtils.hasText(candidateView.getContentType())) { MediaType candidateContentType = MediaType.parseMediaType(candidateView.getContentType()); - if (requestedMediaType.includes(candidateContentType)) { - bestRequestedMediaType = requestedMediaType; - bestView = candidateView; - break; + if (mediaType.includes(candidateContentType)) { + if (logger.isDebugEnabled()) { + logger.debug("Returning [" + candidateView + "] based on requested media type '" + + mediaType + "'"); + } + return candidateView; } } } - if (bestView != null) { - if (logger.isDebugEnabled()) { - logger.debug("Returning [" + bestView + "] based on requested media type '" + - bestRequestedMediaType + "'"); - } - break; - } } - return bestView; - + return null; } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java index 32c620077c..77d072adbd 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolverTests.java @@ -402,6 +402,32 @@ public class ContentNegotiatingViewResolverTests { verify(viewResolverMock, viewMock); } + @Test + public void resolveViewNameRedirectView() throws Exception { + request.addHeader("Accept", "application/json"); + request.setRequestURI("/test"); + + ViewResolver xmlViewResolver = createMock(ViewResolver.class); + viewResolver.setViewResolvers(Arrays.asList(xmlViewResolver, new UrlBasedViewResolver())); + + View xmlView = createMock("application_xml", View.class); + View jsonView = createMock("application_json", View.class); + viewResolver.setDefaultViews(Arrays.asList(jsonView)); + + String viewName = "redirect:anotherTest"; + Locale locale = Locale.ENGLISH; + + expect(xmlViewResolver.resolveViewName(viewName, locale)).andReturn(xmlView); + expect(jsonView.getContentType()).andReturn("application/json").anyTimes(); + + replay(xmlViewResolver, xmlView, jsonView); + + View actualView = viewResolver.resolveViewName(viewName, locale); + assertEquals("Invalid view", RedirectView.class, actualView.getClass()); + + verify(xmlViewResolver, xmlView, jsonView); + } + @Test public void resolveViewNoMatch() throws Exception { request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9");