15.4 Handler mappings

In previous versions of Spring, users were required to define HandlerMappings in the web application context to map incoming web requests to appropriate handlers. With the introduction of Spring 2.5, the DispatcherServlet enables the DefaultAnnotationHandlerMapping, which looks for @RequestMapping annotations on @Controllers. Typically, you do not need to override this default mapping, unless you need to override the default property values. These properties are:

interceptors

List of interceptors to use. HandlerInterceptors are discussed in Section 15.4.1, “Intercepting requests - the HandlerInterceptor interface”.

defaultHandler

Default handler to use, when this handler mapping does not result in a matching handler.

order

Based on the value of the order property (see the org.springframework.core.Ordered interface), Spring sorts all handler mappings available in the context and applies the first matching handler.

alwaysUseFullPath

If true , Spring uses the full path within the current servlet context to find an appropriate handler. If false (the default), the path within the current servlet mapping is used. For example, if a servlet is mapped using /testing/* and the alwaysUseFullPath property is set to true, /testing/viewPage.html is used, whereas if the property is set to false, /viewPage.html is used.

urlDecode

Defaults to true, as of Spring 2.5. If you prefer to compare encoded paths, set this flag to false. However, the HttpServletRequest always exposes the servlet path in decoded form. Be aware that the servlet path will not match when compared with encoded paths.

lazyInitHandlers

Allows lazy initialization of singleton handlers (prototype handlers are always lazy-initialized). The default value is false.

[Note]Note

The alwaysUseFullPath, urlDecode, and lazyInitHandlers properties are only available to subclasses of org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.

The following example shows how to override the default mapping and add an interceptor:

<beans>
  <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
      <bean class="example.MyInterceptor"/>
    </property>
  </bean>

<beans>

15.4.1 Intercepting requests - the HandlerInterceptor interface

Spring's handler mapping mechanism includes handler interceptors, which are useful when you want to apply specific functionality to certain requests, for example, checking for a principal.

Interceptors located in the handler mapping must implement HandlerInterceptor from the org.springframework.web.servlet package. This interface defines three methods: one is called before the actual handler is executed; one is called after the handler is executed; and one is called after the complete request has finished. These three methods should provide enough flexibility to do all kinds of preprocessing and postprocessing.

The preHandle(..) method returns a boolean value. You can use this method to break or continue the processing of the execution chain. When this method returns true, the handler execution chain will continue; when it returns false, the DispatcherServlet assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.

The following example defines a handler mapping which maps all requests matching the URL patterns "/*.form" and "/*.view" to a particular controller, editAccountFormController. An interceptor has been added that intercepts these requests and reroutes the user to a specific page if the time is not between 9 a.m. and 6 p.m.

<beans>
    <bean id="handlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="officeHoursInterceptor"/>
            </list>
        </property>
        <property name="mappings">
            <value>
                /*.form=editAccountFormController
                /*.view=editAccountFormController
            </value>
        </property>
    </bean>

    <bean id="officeHoursInterceptor"
          class="samples.TimeBasedAccessInterceptor">
        <property name="openingTime" value="9"/>
        <property name="closingTime" value="18"/>
    </bean>
<beans>
package samples;

public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {

    private int openingTime;
    private int closingTime;

    public void setOpeningTime(int openingTime) {
        this.openingTime = openingTime;
    }

    public void setClosingTime(int closingTime) {
        this.closingTime = closingTime;
    }

    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler) throws Exception {

        Calendar cal = Calendar.getInstance();
        int hour = cal.get(HOUR_OF_DAY);
        if (openingTime <= hour < closingTime) {
            return true;
        } else {
            response.sendRedirect("http://host.com/outsideOfficeHours.html");
            return false;
        }
    }
}

Any request handled by this mapping is intercepted by the TimeBasedAccessInterceptor. If the current time is outside office hours, the user is redirected to a static HTML file that says, for example, you can only access the website during office hours.

As you can see, the Spring adapter class HandlerInterceptorAdapter makes it easier to extend the HandlerInterceptor interface.