• No results found

Configuring ViewResolvers

In document Spring (Page 114-117)

Building web applications with Spring Web MVC

3.5 Configuring Spring Web MVC: the application context

3.5.4 Configuring ViewResolvers

When a controller is done processing a request, it generally returns a logical view name to DispatcherServlet. The view name serves as a basis for view resolution.

9 Probably HandlerAdapter is a misleading name for the interface. With the adapter design pattern, adapter refers to the implementation code that bridges the two interfaces. The outer interface itself isn’t an adapter.

No biggie, especially because nothing sees HandlerAdapter except DispatcherServlet.

(The controller can also return a null view name to indicate that it has itself handled processing.) When DispatcherServlet receives the view name, it grabs its list of ViewResolvers and iterates over them until it finds one that’s able to generate a View from the view name.

We’ll look at this chaining behavior in a few moments, but first let’s examine the default view resolver, which is InternalResourceViewResolver.

INTERNALRESOURCEVIEWRESOLVER, THE DEFAULT VIEW RESOLUTION STRATEGY

The default strategy for view resolution is InternalResourceViewResolver. This allows you to map view names to InternalResourceViews, which represent servlet-based view technologies such as servlets, JSPs, JSTL-based JSPs, and Tiles pages.

InternalResourceViewResolver converts the logical view name to a physical path by taking the logical view name, prepending a configurable prefix, and appending a configurable suffix. By default, the prefix and suffix are empty, which means you have to specify full view paths instead of logical view names to use. Because you don’t usu-ally want to specify full view paths from your controllers—that ties the controller too closely to the view—you’ll generally want to define your own InternalResourceView-Resolver. Here’s a typical configuration:

<bean class="org.springframework.web.servlet.view.

InternalResourceViewResolver"

p:prefix="/WEB-INF/jsp/"

p:suffix=".jsp"/>

If this resolver receives the logical view name contact, for example, it converts that to /WEB-INF/jsp/contact.jsp and then builds a corresponding view. The view is an InternalResourceView if JavaServer Pages Standard Tag Library (JSTL) isn’t on the classpath or else a JstlView if JSTL is present. InternalResourceViewResolver automatically detects the presence or absence of JSTL and selects the correct view type accordingly.

Let’s look at a couple of special view names that InternalResourceViewResolver knows how to handle.

REDIRECT: AND FORWARD:

InternalResourceViewResolver inherits from its UrlBasedViewResolver superclass an awareness of two special view name prefixes, redirect: and forward:. When

Best practice: place JSPs in /WEB-INF/jsp or /WEB-INF/views

In MVC applications, controllers mediate access to views, and you don’t usually want users hitting JSP pages directly. A best practice is to place the JSPs under the /WEB-INF folder where users can’t get to them. Most applications place the JSPs under /WEB-INF/jsp or /WEB-INF/views. By configuring InternalResourceViewResolver with the /WEB-INF/jsp/ or /WEB-INF/views/ prefix, you can ensure that logical view names resolve to JSPs inside /WEB-INF/jsp or /WEB-INF/views, respectively.

InternalResourceViewResolver sees a view name that begins with either of these, it short-circuits standard view resolution and instead returns a special view, either a RedirectView or an InternalResourceView according to whether the prefix is the redirect prefix or the forward prefix.

Redirecting is especially helpful after processing form requests, as you saw in sec-tion 3.3.5. It does, of course, have other applicasec-tions.

Let’s look at some other view resolvers you can use.

BEANNAMEVIEWRESOLVER

One of the simpler view resolvers is BeanNameViewResolver. When it receives a candi-date view name, it checks the application context for a bean with a matching name or ID. If it finds one, it assumes the bean is the desired View and returns it. Otherwise it returns null, which means the DispatcherServlet will move to the next resolver in the chain.

BeanNameViewResolver is nice for simple applications, but as the number of views grows, XmlViewResolver becomes more helpful.

XMLVIEWRESOLVER

XmlViewResolver is conceptually similar to BeanNameViewResolver in that it uses named View beans to resolve view names to views. The difference is that BeanNameView-Resolver assumes that the View beans are defined in the application context, whereas XmlViewResolver assumes that they’re defined in a separate file, using the same Spring beans schema. By default the file is /WEB-INF/views.xml.

OTHER VIEWRESOLVERS AND VIEWS

Spring includes several ViewResolver and View implementations, including those for handling FreeMarker views, Velocity views, and XSLT views.10 Spring 3 introduces new

10Please see the new Thymeleaf template engine at www.thymeleaf.org. It directly supports integration with Spring 3.

Does forward: do anything?

Once the view name reaches InternalResourceViewResolver, using forward: is almost—but not exactly—the same as using the logical view name. The difference is that with an unprefixed view name, the returned View is either an InternalRe-sourceView or a JstlView depending on whether JSTL is present. With forward:

the view is always an InternalResourceView. Because JstlView provides a super-set of the functionality that InternalResourceView provides, there isn’t a good rea-son to use forward:.

One possible way of using forward: might be to prevent a view name from being han-dled by some other view resolver (other than InternalResourceViewResolver) in view resolver chaining scenarios. We’re a little skeptical of this idea, but it might be useful in some cases.

views for generating RSS and Atom feeds; we show how to generate an RSS feed using the BeanNameViewResolver and AbstractRssFeedView in chapter 8.

CHAINING VIEWRESOLVERS

We’ve alluded several times to the fact that you can chain view resolvers. The usual sce-nario is that you want a standard InternalResourceViewResolver to handle most of your view resolution needs, but sometimes you want other view resolvers, such as BeanNameViewResolver or XmlViewResolver, to handle special cases. Here’s a simple example. Maybe most of your views are JSPs but you also publish an RSS feed. To han-dle that, you’d have an InternalResourceViewResolver to hanhan-dle the JSPs, and you’d probably include a single BeanNameViewResolver for the RSS feed.

To configure multiple view resolvers, you add them to the application context as beans. The ViewResolver implementations implement the Ordered interface, so you can define a processing order using the resolver’s order property if you like. (The numerically lower the order, the higher the precedence.) If you don’t define an explicit processing order, the InternalResourceViewResolver is automatically assumed to be the last resolver in the chain, because it never returns null (and hence never passes processing along to the next processor in the chain).

In document Spring (Page 114-117)