Is it possible to wire a Spring MVC Interceptor using annotations?

Is it possible to wire a Spring MVC Interceptor using annotations and if so could someone provide me with an example of how to do so?

By wire via annotation I am referring to doing as little in the XML configuration as possible. For example in this configuration file I found at http://www.vaannila.com/spring/spring-interceptors.html;

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:interceptors-ref="loggerInterceptor" />
<bean id="loggerInterceptor" class="com.vaannila.interceptor.LoggerInterceptor" />

How little configuration could you get away with there? I imagine an @Autowired would remove the need to explicitly declare the bean in line 2, but would it be possible to get rid of line 1 with an annotation as well?

Spring MVC 3.0: how do I define an interceptor with annotations?

I am developing an app with Spring MVC (3.0). I defined some controllers with annotations, how can I define an intereceptor with annotations too.

Spring mvc interceptor exception

My project is baded on spring mvc, and I wrote a interceptor to intercept request, I want to get parametrts from request, the follows is my code: public boolean preHandle(HttpServletRequest request, H

Spring MVC special login interceptor

I have this small web application, for which I am using Spring MVC 3.0 The way I have implemented the login functionality is via normal Handler Interceptor. i.e. when the request comes in the Session

Spring mvc interceptor Basics

I am new to Spring and currently working on a spring application. I am very confused regarding the spring interceptor and Interceptor in Spring security. I have below doubts. 1. What is the use of Int

It’s possible using Spring Web Mvc without annotations?

I’m doing a training in computer consulting company. The project manager gave me an exercise to do with spring web mvc where do I get the data sent from a form and I need to display them on another pa

Mocking Spring MVC BindingResult when using annotations

I’m migrating a Spring MVC controller to use the newer style annotations, and want to unit test a controller method that validates a command object (see simple example below). @RequestMapping(method

Sending Logging Message with Interceptor in Spring Integration

Is it possible to configure an interceptor in Spring Integration to specify a logging message? This is in contrast to using a wire-tap to send the message to a logging channel to which a logging chann

Spring MVC Annotations and HandleInterceptors

I am on a project using Spring 3.x MVC, and have implemented our controllers using annotations. We recently have a requirement to implement HandlerInterceptors, to which I have had some problems. When

Spring MVC interceptor

I need inputs related to Spring MVC, I have a URL to which a client will send a post request with an xml as the pay load. I plan to have a controller method which maps to the requested url, I want tha

Spring mvc interceptor addObject

I have an interceptor which extends the HandlerInterceptorAdapter. When I add an object to my ModelAndView it also gets added to my url as a path variable but I don’t want that. @Override public void

Answers

I dont know about spring-AOP but if you’re using AspectJ via Spring you can use @Aspect, @Pointcut, @Advise and more…

there’s also a nice article on howto use these annotation with Spring AOP here: http://java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html

As far as I know, there are no ways to configure Spring MVC interceptors without XML at all.

However, there are some simplifications with mvc namespace in the latest versions of Spring 3.0.x (not Spring 3.0.0!):

<mvc:interceptors>
    <bean class="com.vaannila.interceptor.LoggerInterceptor" />
</mvc:interceptors>

See also:

Stumbled upon this question while searching exactly this. Finally I found out that it works in Spring 3.1 using @EnableWebMVC in conjunction with WebMvcConfigurerAdapter.

Simple Example:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggerInterceptor());
    }

}

like Markus Kreusch’answers,It also could work like this

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping RequestMappingHandlerMapping=  super.requestMappingHandlerMapping();
        Object[] interceptors = new Object[1];
        interceptors[0] = new RoleInterceptor();
        RequestMappingHandlerMapping.setInterceptors(interceptors);
        return RequestMappingHandlerMapping;
    }

}

I implemented a working solution using a custom @Interceptor annotation in the spirit of Spring’s @Controller annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Component
public @interface Interceptor {
  String[] pathPatterns() default {};
  String[] excludePathPatterns() default {};
}

This annotation should be applied to HandlerInterceptor types like so:

@Interceptor
public class BuildTimestampInterceptor extends HandlerInterceptorAdapter {
  private final String buildTimestamp;

  public BuildTimestampInterceptor(@Value("${build.timestamp}") String buildTimestamp) {
    this.buildTimestamp = buildTimestamp;
  }

  @Override
  public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
    req.setAttribute("buildTimestamp", buildTimestamp);
    return true;
  }
}

Finally, the processor class, InterceptorProcessor, is a Spring bean that extends WebMvcConfigurerAdapter and implements BeanPostProcessor in order to scan for the custom @Interceptor annotations and register beans having that anntation as HandlerInterceptors inside the overridden addInterceptors method:

@Component
public class InterceptorProcessor extends WebMvcConfigurerAdapter implements BeanPostProcessor {
  private final Map<HandlerInterceptor,Interceptor> interceptors = new HashMap<>();

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    scanForInterceptorAnnotation(bean, beanName);
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String string) throws BeansException {
    return bean;
  }

  protected void scanForInterceptorAnnotation(Object bean, String beanName) {
    Optional<Interceptor> optionalInterceptor = getInterceptorAnnotation(bean.getClass());
    if (optionalInterceptor.isPresent() && bean instanceof HandlerInterceptor) {
      interceptors.put((HandlerInterceptor) bean, optionalInterceptor.get());
    }
  }

  private Optional<Interceptor> getInterceptorAnnotation(Class cls) {
    Annotation[] annotations = cls.getAnnotationsByType(Interceptor.class);
    if (hasValue(annotations)) {
      return Optional.of((Interceptor) annotations[0]);
    }
    return Optional.empty();
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    interceptors.forEach((HandlerInterceptor key, Interceptor val) -> {
      InterceptorRegistration registration = registry.addInterceptor(key);
      if (hasValue(val.pathPatterns())) {
        registration.addPathPatterns(val.pathPatterns());
      }

      if (hasValue(val.excludePathPatterns())) {
        registration.excludePathPatterns(val.excludePathPatterns());
      }
    });
  }

  private static <T> boolean hasValue(T[] array) {
    return array != null && array.length > 0;
  }
}

Just remember to have your spring application scan for this processor bean in order to have it actually register your @Interceptors. Something like:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...