Можно ли подключить Spring MVC Interceptor с помощью аннотаций? - PullRequest
27 голосов
/ 08 декабря 2010

Можно ли подключить Spring MVC Interceptor, используя аннотации, и если да, может ли кто-нибудь предоставить мне пример того, как это сделать?

По проводам через аннотации я имею в виду как можно меньше в конфигурации 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" />

Как мало конфигурации вы могли бы избежать там? Я предполагаю, что @Autowired устранит необходимость явного объявления bean-компонента в строке 2, но возможно ли избавиться от строки 1 с помощью аннотации?

Ответы [ 5 ]

73 голосов
/ 20 марта 2013

Наткнулся на этот вопрос при поиске именно этого.Наконец я обнаружил, что он работает в 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());
    }

}
19 голосов
/ 08 декабря 2010

Насколько я знаю, нет никаких способов настроить перехватчики Spring MVC без XML вообще.

Однако, есть некоторые упрощения с пространством имен mvc в последних версиях Spring 3.0.x (не Spring 3.0.0!):

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

См. также:

3 голосов
/ 03 марта 2017

Я реализовал рабочее решение, используя пользовательскую аннотацию @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 - это bean-компонент Spring, который расширяет WebMvcConfigurerAdapter и реализует BeanPostProcessor для сканирования пользовательских аннотаций @Interceptor и регистрации бинов, имеющих эту аннотацию внутри HandlerInterceptor s переопределенный 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;
  }
}

Просто запомните, что ваше весеннее приложение сканирует этот процессор, чтобы оно действительно зарегистрировало ваши @Interceptor s. Что-то вроде:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...
0 голосов
/ 05 мая 2015

как у Markus Kreusch'answers, также может работать вот так

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

}
0 голосов
/ 08 декабря 2010

Я не знаю о Spring-AOP, но если вы используете AspectJ через Spring, вы можете использовать @Aspect, @Pointcut, @Advise и другие ...

есть также хорошая статья о том, как использовать этианнотация с Spring AOP здесь: http://java -x.blogspot.com / 2009/07 / spring-aop-with-aspecj-annotations.html

...