2016-08-11 36 views
0

我很新的春天「因爲已經有存在的根應用上下文無法初始化語境」,而我已經有一個很奇怪的問題,一個基本的配置。SpringRest(MVC +安全)的Java配置:

產生的原因:java.lang.IllegalStateException:因爲已經有一個根應用上下文目前無法初始化背景 - 檢查是否有多個的ContextLoader *在你的web.xml定義! 在org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:297) 在org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) 在io.undertow.servlet.core。 ApplicationListeners.contextInitialized(ApplicationListeners.java:173) 在io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:194) ... 7個

我需要兩個不同的REST的Servlet:一個用於內部呼叫(查看服務器),另一個用於外部apis。我還希望一些服務能夠被兩個Servlet共享,所以我使用SpringRootConfiguration來掃描包含兩個攔截器和一個服務的軟件包。

所有配置都是在Java中完成,只有在web.xml

的web.xml

<context-param> 
    <param-name>contextClass</param-name> 
    <param-value> 
     org.springframework.web.context.support.AnnotationConfigWebApplicationContext 
    </param-value> 
</context-param> 

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

SpringRestExternalAppInitializer

@Override 
protected Class<?>[] getRootConfigClasses() { 
    return new Class[]{SpringRootConfiguration.class}; 
} 

@Override 
protected Class<?>[] getServletConfigClasses() { 
    return new Class[]{SpringRestExternalConfiguration.class}; 
} 

@Override 
protected String[] getServletMappings() { 
    return new String[]{"/api/*"}; 
} 

@Override 
protected String getServletName() { 
    return "restexternal"; 
} 

SpringRootConfiguration上下文和偵聽

@ComponentScan({"be.xperthis.common"}) 
@Configuration 
public class SpringRootConfiguration { 

} 

SpringRestExternalConfiguration

@ComponentScan("com.polymedis.result.web.api") 
@Configuration 
public class SpringRestExternalConfiguration extends WebMvcConfigurationSupport { 

@Autowired 
private NoCacheHandler noCacheHandler; 

@Autowired 
private RestMetricHandler restMetrics; 

@Override 
public void addInterceptors(final InterceptorRegistry registry) { 
    registry.addInterceptor(noCacheHandler); 
    registry.addInterceptor(restMetrics); 
} 

@Override 
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { 
    configurer.enable(); 
} 

@Override 
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) { 
    .... 
} 

@Override 
public RequestMappingHandlerMapping createRequestMappingHandlerMapping() { 
    return new ApiVersionRequestMappingHandlerMapping(); //used to check a custom annotation on every RestController methods 
} 
} 

從理論上講,應該有一個第二靜止結構(內部),但我刪除它現在試圖瞭解例外...

注:繼春季安全教程,我不得不同時投入getRootConfigClasses的SpringSecurityConfiguration(同樣的錯誤){...}

我應該從web.xml中刪除/添加一些東西嗎? 我使用Wildfly 8和我已經找到了在Wildfly錯誤解決方法:春天confgiurations不拿起如果彈簧庫(罐)未在WEB-INF/lib文件夾添加...

+1

的問題是,因爲你有這兩個網絡。xml和'SpringRestExternalAppInitializer'(可能擴展'AbstractAnnotationConfigDispatcherServletInitializer')。這實際上幾乎相同 - web.xml是xml變體,並且擴展'AbstractAnnotationConfigDispatcherServletInitializer'是在Java中執行相同操作的方式。所以你必須選擇離開web.xml或Java類。檢查這個問題的答案 - 它可能會幫助http://stackoverflow.com/questions/26676782/when-use-abstractannotationconfigdispatcherservletinitializer-and-webapplication – lenach87

+0

刪除web.xml部分確實解決了我的第一個問題。但是現在,我想爲內部REST調用添加第二個servlet。如果我創建了兩個AbstractAnnotationConfigDispatcherServletInitializer,我確實得到了同樣的錯誤... – ALansmanne

+0

好吧,如果只是添加兩個類,它不應該馬上工作。檢查這個答案,它可能會幫助你得到一般的理解和方式進一步搜索http://stackoverflow.com/questions/12059307/multiple-application-context-multiple-dispatcher-servlets – lenach87

回答

0

好吧,我找到了一個解決方案。相反,覆蓋兩次AbstractAnnotationConfigDispatcherServletInitializer的,我現在用的是單類實現WebApplicationInitializer,我建我的兩個servlet在這個類。

public class SpringAppInitializer implements WebApplicationInitializer { 

@Override 
public void onStartup(final ServletContext servletContext) throws ServletException { 
    final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
    rootContext.register(SpringRootConfiguration.class, SpringSecurityConfig.class); 
    servletContext.addListener(new ContextLoaderListener(rootContext)); 

    // Internal REST 
    buildInternalRestContext(servletContext, rootContext); 

    // External REST 
    buildExternalRestContext(servletContext, rootContext); 

    ... 
} 

public void buildExternalRestContext(final ServletContext servletContext, final AnnotationConfigWebApplicationContext rootContext) { 
    final AnnotationConfigWebApplicationContext externalRestContext = new AnnotationConfigWebApplicationContext(); 
    externalRestContext.setParent(rootContext); 
    externalRestContext.register(SpringRestExternalConfiguration.class); 

    final ServletRegistration.Dynamic externalRestServlet = servletContext.addServlet("externalrest", new DispatcherServlet(externalRestContext)); 
    externalRestServlet.addMapping("/api/*"); 
} 

public void buildInternalRestContext(final ServletContext servletContext, final AnnotationConfigWebApplicationContext rootContext) { 
    final AnnotationConfigWebApplicationContext internalRestContext = new AnnotationConfigWebApplicationContext(); 
    internalRestContext.setParent(rootContext); 
    internalRestContext.register(SpringRestConfiguration.class); 

    final ServletRegistration.Dynamic restDispatcherServlet = servletContext.addServlet("rest", new DispatcherServlet(internalRestContext)); 
    restDispatcherServlet.addMapping("/rest/*"); 
} 

}

現在我將繼續設置SpringSecurity,但那是另一個話題:)