Spring Controller方法执行两次

时间:2013-08-07 22:26:50

标签: spring spring-mvc spring-security

我已经将Spring Security与Spring MVC集成并看到了奇怪的行为。 Controller中的每个方法都针对同一请求执行两次。我用谷歌搜索了一下,但没有多大帮助。我能找到的最接近的是http://forum.springsource.org/archive/index.php/t-83158.html我没有成功地尝试了这些建议。

这是我的web.xml:

<servlet>
     <servlet-name>appServlet</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>0</load-on-startup>
</servlet>     
<servlet-mapping>
     <servlet-name>appServlet</servlet-name>
     <url-pattern>/</url-pattern>
</servlet-mapping>

<listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
         /WEB-INF/spring/appServlet/security-app-context.xml            
         /WEB-INF/application-context.xml
    </param-value>
</context-param>

以下是applicationcontext.xml的相关部分:

 <context:component-scan base-package="com.*" />
  <context:spring-configured/>

 <mvc:annotation-driven />

 <context:property-placeholder location="classpath:/conf/myConfig.properties"   />

<mvc:resources mapping="/resources/**" location="/resources/" />

servlet-context.xml只有InternalResourceViewResolver的映射

security-context.xml如下:

<http pattern="/resources/**" security="none"/>

    <http auto-config="false" create-session="stateless" entry-point-ref="loginUrlAuthenticationEntryPoint" >
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/j_spring_security_check" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/accessdenied" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/logout" access="ROLE_USER"/>

    <custom-filter before="SECURITY_CONTEXT_FILTER" ref="cookieSecurityContextFilter" />
    <custom-filter position="LOGOUT_FILTER" ref="logoutfilter" />          
    <custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />
    <custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="customExceptionFilter" />
    </http>


    <beans:bean id="logoutfilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
     <beans:constructor-arg value="/"/>
     <beans:constructor-arg ref="customLogouthandler"/>
    </beans:bean>

然后进一步映射过滤器。 我在配置中做错了什么可能导致控制器被调用两次。我检查了日志,并且bean只实例化了一次。请帮忙。

提前致谢。

2 个答案:

答案 0 :(得分:3)

万一有人在这篇帖子上发现错误并且此处发布的解决方案认为它会修复重复请求,请先检查是否是您的浏览器/其他客户端进行额外通话。

在看到第一个建议的解决方案之后,我浪费了很多时间来尝试配置应用和servlet上下文&#34;直到我发现某些浏览器(Chrome)上的其他客户端为&#34创建了额外的请求; GET请求图像资源&#34;。 Curl只显示了一个方法执行。

但是,我同意将控制器特定bean及其所需的Spring bean分隔为servlet-context并将所有常见bean保存在app-context中是一种很好的做法。如果您的web.xml中有多个Spring调度程序servlet,这一点尤其重要。

阐述前一个答案:

您可以在同一个上下文文件中定义component-scan和mvc,以保持简单。

APP-context.xml中:

 <context:component-scan base-package="..." />
 <mvc:annotation-driven />
 ...

或者将它们分开如下:

APP-context.xml中:

 <context:component-scan base-package="....">
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>
...

servlet的context.xml中:

<context:component-scan base-package="...">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
    <context:include-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>

<mvc:annotation-driven />

...

答案 1 :(得分:0)

我会尝试将<mvc:..元素移动到servlet-context.xml,也许在applicationContext.xml上使用它会导致你有重复的调度程序servlet(尽管bean只创建一次)

使用@Controller扫描applicationContext.xml上除<context:exclude-filter..以外的所有组件。同样,使用@Controller

仅在servlet-context.xml上扫描<context:include-filter..