Spring HandlerInterceptors

When developing a spring MVC application you may want to run the same logic across many different requests, URLs or Controllers. You might first jump to a filter but spring framework also provide a mechanism called HandlerInterceptors. A HandlerInterceptor is similar to a filter but provides the ability for custom pre and post processing. So when would you implement a HandlerInterceptor? Handler interceptors are useful when you want to apply specific functionality to certain requests, for example navigation. Navigation is a common component on each page that is displayed to a user. You might have 50 different controllers with many @RequestMapping so it doesn't make much sense to call NavigationDAO.get() all over.

Implementing HandlerInterceptor Interface

The HandlerInterceptor defines three different methods:

  • preHandle(..) which is called before the handler
  • postHandle(..) is called after the handler is executed
  • afterCompletion(..) is called after the complete request has finished

Keeping with the navigation example we want to make the navigation object available to each view. We can do that by implementing HandlerInterceptor from the org.springframework.web.servlet package and overriding the postHandle method. Once your controller method executes and before your view renders, the postHandle will make the object available to your view where you can perform an include of the navigation in your template.

public class NavigationHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(final HttpServletRequest request,
            final HttpServletResponse response, final Object handler,
            final ModelAndView modelAndView) throws Exception {

        ...

        List<NavigationItem> navItems = Navigation.get(...)
        modelAndView.addObject("navItems", navItems);

        ...
    }
}

Enable handler interceptor

Next we need to tell spring which requests you want the RequestMappingHandlerMapping to process. Using java config we can extend WebMvcConfigurerAdapter and override addInterceptors and add NavigationHandlerInterceptor to InterceptorRegistry. We supply URL patterns in which registered interceptor should apply to and in this case all URLs.

@Configuration
public class ApplicationConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {

        registry.addInterceptor(new NavigationHandlerInterceptor())
                .addPathPatterns("/**");
    }

}

Exclude URL patterns

There is also the ability to exclude URL patterns that you don't want the interceptor to apply to. Let say our application has a series of REST base URLs where we wouldn't want to include navigation. Each URL starts with a pattern of /api/* and by calling excludePathPatterns we can tell spring not to call the interceptor. It might look something like:

@Configuration
public class ApplicationConfigurerAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {

        registry.addInterceptor(new NavigationHandlerInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/api/**");
    }

}