Spring mvc SpringMVC在集成测试中混合使用xml和java@ContextConfiguration
我正在尝试使用XML配置和Spring mvc SpringMVC在集成测试中混合使用xml和java@ContextConfiguration,spring-mvc,spring-security,spring-test,spring-test-mvc,spring-mvc-test,Spring Mvc,Spring Security,Spring Test,Spring Test Mvc,Spring Mvc Test,我正在尝试使用XML配置和@Configuration注释类的组合来配置Spring MVC集成测试 @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @TestPropertySource({"/spring-security.properties", "/rabbitmq-default.properties", "/mongodb-de
@Configuration
注释类的组合来配置Spring MVC集成测试
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@TestPropertySource({"/spring-security.properties",
"/rabbitmq-default.properties",
"/mongodb-default.properties",
"/webapp-override.properties"})
@ContextHierarchy({
@ContextConfiguration("classpath:**/security-config.xml"),
@ContextConfiguration(classes = RootConfig.class),
@ContextConfiguration(classes = SpringMvcConfig.class)
})
public class BaseConfiguredMvcIntegrationTest {
}
java配置已正确初始化。问题是,尽管在初始化期间找到并解析了“**/security config.xml”
文件。。。在那里定义的所有spring安全bean从未在WebApplicationContext
中注册
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
所以我的问题是如何在SpringMVC集成测试中同时利用基于XML和基于注释的配置
我可以将spring安全配置更改为基于java/注释的配置。。。我宁愿不这样做。我发现使用spring安全名称空间比使用java配置更具可读性和简洁性
另外,请注意,这种XML/Java组合配置在非测试环境中工作得非常好
- Spring v4.1.6
- Spring Security v4.0.1
package com.gggdw.web.config;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.DispatcherServlet;
@Configuration
public class GGGWebInitializer implements WebApplicationInitializer {
public static final String SERVLET_NAME = "ggg";
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootConfig.class);
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(SpringMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(SERVLET_NAME, new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
//Spring security config
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
"securityFilter", new DelegatingFilterProxy("springSecurityFilterChain"));
springSecurityFilterChain.addMappingForServletNames(null, false, SERVLET_NAME);
//springSecurityFilterChain.setAsyncSupported(true);
servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
}
}
RootConfig.class
@Configuration
@Import({WebPropertiesConfig.class, // loads all properties files on class path from resources folder
MongoConfig.class // init mongodb connection
})
@ImportResource({"classpath:**/security-config.xml"}) // spring security xml config (java config not as readable)
public class RootConfig {
}
安全配置.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:property-placeholder location="classpath:spring-security.properties" /> -->
<security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>
<bean id="permissionEvaluator"
class="com.my.local.package.security.GenericPermissionEvaluator">
</bean>
<!-- Configure Spring Security -->
<security:http auto-config="true" use-expressions="true" >
<security:form-login login-page="${spring.security.login-page}"
login-processing-url="${spring.security.login-processing-url}"
default-target-url="${spring.security.default-target-url}"
authentication-failure-url="${spring.security.authentication-failure-url}"
username-parameter="${spring.security.username-parameter}"
password-parameter="${spring.security.password-parameter}"
/>
<security:logout logout-url="${spring.security.logout-url}"
logout-success-url="${spring.security.logout-success-url}" />
<security:intercept-url pattern="/**" requires-channel="https" />
<security:intercept-url pattern="/s/**" access="isAuthenticated()" requires-channel="https" />
<security:custom-filter ref="log4JMDCFilter" after="SECURITY_CONTEXT_FILTER"/>
<security:access-denied-handler error-page="${spring.security.access-denied-handler-error-page}" />
<!-- <security:session-management invalid-session-url="${spring.security.invalid-session-url}"/>
2 types of invalid session, brand new user and a timeout of a previous logged in user
both need to be handled differently -->
</security:http>
<bean id="customUserDetailsService" class="com.my.local.package.CustomUserDetailsService" depends-on="userRepository"/>
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<!-- log4j filter to add userName and ipAddress into logging on a per request/thread basis -->
<bean id="log4JMDCFilter" class="com.my.local.package.filter.Log4JMDCFilter"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
更新:经过进一步考虑并根据您的最新反馈,您遇到的行为可能是Spring Framework 4.1.4中引入的错误导致的(有关详细信息,请参阅) 尝试降级到SpringFramework 4.1.3,如果您仍然遇到不希望出现的行为,请告诉我
注意,这种XML/Java组合配置在非测试环境中工作得非常好 怎么会这样 您是否真的在生产的层次结构中加载了三(3)个上下文 我对此表示怀疑。相反,我假设您以某种方式从
“classpath:*/security config.xml”
和RootConfig.class
加载单个根WebApplicationContext
因此,最重要的问题是:如何在生产环境中配置根WebApplicationContext
一旦您回答了这个问题,我可以告诉您如何在测试配置中实现相同的功能。;)
问候,
Sam(SpringTestContext框架的作者)更新:经过进一步考虑并根据您的最新反馈,您所经历的行为可能是SpringFramework 4.1.4中引入的错误导致的(有关详细信息,请参阅) 尝试降级到SpringFramework 4.1.3,如果您仍然遇到不希望出现的行为,请告诉我
注意,这种XML/Java组合配置在非测试环境中工作得非常好 怎么会这样 您是否真的在生产的层次结构中加载了三(3)个上下文 我对此表示怀疑。相反,我假设您以某种方式从
“classpath:*/security config.xml”
和RootConfig.class
加载单个根WebApplicationContext
因此,最重要的问题是:如何在生产环境中配置根WebApplicationContext
一旦您回答了这个问题,我可以告诉您如何在测试配置中实现相同的功能。;)
问候,
Sam(SpringTestContext框架的作者)请注意以下注意事项: 请注意,“classpath*:”与Ant样式模式结合使用时,在模式启动之前,只能在至少一个根目录下可靠地工作,除非实际的目标文件驻留在文件系统中。这意味着像“classpath*:*.xml”这样的模式不会从jar文件的根检索文件,而是只从扩展目录的根检索文件。这源于JDK的ClassLoader.getResources()方法中的一个限制,该方法只返回传入的空字符串(指示要搜索的潜在根)的文件系统位置
请注意以下注意事项: 请注意,“classpath*:”与Ant样式模式结合使用时,在模式启动之前,只能在至少一个根目录下可靠地工作,除非实际的目标文件驻留在文件系统中。这意味着像“classpath*:*.xml”这样的模式不会从jar文件的根检索文件,而是只从扩展目录的根检索文件。这源于JDK的ClassLoader.getResources()方法中的一个限制,该方法只返回传入的空字符串(指示要搜索的潜在根)的文件系统位置
我开始了迁移到spring security java配置的痛苦过程。。。6小时内:(我开始了迁移到spring security java配置的痛苦过程…6小时内:(我开始了迁移到spring security java配置的痛苦过程…6小时内:(不,我没有3。**/security-config.xml实际上在RootConfig.class中,我只是将其取出以澄清问题。我正在扩展一个WebApplicationInitializer,并将RootConfig.class插入rootContext,将SpringMvcConfig.class插入servlet上下文。我将使用此配置更新原始帖子。这是servlet 3.1+,因此没有使用web.xml文件。扩展*=实现WebApplicationInitializedDowngrading到4.1.3并没有解决问题。如果bean在xml中,它们仍然没有加载到上下文中。我已经迁移到基于注释的安全配置中…在迁移过程中,我遇到了另一个问题/错误…这是当我降级到4.1.3时,trangely Though得到了修复哈哈。你能在你的终端复制这个来验证它是否是一个bug吗?请告诉我们XML配置是如何在
RootConfig.class
中的。不,我没有3。**/security-config.XML确实在RootConfig.class中。我刚刚取出它来澄清问题。我正在扩展一个WebApplicationInitializer并插入RootConfig.class