2010-12-08 41 views
24

Est-il possible de câbler un Spring MVC Interceptor à l'aide d'annotations et, dans l'affirmative, quelqu'un pourrait-il me donner un exemple de la façon de procéder?Est-il possible de câbler un intercepteur Spring MVC à l'aide d'annotations?

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

Comment peu de configuration pourriez-vous vous en sortir? J'imagine qu'un @Autowired supprimerait le besoin de déclarer explicitement le bean dans la ligne 2, mais serait-il possible de se débarrasser de la ligne 1 avec une annotation aussi bien?

+0

Pouvez-vous clarifier? Parlez-vous des intercepteurs Spring MVC ou des intercepteurs AOP? Que voulez-vous dire par "câblage" il? – axtavt

+1

Vous pourriez vouloir voir ceci http://karthikg.wordpress.com/2009/10/12/athandlerinterceptor-for-spring-mvc/ – ashishjmeshram

+1

Je sais que cela fait quelques années que vous avez posé cette question, mais @Markus Kreusch a posté la bonne réponse pour la nouvelle version de Spring MVC –

Répondre

17

Pour autant que je sache, il n'y a aucune façon de configurer les intercepteurs Spring MVC sans XML du tout.

Cependant, il y a quelques simplifications avec espace de noms mvc dans les dernières versions de Spring 3.0.x (non Spring 3.0.0!):

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

Voir aussi:

+0

Bonne réponse. Est-il possible de créer un intercepteur qui gérera les exceptions? – fastcodejava

+0

@fastcodejava: Non. Pour gérer les exceptions, vous pouvez utiliser ['HandlerExceptionResolver's] (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc -exceptionhandlers). – axtavt

+0

Que tout le bien dans le monde vienne à votre meilleur monsieur! – Art

0

Je ne sais pas au sujet du printemps-AOP, mais si vous utilisez AspectJ via Spring vous pouvez utiliser @Aspect, @Pointcut, @Advise et plus ...

il y a aussi un bel article sur howto utiliser ces annotations Avec Spring AOP ici: http://java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html

+0

Merci, mais nous n'utilisons pas actuellement AspectJ autant que je sache. Je veux aussi éviter d'utiliser des aspects si je peux. –

72

Nous sommes tombés sur cette question lors de la recherche exactement cela. Enfin, j'ai découvert que cela fonctionne au printemps 3.1 en utilisant @EnableWebMVC en conjonction 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()); 
    } 

} 
+11

Je pense que cela devrait être une réponse acceptée. Une mise en garde, si vous voulez autowire votre intercepteur personnalisé, déclarez-le comme '@ Bean' dans l'une des classes' @ Configuration' et ajoutez le créer par le biais de sa méthode de bean. –

+0

@AlexanderPogrebnyak, Cela peut être la bonne réponse pour les nouvelles versions de Spring, mais je ne suis plus en mesure de tester les annotations Spring et je m'en voudrais de le corriger sans l'avoir personnellement testé. –

+1

se référer à cela aussi: http://stackoverflow.com/questions/21228447/spring-interceptors-excludepathpatterns-function-is-not-working-properly – Nikhil

-2

comme Markus Kreusch'answers, il pourrait aussi travailler 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; 
    } 

} 
+1

Ceci n'a en rien amélioré la réponse de Markus. Votre réponse est en fait plus confuse qu'elle éclaire le problème. – javaauthority

1

Je mis en œuvre une solution de travail en utilisant une annotation personnalisée @Interceptor dans l'esprit d'annotation de printemps @Controller :

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

Cette annotation s Hould être appliqué à HandlerInterceptor types comme ceci:

@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 grain de printemps qui s'étend WebMvcConfigurerAdapter et met en œuvre BeanPostProcessor afin d'analyser la coutume @Interceptor annotations et enregistrer les haricots ayant cette anntation comme HandlerInterceptor s à l'intérieur du addInterceptors: Surcharge de la méthode

@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 d'avoir votre analyse de l'application de printemps pour ce grain de processeur afin d'avoir enregistrer réellement votre @Interceptor s.Quelque chose comme:

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