Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Spring Mvc WebApplicationInitializer、ApplicationContextInitializer和ContextLoaderListener_Java_Spring_Spring Mvc_Configuration - Fatal编程技术网

Java 使用Spring Mvc WebApplicationInitializer、ApplicationContextInitializer和ContextLoaderListener

Java 使用Spring Mvc WebApplicationInitializer、ApplicationContextInitializer和ContextLoaderListener,java,spring,spring-mvc,configuration,Java,Spring,Spring Mvc,Configuration,我使用基于java的SpringMVC配置 我在WebApplicationInitializer实现中注册了Spring dispatcher servlet。 加载Spring应用程序上下文配置文件。Spring概要文件管理的逻辑在ApplicationContextInitializer实现中实现。而且效果很好 以下是原始文件的完整示例: WebApplicationInitializer public class SpringMvcExampleWebApplicationInitial

我使用基于java的SpringMVC配置

我在WebApplicationInitializer实现中注册了Spring dispatcher servlet。 加载Spring应用程序上下文配置文件。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);
    }
}
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");
    }
}
然后,我将Spring安全上下文配置添加到应用程序中。要使用它,必须加载
DelegatingFilterProxy
。我\n已更新配置:

@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);
}
添加了新方法并在启动时调用它:

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);
}
现在,当我尝试请求任何url时,我得到了错误:

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));
}
错误已经消失了

但是现在没有加载所有依赖于Spring概要文件的bean。添加
ContextLoaderListener
已破坏
SpringMvcExampleProfilesInitializer
逻辑

No qualifying bean of type [javax.sql.DataSource] found for dependency
我能做些什么来解决它?有什么想法吗

以下是完整更新的web初始值设定项类:

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);
    }
}
公共类SpringMvcExampleWebApplicationInitializer实现WebApplicationInitializer{
私有静态最终字符串DISPATCHER\u SERVLET\u NAME=“DISPATCHER”;
私有静态最终类[]配置类=新类[]{
WebMvcContextConfiguration.class,InfrastructureContextConfiguration.class};
@凌驾
启动时公共void(ServletContext ServletContext)引发ServletException{
registerListener(servletContext);
registerDispatcherServlet(servletContext);
registerHiddenHttpMethodFilter(servletContext);
registerSpringSecurityFilterChain(servletContext);
}
私有无效注册表SpringSecurityFilterChain(ServletContext ServletContext){
FilterRegistration.Dynamic springSecurityFilterChain=servletContext.addFilter(
BeanIds.SPRING\u SECURITY\u FILTER\u CHAIN,
新的DelegatingFilterProxy());
springSecurityFilterChain.addMappingForUrlPatterns(null,false,“/*”);
}
私有无效注册表DispatcherServlet(最终ServletContext ServletContext){
WebApplicationContext dispatcherContext=createContext(WebMvcContextConfiguration.class,InfrastructureContextConfiguration.class);
DispatcherServlet DispatcherServlet=新DispatcherServlet(dispatcherContext);
setContextInitializers(新的SpringMvcExampleProfilesInitializer());
ServletRegistration.Dynamic dispatcher=servletContext.addServlet(dispatcher\u SERVLET\u名称,dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(“/”);
}
私有WebApplicationContext createContext(最终类…AnnotatedClass){
AnnotationConfigWebApplicationContext上下文=新的AnnotationConfigWebApplicationContext();
上下文。寄存器(带注释的类);
//context.refresh();
返回上下文;
}
私有无效注册表列表器(ServletContext ServletContext){
WebApplicationContext rootContext=createContext(配置类);
addListener(新的ContextLoaderListener(rootContext));
//addListener(新的RequestContextListener());
}
私有无效注册表HiddenHttpMethodFilter(ServletContext ServletContext){
FilterRegistration.Dynamic registration=servletContext.addFilter(“hiddenHttpMethodFilter”,hiddenHttpMethodFilter.class);
registration.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD),
false,DISPATCHER_SERVLET_NAME);
}
}

根据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);
}

请发布完整的
springmvcexampleprofilesinializer
,并指定哪个
@Configuration
类包含配置文件,哪个
@Configuration
类具有
ApplicationContextInitializer
。您的问题是,所有内容都要加载两次,并且只在上指定初始值设定项
DispatcherServlet
,而不在
ContextLoaderListener
上。您应该在
ContextLoaderListener
加载常规内容(服务、DAO、基础设施等)和
DispatcherServlet
仅加载与web相关的内容(控制器、查看者等)的位置拆分配置。@SotiriosDelimanolis,我已经更新了question@M.Deinum,我尝试仅在DispatcherServlet中加载web配置,而InfrastructureContextConfiguration仅通过ContextLoaderListener加载。但问题是InfrastructureContextConfiguration使用配置文件。它们仅通过SpringMvcExampleProfilesInitializer for web dispatcher servlet激活。结果,我得到了相同的错误:(数据源bean没有加载。正如前面提到的,您只在
ContextLoaderListener
上指定了
SpringMvcExampleProfilesInitializer
。您通过上下文参数为
ContextLoaderListener
指定它(您可以直接在
ServletContext
上设置)。实际上您需要两者。
ServletContext
中的一个由
ContextLoaderListener
使用,而另一个由
DispatcherSevlet
使用。
@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);
}