【问题标题】:Add request interceptor outside of Web MVC configuration class在 Web MVC 配置类之外添加请求拦截器
【发布时间】:2023-03-18 09:38:01
【问题描述】:

我正在努力寻找一种从一个或多个附加模块(在本例中为 Maven 模块)中添加请求拦截器的方法。

在主模块中,有一个 Web MVC 配置类,如下所示:

@Configuration
public class WebMvcConfig extends DelegatingWebMvcConfiguration {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // main module interceptors are registered here via
        // registry.addInterceptor(interceptor);
    }

}

现在,在附加模块 1 中,我有 MyFirstCustomInterceptor 和附加模块 2 MySecondCustomInterceptor,我想将它们添加到同一个拦截器注册表中。我觉得这应该很容易,但是在阅读 Spring MVC 官方文档时我找不到明显的方法。

文档中提到并且听起来很有希望的一种方法是使用RequestMappingHandlerMapping bean,它是setInterceptors(Object[] interceptors) 方法。

我尝试通过将 bean 注入应用程序启动的事件侦听器类并通过 requestMappingHandlerMapping.setInterceptors(myCustomerInterceptorArray) 添加自定义拦截器来实现这一点。不幸的是,这并不完全奏效。似乎正在添加拦截器,但 Spring 使用另一个拦截器列表 - adaptedInterceptors - 用于执行链。不幸的是,似乎没有任何公共方法可用于将拦截器添加到 adaptedInterceptors 列表。

我在想可能需要提前调用RequestMappingHandlerMapping.setInteceptors() 方法,或者必须有一种方法可以将WebMvcConfig 扩展到附加模块。但我不确定如何做到这一点。

编辑:

我刚刚想到的另一个想法是基于注入所有HandlerInterceptor bean 的列表。例如:

@Configuration
public class WebMvcConfig extends DelegatingWebMvcConfiguration {

    @Inject private List<HandlerInterceptor> handlerInterceptors;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // Note: the order of the interceptors would likely be an issue here
        for (HandlerInterceptor interceptor : handlerInterceptors) {
            registry.addInterceptor(interceptor);
        }
    }

}

这种方法的唯一问题是没有一种非常好的方法来订购拦截器。这可以通过自定义解决方案来解决,例如在每个拦截器类上添加一个订单注释,并在将它们添加到注册表时考虑到这一点。但它仍然感觉不是 100% 干净。所以我仍然希望有更好的方法。

【问题讨论】:

  • 只需添加一个实现DelegatingWebMvcConfiguration 或扩展WebMvcConfigurerAdapter 的bean 并添加它。只需将此类添加到您的模块中。不要在根应用程序中扩展DelegatingWebMvcConfiguration,只需添加一个带有@EnableWebMvc 注释的@Configuration 类来自定义您的配置,您可以使用WebMvcConfigurer。配置 mvc 内容时会考虑所有实现 WebMvcConfigurer 的 bean。
  • 感谢您的评论!不确定我是否完全理解,我似乎仍然无法让它工作。在我的主模块中,我正在扩展 DelegatingWebMvcConfiguration 而不是使用 EnableWebMvc 注释,因为我在那里进行了一些高级配置。我的理解是拥有一个扩展DelegatingWebMvcConfiguration@Configuration 类相当于使用@EnableWebMvc。我尝试添加实现WebMvcConfigurer@Configuration 类和实现相同的bean。但是对于任何一个,我都没有看到 addInterceptors 方法被调用。
  • 如果您扩展 DelegatingWebMvcConfiguration 并覆盖其中的某些方法,则不再发生委派。因此它不起作用。你在做什么配置?通常,您不必扩展 DelegatingWebMvcConfiguration,并且您可能希望在添加拦截器和高级配置时分开处理(但也许您可以添加完整的配置类)。
  • 谢谢,我没有意识到默认实现是咨询所有配置器,而覆盖它会破坏该功能。在覆盖方法中添加super.addInterceptors(registry) 后,它看起来像预期的那样工作。我不得不扩展DelegatingWebMvcConfiguration 一段时间,因为如果我没记错的话,可以通过WebMvcConfigurerAdapter 配置消息转换器的方式受到限制。我将回顾一下,看看最新的 Spring 版本现在是否不需要这样做。再次感谢!

标签: java spring spring-mvc spring-boot


【解决方案1】:

通常在使用 Spring MVC 时,您应该有一个基于配置的类,@EnableWebMvc

这将在您的根配置中

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {        
        // Add the interceptors for the root here.
    }
}

现在在您的附加项目中添加一个仅添加拦截器的配置类。

@Configuration
public class ModuleAWebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {        
        // Add the interceptors for the Module A here.
    }
}

配置 Spring @MVC 时会参考所有 WebMvcConfigurers。

但是,在您的情况下,这是行不通的,因为您已经扩展了 DelegatingWebMvcConfiguration 并破坏了委托,因为您已经覆盖了 addInterceptors 方法。

该方法的默认实现是

protected void addInterceptors(InterceptorRegistry registry) {
    this.configurers.addInterceptors(registry);
}

咨询所有configurers(它检测到的WebMvcConfigurers)。但是,由于您的覆盖方法,这不再发生,并且正常的扩展机制不再起作用。

【讨论】:

  • 使用这种方法,有没有办法将不同模块的拦截器添加到拦截器列表中的特定位置?我意识到我可以在配置类上添加 @Order 注释,但这不会对各个拦截器的位置进行细粒度控制。
  • 不,实际上也不应该在您的拦截器中存在依赖关系。这将超出让多个模块各自贡献功能的目的。您可以@Order 拦截器并将完整列表/集合注入您的根配置(应该遵守顺序)。但如前所述,恕我直言,排序不应该很重要。
  • 感谢您的确认。大多数情况下我同意,但在某些情况下,我可以看到InterceptorRegistry 上的订单机制很有用。可能类似于在HttpSecurity 上设置过滤器的方式。但这并没有什么大不了的,因为如果需要,可以注入拦截器列表。
猜你喜欢
  • 1970-01-01
  • 2020-01-21
  • 2014-09-16
  • 2016-08-01
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多