Spring Interceptor not working in Spring Data REST

2020-03-03 06:28发布

问题:

I am working on a project with Spring Data Rest and JPA and I am trying to configure an HTTP interceptor. As per the reference docs, available in Spring Web MVC Docs - Handler Mapping Interceptor, I created a component that extends HandlerInterceptorAdapter as follows:

@Component
public class DBEditorTenantInterceptor extends HandlerInterceptorAdapter {

    Logger logger = LoggerFactory.getLogger(DBEditorTenantInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
         logger.debug("********** INTERCEPTION SUCCESSFUL **********");
         return true;
    }
}

And then, registered the interceptor by extending WebMvcConfig (as explained in Spring Web MVC Docs - Config Interceptors

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    DBEditorTenantInterceptor dbEditorTenantInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(dbEditorTenantInterceptor)
         .addPathPatterns("/**");
    }

}

When I issue HTTP requests to any URL that is not used by Spring Data REST such as /helloworld the Interceptor works as expected, as I see the logger output

017-10-26 13:16:24.689 DEBUG 17012 --- [p-nio-80-exec-4] c.c.v.d.DBEditorTenantInterceptor        : ********** INTERCEPTION SUCCESSFUL **********

However, when the URL is used by spring data rest, my interceptor is not called. This applies to all URLs like /api/{existing entity in model}

Why is my interceptor not called for Spring Data Rest URLs ? What can I do to make my interceptor work for all requests ?

Thanks a lot in advance.

回答1:

By declaring a bean of type MappedInterceptor and injecting it with my interceptor - which extends HandlerInterceptorAdapter, my interceptor was picked up by Spring Data Rest and now works for any URL on the application.

This translated to the following implementation (replacing the one in my original question):

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    DBEditorTenantInterceptor dbEditorTenantInterceptor;

    @Bean
    public MappedInterceptor dbEditorTenantInterceptor() {
        return new MappedInterceptor(new String[]{"/**"}, dbEditorTenantInterceptor);
    }

}

Unfortunately, I could not find any references to this on the Spring documentation.



回答2:

I just want to add something to the @AndrewP's answer...

If you're using only Spring REST Data in your project, and you want to intercept your Spring Repositories and @RepositoryRestControllers, you need only to define a @Bean method with the following syntax:

@Bean
public MappedInterceptor someMethodName() {
    return new MappedInterceptor(
        null,  // => maps to any repository
        new YourInterceptorImpl()
    );
}

Such method must be declared in any @Configuration annotated class; and such class does not need to implement/extend anything special (for example, WebMvcConfigurerAdapter) ... Many documentation on the web implies that, but I think it only applies when you are dealing with Spring MVC Resources!!!

The interceptor implementation must either implement HandlerInterceptor or extend HandlerInterceptorAdapter...