【问题标题】:Multiple CXF servers binding gets overridden by the first server多个 CXF 服务器绑定被第一台服务器覆盖
【发布时间】:2013-04-18 12:53:41
【问题描述】:

我有多个WARs,它们都使用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,Karaf:2.3.1

【问题讨论】:

    标签: spring osgi cxf


    【解决方案1】:

    如果您在 Karaf 中运行,我建议您首先安装 cxf 功能,然后通过蓝图注册您的 cxf 端点,就像使用 Apache Camel 一样。因为据我所知,CXF 确实在 cxf 上下文中注册了一个“主”servlet,从那里可以访问所有 web 服务。 在这一点上,你不需要任何战争。除了您没有显示有关 Web-ContextPath 的清单条目之外,Web 容器需要在可服务的上下文之间进行区分,因此如果它们都具有相同的上下文,则第一个获胜!

    【讨论】:

    • 感谢您的回答!我知道这个版本的CXF 具有“主”servlet。但是,我从 CXF 2.4.2 迁移并使用了 WARs 和 Spring Web 上下文,因此转向您建议的解决方案,这是正确的,需要对我的应用程序进行太多更改,就像一步一样。因此,我决心保留WARs,尽管没有明确说明,但每个都有不同的Web-ContextPath 值。我能够找到一个解决方案,我将发布一个单独的答案。
    【解决方案2】:

    原来是DestinationRegistry 的问题。默认情况下,CXF 注册一个使用DestinationRegistry 的单个实例的DestinationFactory。这就是为什么每个Server 都被分配给一个Destination 的原因,因为它们都映射到每个servlet 的/,正如address 字段值所定义的那样。

    对我有用的解决方案是为每个 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 用作ConfiguredBeanLocatorSpringBeanLocator 相结合,会为每个WAR 包生成一个单独的、Spring 托管的HTTP DestinationRegistry 实例,这反过来又允许正确配置CXF 服务器每个捆绑包并导致正确的应用程序。

    【讨论】:

    • 你有没有机会向我指出一些示例代码的方向?如何配置SpringBeanLocator 来查找DestinationRegistryImpl
    猜你喜欢
    • 2013-05-17
    • 2023-04-08
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 2021-07-07
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多