【问题标题】:Proper mvc:interceptor configuration in SpringSpring 中正确的 mvc:interceptor 配置
【发布时间】:2011-08-05 02:17:20
【问题描述】:

我有一个问题。我需要在这个拦截器中调用每个请求的 postHandle 方法:

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

所以我将这些行放入 servlet 配置中,一切正常。

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

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

但现在我必须更改配置并使用&lt;mvc:interceptors&gt;

使用此配置,我在 postHandle 方法中的 modelAndView 上收到一系列空指针异常,因为 postHandle 方法在每个请求中被多次调用。

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

使用此配置,它可以工作,但仅适用于请求 serverAdress/anything。对于请求 serverAdress/anything/something 未调用 postHandle。

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

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>

看来,问题可能与资源有关,因为有异常没有正确加载图像、样式和 javascript。如果没有 mvc:resources 它可以正常工作,但这不是解决方案。

我的问题是,如何使用&lt;mvc:interceptors&gt; 正确配置 DiMenuInterceptor。非常感谢您的建议。

堆栈:

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)

也许我找到了解决方案,但绝对不是最好的。目前看来,这是可行的。

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

【问题讨论】:

  • 你应该发布空指针。
  • 您的解决方案有效,而“/**”无效? -- 看起来像一个错误。
  • 没错。只有“/**”对我不起作用。

标签: spring interceptor


【解决方案1】:

您需要指定您的路径包含子路径:/**" 而不是 /*

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

@参见 Spring 参考中的示例,Chapter 15.12.2 mvc:interceptors

【讨论】:

  • 我也测试过这个版本的配置,但我得到的空指针与当前较短的版本相同。 &lt;mvc:interceptors&gt; &lt;bean class="cz.cosi.DiMenuInterceptor" /&gt; &lt;/mvc:interceptors&gt;
  • @rinzler:我正在解决这个声明:使用此配置它正在工作,但仅适用于请求 serverAdress/anything。对于请求 serverAdress/anything/something 是 postHandle 未调用。“
  • 是的,我知道。使用/* 是否有效,因为 postHandle 只被调用一次。第一次打电话没问题。但是对于第二次和进一步的调用,会抛出空指针异常。 /** 是 postHandle 又被调用了很多次。
【解决方案2】:

我也有同样的问题。初始配置:

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

我更改了值“mvc:mapping”,它起作用了。我的新配置如下:

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

【讨论】:

    【解决方案3】:

    我遇到了非常类似的问题,但是在访问 Bootstrap 3 的字体时。拦截器阻止了诸如“glyphicons-halflings-regular.woff”或“glyphicons-halflings-regular.ttf”之类的字体资源,并且它们在首页中不可见。 我通过以下方式解决我的问题。 我的拦截器的定义如下所示:

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

    还有我的 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;
        }
    }
    

    【讨论】:

      【解决方案4】:

      问题是在请求资源时会调用拦截器。

      这个post 讨论了如何防止拦截器被使用 xml 配置调用。在公认的答案中,我不太喜欢依赖路径的语义构成(即使用 .html 或在路径中有页面)。现在,团队中的所有开发人员在创建控制器时都必须意识到这一点。

      我也不喜欢详细的 bean 配置,所以我决定在拦截器中添加以下代码:

      if (ClassUtils.isAssignableValue(ResourceHttpRequestHandler.class, handler)) {
          return;
      }
      
      // do interceptor logic here...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-02
        • 1970-01-01
        • 2020-12-03
        • 2016-03-22
        • 1970-01-01
        • 2021-02-21
        • 1970-01-01
        • 2012-07-17
        相关资源
        最近更新 更多