是否可以使用注释连接 Spring MVC 拦截器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4389224/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:14:40  来源:igfitidea点击:

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

springspring-mvcannotationsinterceptorautowired

提问by James McMahon

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?

是否可以使用注释连接 Spring MVC 拦截器,如果可以的话,有人可以向我提供一个如何这样做的示例吗?

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;

通过注释连接,我指的是在 XML 配置中尽可能少做。例如,在我在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 @Autowiredwould 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?

你能摆脱多少配置?我想这@Autowired会消除在第 2 行中显式声明 bean 的需要,但是是否也可以用注释去掉第 1 行?

采纳答案by axtavt

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

据我所知,没有 XML 根本没有办法配置 Spring MVC 拦截器。

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

但是,mvc在最新版本的 Spring 3.0.x(不是 Spring 3.0.0!)中对命名空间进行了一些简化:

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

See also:

也可以看看:

回答by Markus Kreusch

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.

在搜索这个时偶然发现了这个问题。最后我发现它在 Spring 3.1 中使用 @EnableWebMVC 和 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());
    }

}

回答by Brice Roncace

I implemented a working solution using a custom @Interceptorannotation in the spirit of Spring's @Controllerannotation:

@Interceptor本着 Spring@Controller注释的精神使用自定义注释实现了一个可行的解决方案:

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

This annotation should be applied to HandlerInterceptortypes like so:

此注释应应用于如下HandlerInterceptor类型:

@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 WebMvcConfigurerAdapterand implements BeanPostProcessorin order to scan for the custom @Interceptorannotations and register beans having that anntation as HandlerInterceptors inside the overridden addInterceptorsmethod:

最后,处理器类InterceptorProcessor是一个 Spring bean,它扩展WebMvcConfigurerAdapter和实现BeanPostProcessor以扫描自定义@Interceptor注释并将具有该注释的 bean 注册为HandlerInterceptors 在重写addInterceptors方法中:

@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:

请记住让您的 spring 应用程序扫描此处理器 bean,以便让它实际注册您的@Interceptors。就像是:

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

回答by fasseg

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

我不知道 spring-AOP 但如果你通过 Spring 使用 AspectJ,你可以使用 @Aspect、@Pointcut、@Advise 等等......

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

还有一篇关于如何在 Spring AOP 中使用这些注释的好文章:http: //java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html

回答by u2739238

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

像 Markus Kreusch 的回答一样,它也可以这样工作

@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;
    }

}