2

我已经将 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 只实例化了一次。请帮忙。

提前致谢。

4

2 回答 2

3

万一有人偶然发现这篇文章和此处发布的解决方案认为它会修复重复的请求,请首先检查是否是您的浏览器/休息客户端发出了额外的调用。

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

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

详细说明之前的答案:

您可以在同一个上下文文件中定义组件扫描和 mvc 以保持简单。

应用上下文.xml:

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

或者将它们分开如下:

应用上下文.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 />

...
于 2015-05-23T02:58:46.623 回答
0

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

使用扫描除@ControllerapplicationContext.xml 之外的所有组件<context:exclude-filter..@Controller同样,仅使用 servlet-context.xml扫描<context:include-filter..

于 2013-08-07T23:13:43.870 回答