web-dev-qa-db-fra.com

Mvc: configuration de l'intercepteur au printemps

J'ai un genre de problème. Je dois appeler chaque méthode postHandle de requête dans cet intercepteur:

public class DiMenuInterceptor extends HandlerInterceptorAdapter {

   @Autowired
   private IDiCategoryService categoryService;


   @Override
   public void postHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler,
        ModelAndView modelAndView) throws Exception {

       modelAndView.addObject("category", categoryService.getCategoryInTree());
   }
}

donc je mets dans la configuration de servlet ces lignes et tout fonctionne bien.

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:interceptors-ref="menuInterceptor" />

<bean id="menuInterceptor" class="cz.cosi.DiMenuInterceptor" />

Mais maintenant je dois changer de configuration et utiliser <mvc:interceptors>

Avec cette configuration, j'obtiens une série d'exceptions de pointeur null sur modelAndView dans la méthode postHandle, car la méthode postHandle est appelée plusieurs fois par demande. 

 <mvc:interceptors>
    <bean class="cz.cosi.DiMenuInterceptor" />
 </mvc:interceptors>

Avec cette configuration, cela fonctionne, mais uniquement pour request serverAdress/rien. Pour request serverAdress/tout/quelque chose, postHandle n'est pas appelé.

<mvc:interceptors>
   <mvc:interceptor>
     <mvc:mapping path="/*" />
     <bean class="cz.cosi.DiMenuInterceptor" />
   </mvc:interceptor>
</mvc:interceptors>

partie de la configuration de servlet

<mvc:annotation-driven />

<bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
    <property name="defaultEncoding" value="UTF-8" />       

</bean>

<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/" />

<mvc:interceptors>
    <bean class="cz.cosi.DiMenuInterceptor" />
</mvc:interceptors>

<tx:jta-transaction-manager />

<tx:annotation-driven />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

Il semble que le problème puisse en quelque sorte être lié aux ressources, car avec les exceptions ne sont pas correctement chargées les images, les styles et le javascript. Sans MVC: les ressources fonctionnent correctement, mais ce n'est pas une solution. 

Ma question est de savoir comment configurer correctement DiMenuInterceptor avec <mvc:interceptors>. Merci beaucoup pour les conseils.

empiler: 

2011-04-14 09:56:02,487 [http-8080-3] DEBUG (FilterChainProxy.Java:195) ? Converted URL to lowercase, from: '/images/core/users/super_admin.png'; to: '/images/core/users/super_admin.png'
2011-04-14 09:56:02,533 [http-8080-3] DEBUG (FilterChainProxy.Java:202) ? Candidate is: '/images/core/users/super_admin.png'; pattern is /images/**; matched=true
2011-04-14 09:56:02,533 [http-8080-3] DEBUG (FilterChainProxy.Java:158) ? /images/core/users/super_admin.png has an empty filter list
14.4.2011 9:56:02 org.Apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet spring threw exception
Java.lang.NullPointerException
    at cz.cosi.DiMenuInterceptor.postHandle(DiMenuInterceptor.Java:41)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:801)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:644)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:549)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:290)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.Java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:76)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:235)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:163)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:235)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:233)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:191)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:127)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:102)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:109)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:298)
    at org.Apache.coyote.http11.Http11Processor.process(Http11Processor.Java:859)
    at org.Apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.Java:588)
    at org.Apache.Tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.Java:489)
    at Java.lang.Thread.run(Thread.Java:595)

J'ai peut-être trouvé une solution, mais ce n'est certainement pas la meilleure. Pour l'instant, il semble que cela fonctionne.

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*" />
        <bean class="cz.cosi.DiMenuInterceptor" />
    </mvc:interceptor>
    <mvc:interceptor>
         <mvc:mapping path="/search/**" />
        <bean class="cz.cosi.DiMenuInterceptor" />
    </mvc:interceptor>

    <mvc:interceptor>
         <mvc:mapping path="/context/**" />
        <bean class="cz.cosi.DiMenuInterceptor" />
    </mvc:interceptor>
    <mvc:interceptor>
          <mvc:mapping path="/member/**" />
        <bean class="cz.cosi.DiMenuInterceptor" />
    </mvc:interceptor>

</mvc:interceptors>
13
rinzler

Vous devez spécifier que votre chemin comprend des sous-chemins: /**" au lieu de /*.

<mvc:interceptors>
   <mvc:interceptor>
     <mvc:mapping path="/**" />
     <bean class="cz.cosi.DiMenuInterceptor" />
   </mvc:interceptor>
</mvc:interceptors>

@see Exemple in Spring Reference, Chapitre 15.12.2 mvc: interceptors

15
Ralph

Le problème est que les intercepteurs sont appelés lorsque des ressources sont demandées.

Ceci post explique comment empêcher les intercepteurs d'être appelés à l'aide de la configuration xml. Dans la réponse acceptée, je ne suis pas un grand fan de compter sur la composition sémantique des chemins (c'est-à-dire utiliser .html ou avoir une page dans le chemin). Désormais, tous les développeurs de l'équipe doivent en être conscients lors de la création de contrôleurs.

Je ne suis pas non plus un fan de la configuration du haricot prolixe, j'ai donc décidé d'ajouter le code suivant à l'intercepteur:

if (ClassUtils.isAssignableValue(ResourceHttpRequestHandler.class, handler)) {
    return;
}

// do interceptor logic here...
1
Craig Swing

J'ai eu la même question aussi. Configuration initiale:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*"/>
        <bean class="cn.mmd.micro.common.TokenInterceptor">
            <property name="excludeUrls">
                <list>
                    <value>/app/token</value>
                </list>
            </property>
        </bean>
    </mvc:interceptor>
</mvc:interceptors>

J'ai changé la valeur "mvc: mapping", et cela a fonctionné. Ma nouvelle configuration est la suivante:

<mvc:interceptors>
<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="cn.mmd.micro.common.TokenInterceptor">
        <property name="excludeUrls">
            <list>
                <value>/app/token</value>
            </list>
        </property>
    </bean>
</mvc:interceptor>

0
Richard Xue

J'ai eu un problème très similaire, mais l'accès aux polices pour Bootstrap 3. Interceptors a bloqué des ressources telles que 'glyphicons-halflings-regular.woff' ou 'glyphicons-halflings-regular.ttf' et elles n'étaient pas visibles en première page. Je résous mon problème de la manière suivante. La définition de mon intercepteur est la suivante: 

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="cz.cosi.DiMenuInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

Et ma classe DiMenuInterceptor:

public class DiMenuInterceptor extends HandlerInterceptorAdapter {

private List<String> nonAuthPaths;

public DiMenuInterceptor() {
    nonAuthPaths = new ArrayList<String>();
    nonAuthPaths.add("/login");
    nonAuthPaths.add("/resources/vendor/fonts/glyphicons-halflings-regular.woff");
    nonAuthPaths.add("/resources/vendor/fonts/glyphicons-halflings-regular.ttf");
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    Object user = request.getSession().getAttribute(SessionManagement.USER_KEY);

    if (user == null && !nonAuthPaths.contains(request.getServletPath())) {
            response.sendRedirect(request.getContextPath() + "/login");
        }
        return false;
    } else {
        //ect ...
        return true;
    }
}
0
mariusz117