我使用基于java的Spring Mvc配置。
我在WebApplicationInitializer实现中注册了Spring调度程序servlet。 加载Spring ApplicationContext配置文件。 Spring概要管理的逻辑在ApplicationContextInitializer实现中实现。它工作得很好。
以下是原始文件的完整示例: 的 WebApplicationInitializer
public class SpringMvcExampleWebApplicationInitializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
}
private void registerDispatcherServlet(final ServletContext servletContext) {
WebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext);
dispatcherServlet.setContextInitializers(new SpringMvcExampleProfilesInitializer());
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private WebApplicationContext createContext(final Class<?>... annotatedClasses) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(annotatedClasses);
return context;
}
private void registerHiddenHttpMethodFilter(ServletContext servletContext) {
FilterRegistration.Dynamic registration = servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
registration.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),
false, DISPATCHER_SERVLET_NAME);
}
}
SpringMvcExampleProfilesInitializer
public class SpringMvcExampleProfilesInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext ctx) {
ConfigurableEnvironment environment = ctx.getEnvironment();
List<String> profiles = new ArrayList<String>(getProfiles());
if( profiles == null || profiles.isEmpty() )
{
throw new IllegalArgumentException("Profiles have not been configured");
}
environment.setActiveProfiles(profiles.toArray( new String[0]));
}
//TODO add logic
private Collection<String> getProfiles() {
return Lists.newArrayList("file_based", "test_data");
}
}
InfrastructureContextConfiguration
@Configuration
@ComponentScan(basePackages = {"com.savdev.springmvcexample.repository", "com.savdev.springmvcexample.config"})
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.savdev.springmvcexample.repository"})
public class InfrastructureContextConfiguration {
@Configuration
@Profile(value = "file_based")
@PropertySource("classpath:/db/config/file_based.properties")
public static class FileBasedConfiguration {
@Inject
private Environment environment;
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new org.apache.commons.dbcp.BasicDataSource();
dataSource.setDriverClassName(environment.getProperty("jdbc.driver"));
dataSource.setUrl(environment.getProperty("jdbc.url"));
dataSource.setUsername(environment.getProperty("jdbc.username"));
dataSource.setPassword(environment.getProperty("jdbc.password"));
return dataSource;
}
}
@Bean
public SpringLiquibase liquibase(DataSource dataSource) {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource);
liquibase.setChangeLog("classpath:/db/liquibase/changelog/db.changelog-master.xml");
liquibase.setDropFirst(true);
return liquibase;
}
然后我将Spring Security上下文配置添加到应用程序中。要使用它,必须加载DelegatingFilterProxy
。我已经更新了配置:
添加了新方法,并在onStartup
:
private void registerSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
BeanIds.SPRING_SECURITY_FILTER_CHAIN,
new DelegatingFilterProxy());
springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*");
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
...
registerDispatcherServlet(servletContext);
...
registerSpringSecurityFilterChain(servletContext);
}
现在,当我尝试请求任何网址时,我收到错误:
message No WebApplicationContext found: no ContextLoaderListener registered?
description The server encountered an internal error that prevented it from fulfilling this request.
exception
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:251)
好的,我添加了以下内容:
private static final Class<?>[] configurationClasses = new Class<?>[]{
WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class};
...
private void registerListener(ServletContext servletContext) {
WebApplicationContext rootContext = createContext(configurationClasses);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
从以下方式调用它:
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerListener(servletContext);
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
registerSpringSecurityFilterChain(servletContext);
}
错误已经消失。
但是现在没有加载所有依赖于Spring配置文件的bean。添加ContextLoaderListener
已经破坏了SpringMvcExampleProfilesInitializer
逻辑。
No qualifying bean of type [javax.sql.DataSource] found for dependency
我该怎么做才能解决它?有什么想法吗?
以下是完整更新的网络初始化程序类:
public class SpringMvcExampleWebApplicationInitializer implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final Class<?>[] configurationClasses = new Class<?>[]{
WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class};
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerListener(servletContext);
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
registerSpringSecurityFilterChain(servletContext);
}
private void registerSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter(
BeanIds.SPRING_SECURITY_FILTER_CHAIN,
new DelegatingFilterProxy());
springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*");
}
private void registerDispatcherServlet(final ServletContext servletContext) {
WebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class, InfrastructureContextConfiguration.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext);
dispatcherServlet.setContextInitializers(new SpringMvcExampleProfilesInitializer());
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private WebApplicationContext createContext(final Class<?>... annotatedClasses) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(annotatedClasses);
// context.refresh();
return context;
}
private void registerListener(ServletContext servletContext) {
WebApplicationContext rootContext = createContext(configurationClasses);
servletContext.addListener(new ContextLoaderListener(rootContext));
// servletContext.addListener(new RequestContextListener());
}
private void registerHiddenHttpMethodFilter(ServletContext servletContext) {
FilterRegistration.Dynamic registration = servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
registration.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),
false, DISPATCHER_SERVLET_NAME);
}
}
答案 0 :(得分:0)
正如M.Deinum建议我将配置文件的初始值设置为ServletContext
,而不是将其设置为DispatcherServlet
。这是更新的配置:
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
configureServletContext( servletContext );
registerListener(servletContext);
registerDispatcherServlet(servletContext);
...
}
private void configureServletContext(ServletContext servletContext) {
String initializerClasses = servletContext.getInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM);
String profilesInitClassName = SpringMvcExampleProfilesInitializer.class.getName();
if (StringUtils.hasText(initializerClasses)) {
initializerClasses += " " + profilesInitClassName;
}
else {
initializerClasses = profilesInitClassName;
}
servletContext.setInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, initializerClasses);
}