我有多个WAR
,它们都使用CXFServlet
来处理所有请求和Spring
配置。
它们都具有相似的web.xml
(是的,它也在OSGi
(:
<web-app id="app1">
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
它们也都共享一个共同的Spring
配置(common-rest.xml
(:
<beans>
<import resource="classpath:META-INF/cxf/cxf.xml" />
<!-- For brevity I left out jaxRSProviders and jaxRSInInterceptors lists definitions -->
<bean id="baseJaxRSServer"
abstract="true"
lazy-init="false"
class="org.apache.cxf.jaxrs.spring.JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean"
init-method="create"
p:address="${http.server}/"
p:providers-ref="jaxRSProviders"
p:inInterceptors-ref="jaxRSInInterceptors" />
</beans>
它们都有一个类似的特定Spring
配置:
<beans>
<import resource="classpath:META-INF/app/common-rest.xml" />
<!-- For brevity I left out app1ServiceBeans list definition -->
<bean id="app1JaxRSServer"
parent="baseJaxRSServer"
p:serviceBeans-ref="app1ServiceBeans" />
</beans>
问题是,当我现在部署第一个应用程序时,它似乎还可以,但基本上看不到所有其他应用程序绑定。似乎尽管所有应用程序都有单独的Spring
上下文、单独的CXF
服务器和单独的CXF
总线,但它们仍然以某种方式感到困惑,并且每个应用程序都被分配了一个org.apache.cxf.transport.Destination
- 第一个捆绑包中的那个。有谁知道这怎么可能?
CXF:2.6.2,弹簧:3.1.4,卡拉夫:2.3.1
如果你在 Karaf 中运行,我建议先安装 cxf 功能,然后通过蓝图注册你的 cxf 端点,就像使用 Apache Camel 一样。因为据我所知,CXF 确实在 cxf 上下文中注册了一个"主"servlet,从中可以访问所有 Web 服务。在这一点上,你不需要任何战争。除此之外,您没有显示有关 Web-ContextPath 的清单条目,这是 Web 容器在可服务上下文之间有所不同所必需的,因此,如果它们都具有相同的上下文,则第一个获胜!
原来是DestinationRegistry
的问题。默认情况下,CXF
注册使用单个 DestinationRegistry
实例的单个DestinationFactory
。这就是为什么每个Server
都被分配给一个Destination
,因为正如address
字段值所定义的那样,它们都映射到每个 servlet 的/
。
我有用的解决方案是为每个WAR
捆绑包添加一个单独的目标注册表。所以我的common-rest.xml
现在看起来像这样:
<beans>
<import resource="classpath:META-INF/cxf/cxf.xml" />
<bean id="httpDestinationRegistry"
class="org.apache.cxf.transport.http.DestinationRegistryImpl" />
<!-- For brevity I left out jaxRSProviders and jaxRSInInterceptors lists definitions -->
<bean id="baseJaxRSServer"
abstract="true"
lazy-init="false"
class="org.apache.cxf.jaxrs.spring.JAXRSServerFactoryBeanDefinitionParser.SpringJAXRSServerFactoryBean"
init-method="create"
p:address="${http.server}/"
p:providers-ref="jaxRSProviders"
p:inInterceptors-ref="jaxRSInInterceptors" />
</beans>
上述配置与SpringBus
用作ConfiguredBeanLocator
SpringBeanLocator
相结合,为每个 WAR 捆绑包生成一个单独的 Spring 托管的 HTTP DestinationRegistry
实例,这反过来又允许在每个捆绑包中正确配置 CXF 服务器,并导致正确的定义应用程序。