-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Mihhail Verhovtsov opened SPR-8640 and commented
We wanted to change the way Spring's ContentNegotiatingViewResolver resolves views, but could not achive that, because it uses a private method to get a list of view candidates:
private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes)
throws Exception {
List<View> candidateViews = new ArrayList<View>();
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
candidateViews.add(view);
}
for (MediaType requestedMediaType : requestedMediaTypes) {
List<String> extensions = getExtensionsForMediaType(requestedMediaType);
for (String extension : extensions) {
String viewNameWithExtension = viewName + "." + extension;
view = viewResolver.resolveViewName(viewNameWithExtension, locale);
if (view != null) {
candidateViews.add(view);
}
}
}
}
if (!CollectionUtils.isEmpty(this.defaultViews)) {
candidateViews.addAll(this.defaultViews);
}
return candidateViews;
}What we don't like in the original method was that it loops through every view resolver and asks for a view. It also adds an extension to the view name and then asks again for such a view. In out opinion, this could be too expensive operation, because internally views try to load template resources from file system and fail with exception. This is the way VelocityEngine tries to create views. More over, Velocity logs a message at ERROR level for each attempt to load a non-existing template.
Our custom improvement would be to use one-to-one relationship between media type and view resolver. We would like to select one view resolver by media type and then once ask it for a view.
We could have implemented that if getCandidateViews method would have visibility level of protected.
Affects: 3.1 M2
Issue Links:
- Content negotiation improvements [SPR-8410] #13057 Content negotiation improvements