0

背景: 我正在使用 Mule 将大量 Web 服务部署到多个 Mule 实例。我正在使用 Spring 来配置服务,这一切都与文件系统上的属性文件中的配置很好地配合使用。为了简化此类设置的管理,我想将所有配置移至 Web 服务,仅保留文件系统上的最少引导信息。

此引导信息由两部分组成:

1) 配置服务的 URI - 这是作为系统属性传递给 Mule 并被正确获取

2) 配置领域 - 允许服务实例向配置服务标识自己的附加标识符(例如,在服务器 dev-2 上运行的目录服务实例)。这部分不能编码到 Spring 配置中(例如,通过将 configRealm 设置为 catalogue-service),因为每个配置服务可能正在向给定服务的多个实例(例如目录服务)提供配置信息

尝试的解决方案:

1)单个覆盖的 PropertyPlaceholderConfigurer(我知道,我知道),其中包含所有决定编码的逻辑

2)多个不同顺序的PropertyPlaceholderConfigurer(一个处理文件系统属性,一个处理Web服务属性)

3) 一个实现 Order 的自定义 BeanFactoryPostProcessor

4) 将 WebServicePropertySource 定义为 @Configuration 并使用 @PropertySource 显式引用外部文件(失败,因为在需要 WebServicePropertySource 来解析占位符时未初始化环境)

5) 单个 PropertySourcesPlaceholderConfigurer 和一个自定义 PropertySource 来处理 Web 服务属性和 ResourcePropertySources 来处理文件系统属性

所有这些方法(除 4 之外)都失败了,因为我在 PropertySourcesPlaceholderConfigurer/PropertyPlaceholderConfigurer 的定义中使用了占位符 - 未解析占位符并且传递给 Web 服务的领域是 ${catalogue- service-realm} 或类似的。

我知道我可以通过使用系统属性来定义配置领域来完成这项工作,但是由于可能在 Mule 实例中部署了很多服务,这很丑陋,并且需要重新启动服务器才能进行任何更改。

在下面的代码中,我将示例限制为最新的解决方案(上面的 5 个),因为它使用了最新的 Spring 3.1 API。

摘自 mule-config.xml:

   <spring:bean id="configServiceHelper" class="config.client.GetConfigurationServiceHelper">
        <spring:property name="configRealm" value="${catalogue-service-realm}"/>
        <spring:property name="configServiceWsdlUrl" value="${configuration.service.url}"/>
    </spring:bean>

    <spring:bean id="webServicePropertySource" class="config.client.WebServicePropertySource">
        <spring:constructor-arg name="name" value="web-service-property-source"/>
        <spring:constructor-arg name="helper" ref="configServiceHelper"/>
    </spring:bean>

    <spring:bean id="propertySources" class="config.client.DefaultPropertySources">
        <spring:property name="propertySources">
            <spring:list>
                <spring:ref bean="webServicePropertySource"/>
            </spring:list>
        </spring:property>
    </spring:bean>

    <spring:bean class="config.client.LocationPropertySourcesPlaceholderConfigurer">
        <spring:property name="propertySources" ref="propertySources"/>
        <spring:property name="locations">
            <spring:list>
                <spring:value>classpath*:spring/config/*.properties</spring:value>
                <spring:value>classpath:catalogue-service.properties</spring:value>
                <spring:value>classpath:catalogue-service-override.properties</spring:value>
            </spring:list>
        </spring:property>
    </spring:bean>

请注意: config.client.LocationPropertySourcesPlaceholderConfigurer 的行为与默认的 PropertySourcesPLaceholderConfigurer 的不同之处在于,如果设置了 propertySources,它不会丢弃位置,而是将它们添加到 propertySources。记录已确认 propertySources 列表在运行时包含 14 个元素(Web 服务属性源加上 13 个资源)

我很确定这段摘录简洁地说明了我正在尝试做的事情,但如果没有,请询​​问更多细节。我的问题的症结在于 Web 服务帮助程序中的 ${catalogue-service-realm} 占位符没有从类路径上的属性文件中保存的信息中解析出来。

在我看来,这就像先有鸡还是先有蛋的问题,也必须有一个简单的解决方案-我只是不知道它是什么,因此非常感谢任何帮助或指示:-)

亲切的问候,马特

4

3 回答 3

0

我的问题的症结在于 PropertySourcesPlaceholderConfigurer bean 定义中的占位符没有得到解决。

我通过显式手动解析有问题的 configRealm 属性定义中的占位符来解决这个问题。它并不完全优雅,但它确实避免了使用上面Victor Romero提出的额外配置库的需要。

下面带注释的 Spring 配置。

<!-- configRealm moved to webServicePropertySource to prevent 
     the need to pollute service client with Spring PropertyResolver -->
    <spring:bean id="configServiceHelper" class="config.client.GetConfigurationServiceHelper">
        <spring:property name="configServiceWsdlUrl" value="${configuration.service.url}"/>
    </spring:bean>

<!-- WebServicePropertySource now contains configRealm and a PropertyResolver to use
     to resolve the placeholder -->
    <spring:bean id="webServicePropertySource" class="config.client.WebServicePropertySource">
        <spring:constructor-arg name="name" value="web-service-property-source"/>
        <spring:constructor-arg name="helper" ref="configServiceHelper"/>
        <spring:constructor-arg name="realm" value="${bisac_genre_service.config_realm}"/>
        <spring:constructor-arg name="resolver" ref="propertyResolver"/>
    </spring:bean>

<!-- New class to wrap a bunch of resources into a PropertySource -->
    <spring:bean id="resourcePropertySource" class="config.client.ResourceAggregationPropertySource">
        <spring:constructor-arg name="name" value="resource-property-source"/>
        <spring:constructor-arg name="resources">
            <spring:list>
                <spring:value>classpath*:spring/config/*.properties</spring:value>
                <spring:value>classpath:genre-service.properties</spring:value>
                <spring:value>classpath:genre-service-override.properties</spring:value>
            </spring:list>
        </spring:constructor-arg>
    </spring:bean>

<!-- Standard PropertySourcesPropertyResolver defined to just use the 
     classpath resources for resolution -->
    <spring:bean id="propertyResolver" class="org.springframework.core.env.PropertySourcesPropertyResolver">
        <spring:constructor-arg ref="resourcePropertySources"/>
    </spring:bean>

<!-- PropertySources consisting of just the filesystem resources -->
    <spring:bean id="resourcePropertySources" class="config.client.DefaultPropertySources">
        <spring:property name="propertySources">
            <spring:list>
                <spring:ref bean="resourcePropertySource"/>
            </spring:list>
        </spring:property>
    </spring:bean>

<!-- PropertySources consisting of the web service source plus
     the filesystem resources -->
    <spring:bean id="allPropertySources" class="config.client.DefaultPropertySources">
        <spring:property name="propertySources">
            <spring:list>
                <spring:ref bean="resourcePropertySource"/>
                <spring:ref bean="webServicePropertySource"/>
            </spring:list>
        </spring:property>
    </spring:bean>

<!-- Vanilla Spring PropertySourcesPlaceholderConfigurer using ALL PropertySources -->
    <spring:bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <spring:property name="propertySources" ref="allPropertySources"/>
    </spring:bean>
于 2013-03-07T15:55:21.007 回答
0

您是否考虑过使用Spring Profiles

您可以在此处找到有关如何在 mule 中利用它们的简短示例

于 2013-03-06T11:31:47.573 回答
0

Java Configuration API支持多租户配置

要与 Spring 集成,您可以使用此处发布的一些解决方案或仅利用 SpEL,即:@Property("expression").

于 2013-03-06T15:46:08.050 回答