Proper mvc:interceptor configuration in Spring

别来无恙 提交于 2019-11-26 23:09:08

问题


I have kind of a problem. I need to call on each request postHandle method in this interceptor:

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());
   }
}

so I put into servlet configuration this lines and everything work fine.

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

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

But now I have to change configuration and use <mvc:interceptors>

With this configuration, I'm getting series of null pointer exception on modelAndView in the postHandle method because the postHandle method is called more than once per request.

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

With this configuration, it is working, but only for request serverAdress/anything. For request serverAdress/anything/something is postHandle not called.

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

part of servlet configuration

<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>

It seems, that the problem might somehow relate to resources, because with exceptions are not properly loaded images, styles, and javascript. Without mvc:resources its working correctly, but this is not a solution.

My question is, how to properly configure DiMenuInterceptor with <mvc:interceptors>. Thanks very much for the advices.

stack:

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)

Maybe I found a solution, but it is definitely not the best. For now it seems, that is working.

<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>

回答1:


Your need to specify that your path includes subpaths: /**" instead /*.

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

@see Excample in Spring Reference, Chapter 15.12.2 mvc:interceptors




回答2:


The problem is that the interceptors are called when resources are requested.

This post talks about how to prevent the interceptors from being called using the xml configuration. In the accepted answer, I am not a big fan of relying on the semantic makeup of the paths (ie using .html or having page in the path). Now all developers on the team have to be aware of this when creating controllers.

I also am not a fan of the verbose bean configuration, so I have decided to add the following code to the interceptor:

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

// do interceptor logic here...



回答3:


I had very simillar problem but with accessing to fonts for Bootstrap 3. Interceptors blocked fonts resources like 'glyphicons-halflings-regular.woff' or 'glyphicons-halflings-regular.ttf' and they were not visible in front page. I resolve my problem in following way. The definition of my interceptor look like below:

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

And my DiMenuInterceptor class:

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



回答4:


I had the same question too. Initial configuration:

<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>

I changed the value "mvc:mapping", and it worked. My new configuration is as follows:

<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>



来源:https://stackoverflow.com/questions/5656124/proper-mvcinterceptor-configuration-in-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!