In Spring MVC view resolvers help the Dispatcher Servlet in identifying the views which has to be rendered in response for a request. There are lot view resolvers available in Spring framework. For example: InternalResourceViewResolver, ResourceBundleViewResolver, XmlViewResolver etc. If needed, the programmers can have custom view resolvers by extending existing view resolver implementation or implementing the ViewResolver interface. Spring applications also support configuration of multiple view resolvers. This article, will explain, chaining view resolvers and extending view resolvers in detail. This article assuming that reads have the basic knowledge on the Spring MVC framework. If you don’t have sufficuent knowledge on the topic, please read Introduction to Spring MVC before start reading this article.If you are looking ot buy spring books, here is the list of spring books.
also read:
What is View Resolver in Spring MVC?
In Spring MVC, after handling the requests the controller handler methods will resolve to a view name. For example:
@Controller public class MyController { @RequestMapping("/hello.htm") public ModelAndView getMsg(){ String message="Hi, This is an example for Internal Resource View Resolver"; return new ModelAndView("MyView","msg",message); } }
Here getMsg() is the handler method for the request “/hello.htm”. In response a view has to be rendered and the name of the view is “MyView”. View Resolver helps in mapping the view name to the actual view. ViewResolvers in Spring MVC implements ViewResolver interface. Some of the View Resolvers available in Spring framework are,
- AbstractCachingViewResolver
- InternalResourceViewResolver
- ResourceBundleViewResolver
- UrlBasedViewResolver
- VelocityViewResolver / FreeMarkerViewResolver
- XmlViewResolver
These view resolvers when configured in dispatcher servlet’s configuration file will do the mapping of view names to actual views. While configuring the following InternalViewReoslver,
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
when the controller returns the view name “MyView”, the InternalResourceViewResolver will try to identify the internal resource of the application “/jsp/ MyView.jsp”. View resolution depends on the type of the ViewResolver used. For example: If ResourceBundleViewResolver is used, the view will be identified based on the entries in a resource bundle (property file) associated with the view resolver.
Chaining ViewResolvers
In Spring, multiple view resolvers can be configured and used in an application. For example consider the following scenario: The application requires Tiles to generate the User Interface. Whenever there is an exception, failure.jsp, the internal resource of the application has to be displayed to the user. Such a requirement needs both TilesViewResolver and InternalResourceViewResolver to be configured. Order property in the view resolver bean definition will help in ordering the view resolvers in the chain. Higher the value, later will be the position of the view resolver in the chain.
View Resolvers and Exception Resolver Configuration
<bean id="viewResolver1" class="org.springframework.web.servlet.view.tiles2.TilesViewResolver" p:order="1"/> <bean id="viewResolver2" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="2"/> <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"> <property name="definitions"> <list> <value>/WEB-INF/tiles.xml</value> </list> </property> </bean> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <map> <entry key="Exception" value="/WEB-INF/jsp/failure.jsp"/> </map> </property> </bean>
How this works?
When a view has to be resolved, the spring web application context will be searched for the view resolver. If the identified view resolver is able to handle the view resolving, then the rest of the view resolvers configured in the context will be ignored else the next one in the context will be looked up. If no view resolvers result in a view, then the exception will be thrown. In the above example, Tiles views will be resolved by TilesViewResolver and exception page will be resolved by InternalResourceViewResolver.
While chaining, the view resolvers should return a view object or null if the view could not be found. But not all the view resolvers do this. For example InternalResourceViewResolver will attempt to generate views no matter whether the view exists or not. Such view resolver should be at the end of the chain.
Extending View Resolvers
View Resolvers can be extended to have custom behaviors. For example: Let us see how to extend InternalResourceViewResolver, so that it will generate the required view object if the view exists else some default view.
public class MyViewResolver extends InternalResourceViewResolver { @Override protected AbstractUrlBasedView buildView(String viewName) throws Exception { HttpServletRequest request=((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); String viewFile =request.getRealPath(this.getPrefix()+viewName+this.getSuffix()); File reqFile=new File(viewFile); System.out.println(reqFile.getAbsolutePath()+":extists:"+reqFile.exists()); if(!reqFile.exists()){ viewName="default"; } InternalResourceView view = (InternalResourceView) super.buildView(viewName); view.setAlwaysInclude(false); return view; } } <bean class="mypack.MyViewResolver"> <property name="prefix" value="/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
In this example the View Resolver will check for the existence of the view required to be rendered. If the view does not exist it will display the default page.
also read:
Conclusion
Spring MVC provides various view resolver implementation for indentifying views based on the view names. As said in the above example view resolvers can be chained and extended based on our requirement.