30

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

通过注释通过电汇我指的是在 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" />

你可以在那里逃脱多少配置?我想 an@Autowired会消除在第 2 行显式声明 bean 的需要,但是是否有可能用注释摆脱第 1 行?

4

5 回答 5

80

在搜索这个问题时偶然发现了这个问题。最后我发现它可以在 Spring 3.1 中使用 @EnableWebMVC 和 WebMvcConfigurerAdapter。

简单示例:

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

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

}
于 2013-03-20T19:01:11.787 回答
19

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

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

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

也可以看看:

于 2010-12-08T16:15:34.463 回答
7

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

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

此注释应应用于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;
  }
}

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

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

只要记住让你的spring应用程序扫描这个处理器bean,以便让它真正注册你@Interceptor的s。就像是:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...
于 2017-03-03T16:41:50.713 回答
0

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

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

于 2010-12-08T15:49:05.710 回答
-2

就像 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;
    }

}
于 2015-05-05T01:45:28.227 回答