it-swarm.com.de

Kann ein Spring MVC Interceptor mit Anmerkungen verbunden werden?

Ist es möglich, einen Spring MVC Interceptor mit Anmerkungen zu verdrahten, und wenn ja, könnte mir jemand ein Beispiel geben, wie dies möglich ist?

Mit "Wire via Annotation" beziehe ich mich darauf, so wenig wie möglich in der XML-Konfiguration zu tun. Zum Beispiel in dieser Konfigurationsdatei fand ich unter 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" />

Mit wie wenig Konfiguration können Sie da durchkommen? Ich stelle mir vor, ein @Autowired würde die Notwendigkeit beseitigen, die Bean explizit in Zeile 2 zu deklarieren, aber wäre es auch möglich, Zeile 1 mit einer Annotation zu entfernen?

27
James McMahon

Soweit ich weiß, gibt es keine Möglichkeiten, Spring MVC-Interceptors ohne XML zu konfigurieren.

In den neuesten Versionen von Spring 3.0.x (nicht Spring 3.0.0!) Gibt es jedoch einige Vereinfachungen mit dem Namespace mvc:

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

Siehe auch:

19
axtavt

Bei dieser Suche bin ich auf diese Frage gestoßen. Schließlich habe ich herausgefunden, dass es in Spring 3.1 mit @EnableWebMVC in Verbindung mit dem WebMvcConfigurerAdapter funktioniert.

Einfaches Beispiel:

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

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

}
73
Markus Kreusch

Ich habe eine funktionierende Lösung mit einer benutzerdefinierten @Interceptor-Annotation im Sinne von Spring's @Controller-Annotation implementiert:

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

Diese Annotation sollte wie folgt auf HandlerInterceptor-Typen angewendet werden:

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

Schließlich ist die Prozessorklasse InterceptorProcessor eine Spring-Bean, die WebMvcConfigurerAdapter erweitert und BeanPostProcessor implementiert, um nach benutzerdefinierten @Interceptor-Annotationen zu suchen und Beans mit dieser Bezeichnung als HandlerInterceptors in der überschriebenen addInterceptors-Methode zu registrieren:

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

Denken Sie daran, Ihre Frühjahrsanwendung für dieses Prozessor-Bean zu scannen, damit es Ihren @Interceptors tatsächlich registriert. So etwas wie:

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

Ich weiß nicht über Spring-AOP Bescheid, aber wenn Sie AspectJ über Spring verwenden, können Sie @Aspect, @Pointcut, @Advise und mehr verwenden ...

es gibt auch einen schönen Artikel zur Verwendung dieser Anmerkungen mit Spring AOP hier: http://Java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html

0
fasseg