quoi - tutoriel spring 5




Est-il possible de raccorder un intercepteur Spring MVC à l'aide d'annotations? (4)

Est-il possible de connecter un intercepteur Spring MVC à l'aide d'annotations et si oui, quelqu'un pourrait-il me donner un exemple de la manière de procéder?

Par fil via annotation, je parle de faire aussi peu que possible dans la configuration XML. Par exemple, dans ce fichier de configuration que j'ai trouvé à 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" />

Avec quelle petite configuration pouvez-vous vous en sortir? J'imagine qu'un @Autowired supprime la nécessité de déclarer explicitement le bean dans la ligne 2, mais serait-il possible de se débarrasser également de la ligne 1 avec une annotation?


Autant que je sache, il n'y a aucun moyen de configurer les intercepteurs Spring MVC sans XML.

Cependant, il existe quelques simplifications avec l'espace de noms mvc dans les dernières versions de Spring 3.0.x (pas Spring 3.0.0!):

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

Voir également:


J'ai implémenté une solution de travail en utilisant une annotation @Interceptor personnalisée dans l'esprit de l'annotation @Controller de Spring:

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

Cette annotation doit être appliquée aux types HandlerInterceptor comme 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;
  }
}

Enfin, la classe de processeur, InterceptorProcessor , est un bean Spring qui étend WebMvcConfigurerAdapter et implémente BeanPostProcessor afin de rechercher les annotations @Interceptor personnalisées et d'enregistrer les beans ayant cette annotation en tant que HandlerInterceptor dans la méthode 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;
  }
}

Rappelez-vous juste de faire analyser votre application printanière pour ce bean processeur afin de pouvoir enregistrer vos @Interceptor . Quelque chose comme:

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

Trébuché sur cette question en cherchant exactement cela. Enfin, j'ai découvert que cela fonctionne dans Spring 3.1 en utilisant @EnableWebMVC conjointement avec WebMvcConfigurerAdapter.

Exemple simple:

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

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

}

comme Markus Kreusch'answers, ça pourrait aussi fonctionner comme ça

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

}




autowired