2.7. 属性 Placeholders


概述

属性占位符功能可用于将字符串替换为不同的上下文(如端点 URI 和 XML DSL 元素中的属性),其中占位符设置存储在 Java 属性文件中。如果您要在不同 Apache Camel 应用程序间共享设置,或者要集中某些配置设置,则此功能很有用。

例如,以下路由向 Web 服务器发送请求,其主机和端口被占位符、{{remote.host}}{{remote.port}} 替换:

from("direct:start").to("http://{{remote.host}}:{{remote.port}}");

占位符值在 Java 属性文件中定义,如下所示:

# Java properties file
remote.host=myserver.com
remote.port=8080
注意

属性 Placeholders 支持编码选项,允许您使用特定字符集(如 UTF-8)读取 .properties 文件。但是,默认情况下它会实施 ISO-8859-1 字符集。

使用 PropertyPlaceholders 的 Apache Camel 支持以下内容:

  • 将默认值与要查找的键一起指定。
  • 如果所有占位符键都包含默认值,则不需要定义 PropertiesComponent
  • 使用第三方功能查找属性值。它可让您实现自己的逻辑。

    注意

    提供三个开箱即用的功能,用于从 OS 环境变量、JVM 系统属性或服务名称 idiom 中查找值。

属性文件

属性设置存储在一个或多个 Java 属性文件中,必须符合标准 Java 属性文件格式。每个属性设置都出现在其自己的行中,格式为 Key=Value。带有 #! 作为第一个非空字符的行被视为注释。

例如,属性文件可以有如下内容,如 例 2.4 “属性文件示例” 所示。

例 2.4. 属性文件示例

# Property placeholder settings
# (in Java properties file format)
cool.end=mock:result
cool.result=result
cool.concat=mock:{{cool.result}}
cool.start=direct:cool
cool.showid=true

cheese.end=mock:cheese
cheese.quote=Camel rocks
cheese.type=Gouda

bean.foo=foo
bean.bar=bar

解析属性

属性组件必须配置有一个或多个属性文件的位置,然后才能在路由定义中使用它。您必须使用以下解析器之一提供属性值:

classpath:PathName,PathName,…​
(默认) 指定 classpath 上的位置,其中 PathName 是使用正斜杠分隔的文件路径名称。
file:PathName,PathName,…​
指定文件系统上的位置,其中 PathName 是用正斜杠分隔的文件路径名称。
ref:BeanID
指定 registry 中的 java.util.Properties 对象的 ID。
蓝图:BeanID
指定 cm:property-placeholder bean 的 ID,该 Bean 蓝图文件上下文中用于访问 OSGi 配置管理服务中 定义的属性。详情请查看 “与 OSGi 蓝图属性占位符集成”一节

例如,要指定 com/fusesource/cheese.properties 属性文件和 com/fusesource/bar.properties 属性文件(位于 classpath 上),您可以使用以下位置字符串:

com/fusesource/cheese.properties,com/fusesource/bar.properties
注意

您可以在本示例中省略 classpath: 前缀,因为默认情况下使用了 classpath 解析器。

使用系统属性和环境变量指定位置

您可以将 Java 系统属性和 O/S 环境变量嵌入到 路径Name 中。

Java 系统属性可以使用语法 ${PropertyName} 嵌入到位置解析器中。例如,如果红帽 Fuse 的根目录存储在 Java 系统属性 karaf.home 中,您可以将该目录值嵌入到文件位置,如下所示:

file:${karaf.home}/etc/foo.properties

O/S 环境变量可以使用语法 ${env:VarName} 嵌入到位置解析器中。例如,如果 JBoss Fuse 的根目录存储在环境变量 SMX_HOME 中,您可以将该目录值嵌入到文件位置,如下所示:

file:${env:SMX_HOME}/etc/foo.properties

配置属性组件

在开始使用属性占位符前,您必须配置属性组件,指定一个或多个属性文件的位置。

在 Java DSL 中,您可以使用属性文件位置配置属性组件,如下所示:

// Java
import org.apache.camel.component.properties.PropertiesComponent;
...
PropertiesComponent pc = new PropertiesComponent();
pc.setLocation("com/fusesource/cheese.properties,com/fusesource/bar.properties");
context.addComponent("properties", pc);

addComponent () 调用中所示,属性组件的名称 必须设置为 属性

在 XML DSL 中,您可以使用专用 propertyPlacholder 元素配置属性组件,如下所示:

<camelContext ...>
   <propertyPlaceholder
      id="properties"
      location="com/fusesource/cheese.properties,com/fusesource/bar.properties"
   />
</camelContext>

如果您希望属性组件在初始化时忽略任何缺少的 .properties 文件,您可以将 ignoreMissingLocation 选项设置为 true (通常,缺少 .properties 文件会导致引发错误)。

另外,如果您希望属性组件忽略使用 Java 系统属性或 O/S 环境变量指定的任何缺失位置,您可以将 ignoreMissingLocation 选项设置为 true

占位符语法

配置后,属性组件会自动替换占位符(在适当的上下文中)。占位符的语法取决于上下文,如下所示:

  • 在端点 URI 中,在 Spring XML 文件中 iwl-wagonthe 占位符被指定为 { {Key}}
  • 当设置 XML DSL 属性 criu- xs:string 属性时,使用以下语法设置:

    AttributeName="{{Key}}"

    必须使用以下语法设置其他属性类型(如 xs:intxs:boolean):

    prop:AttributeName="Key"

    其中 prophttp://camel.apache.org/schema/placeholder 命名空间关联。

  • 在 Java DSL 中设置 Java DSL EIP 选项 criu- iwlto 设置选项时,请在 Java DSL 中的 Enterprise Integration Pattern (EIP)命令上设置选项,请将类似于 fluent DSL 的 placeholder () 子句添加到 fluent DSL 中:

    .placeholder("OptionName", "Key")
  • 在简单语言表达式 中,在简单语言表达式 criu-wagonthe 占位符被指定为 ${properties:Key}

在端点 URI 中替换

如果端点 URI 字符串出现在路由中,解析端点 URI 的第一步是应用属性占位符解析程序。占位符解析器会自动替换双花括号 {{ Key}} 之间出现的任何属性 名称。例如,假设 例 2.4 “属性文件示例” 中显示的属性设置,您可以定义路由,如下所示:

from("{{cool.start}}")
    .to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
    .to("mock:{{cool.result}}");

默认情况下,占位符解析器查找 registry 中的 属性 bean ID 来查找属性组件。如果您愿意,您可以在端点 URI 中明确指定方案。例如,通过将 properties: 前缀给每个端点 URI,您可以定义以下等同的路由:

from("properties:{{cool.start}}")
    .to("properties:log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
    .to("properties:mock:{{cool.result}}");

在明确指定方案时,您还可以选择指定属性组件的选项。例如,要覆盖属性文件位置,您可以设置 location 选项,如下所示:

from("direct:start").to("properties:{{bar.end}}?location=com/mycompany/bar.properties");

Spring XML 文件中的替换

您还可以使用 XML DSL 中的属性占位符来设置 DSL 元素的各种属性。在这种情况下,placholder 语法也使用双花括号 {{ Key}}。例如,您可以使用属性占位符定义 jmxAgent 元素,如下所示:

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <propertyPlaceholder id="properties" location="org/apache/camel/spring/jmx.properties"/>

    <!-- we can use property placeholders when we define the JMX agent -->
    <jmxAgent id="agent" registryPort="{{myjmx.port}}"
              usePlatformMBeanServer="{{myjmx.usePlatform}}"
              createConnector="true"
              statisticsLevel="RoutesOnly"
            />

    <route>
        <from uri="seda:start"/>
        <to uri="mock:result"/>
    </route>
</camelContext>

替换 XML DSL 属性值

您可以使用常规的占位符语法来指定 xs:string type iwl-setuptoolsfor 例如,< jmxAgent registryPort="{{myjmx.port}}" …​ >。但是,对于任何其他类型的属性(例如 xs:intxs:boolean),您必须使用特殊语法,prop:AttributeName="Key".

例如,如果属性文件定义了 stop.flag 属性来具有值 true,您可以使用此属性设置 stopOnException 布尔值属性,如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:prop="http://camel.apache.org/schema/placeholder"
       ... >

    <bean id="illegal" class="java.lang.IllegalArgumentException">
        <constructor-arg index="0" value="Good grief!"/>
    </bean>

    <camelContext xmlns="http://camel.apache.org/schema/spring">

        <propertyPlaceholder id="properties"
                             location="classpath:org/apache/camel/component/properties/myprop.properties"
                             xmlns="http://camel.apache.org/schema/spring"/>

        <route>
            <from uri="direct:start"/>
            <multicast prop:stopOnException="stop.flag">
                <to uri="mock:a"/>
                <throwException ref="damn"/>
                <to uri="mock:b"/>
            </multicast>
        </route>

    </camelContext>

</beans>
重要

prop 前缀必须明确分配给 Spring 文件中的 http://camel.apache.org/schema/placeholder 命名空间,如上例的 beans 元素所示。

替换 Java DSL EIP 选项

在 Java DSL 中调用 EIP 命令时,您可以使用属性占位符值设置任何 EIP 选项,方法是添加表单的子clause,占位符("OptionName", "Key")

例如,如果属性文件定义了 stop.flag 属性来具有值 true,您可以使用此属性设置多播 EIP 的 stopOnException 选项,如下所示:

from("direct:start")
    .multicast().placeholder("stopOnException", "stop.flag")
        .to("mock:a").throwException(new IllegalAccessException("Damn")).to("mock:b");

使用简单语言表达式替换

您也可以用简单语言表达式替换属性占位符,但在这种情况下,占位符的语法为 ${properties:Key}。例如,您可以替换简单表达式中的 cheese.quote 占位符,如下所示:

from("direct:start")
    .transform().simple("Hi ${body} do you think ${properties:cheese.quote}?");

您可以使用语法 ${properties:Key:DefaultVal} 来指定属性的默认值。例如:

from("direct:start")
    .transform().simple("Hi ${body} do you think ${properties:cheese.quote:cheese is good}?");

也可以使用语法 ${properties-location:Location:Key} 来覆盖属性文件的位置。例如,要使用 com/mycompany/bar.properties 属性文件中的设置替换 bar.quote 占位符,您可以定义一个简单的表达式,如下所示:

from("direct:start")
    .transform().simple("Hi ${body}. ${properties-location:com/mycompany/bar.properties:bar.quote}.");

在 XML DSL 中使用 Property Placeholders

在旧版本中,xs:string 类型属性用于支持 XML DSL 中的占位符。例如,timeout 属性是 xs:int 类型。因此,您无法将字符串值设置为占位符键。

现在,在 Apache Camel 2.7 中,可以使用特殊的占位符命名空间来实现。以下示例演示了命名空间的 prop 前缀。它可让您在 XML DSLs 的属性中使用 prop 前缀。

注意

在 Multicast 中,将选项 stopOnException 设置为占位符值,其键 stop。另外,在属性文件中,将值定义为

stop=true
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:prop="http://camel.apache.org/schema/placeholder"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    ">

    <!-- Notice in the declaration above, we have defined the prop prefix as the Camel placeholder namespace -->

    <bean id="damn" class="java.lang.IllegalArgumentException">
        <constructor-arg index="0" value="Damn"/>
    </bean>

    <camelContext xmlns="http://camel.apache.org/schema/spring">

        <propertyPlaceholder id="properties"
                             location="classpath:org/apache/camel/component/properties/myprop.properties"
                             xmlns="http://camel.apache.org/schema/spring"/>

        <route>
            <from uri="direct:start"/>
            <!-- use prop namespace, to define a property placeholder, which maps to
                 option stopOnException={{stop}} -->
            <multicast prop:stopOnException="stop">
                <to uri="mock:a"/>
                <throwException ref="damn"/>
                <to uri="mock:b"/>
            </multicast>
        </route>

    </camelContext>

</beans>

与 OSGi 蓝图属性占位符集成

如果您将路由部署到红帽 Fuse OSGi 容器中,您可以将 Apache Camel 属性占位符机制与 JBoss Fuse 的蓝图属性占位符机制集成(实际上,集成会被默认启用)。设置集成的基本方法有两种,如下所示:

隐式蓝图集成

如果您在 OSGi 蓝图文件中定义了 camelContext 元素,则 Apache Camel 属性占位符机制会自动与蓝图属性占位符机制集成。也就是说,通过查找 蓝图属性占位符 机制来隐式解析在 camelContext 范围内出现的 Apache Camel 语法(如 {{cool.end}})。

例如,请考虑以下路由,其中路由中的最后一个端点由属性占位符 {{result}} 定义:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
           xsi:schemaLocation="
           http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <!-- OSGI blueprint property placeholder -->
    <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
        <!-- list some properties for this test -->
        <cm:default-properties>
            <cm:property name="result" value="mock:result"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">
        <!-- in the route we can use {{ }} placeholders which will look up in blueprint,
             as Camel will auto detect the OSGi blueprint property placeholder and use it -->
        <route>
            <from uri="direct:start"/>
            <to uri="mock:foo"/>
            <to uri="{{result}}"/>
        </route>
    </camelContext>

</blueprint>

blueprint 属性占位符机制通过创建一个 cm:property-placeholder bean 来初始化。在前面的示例中,cm:property-placeholder bean 与 camel.blueprint 持久 ID 关联,其中持久性 ID 是引用 OSGi Configuration Admin 服务中一组相关属性的标准方法。换句话说,cm:property-placeholder bean 提供对 camel.blueprint 持久 ID 中定义的所有属性的访问。也可以为某些属性指定默认值(使用嵌套的 cm:property 元素)。

在蓝图中,Apache Camel 占位符机制在 bean registry 中搜索 cm:property-placeholder 实例。如果找到这样的实例,它会自动集成 Apache Camel 占位符机制,以便诸如 {{result}} 的占位符是通过在蓝图属性占位符机制(本例中为 myblueprint.placeholder bean)中的键来解决。

注意

默认蓝图占位符语法(直接访问蓝图属性)为 ${Key}。因此,在 camelContext 元素的 范围外,您必须使用的占位符语法为 ${Key}。但在 camelContext 元素的范围内,您必须使用的占位符语法是 {{ Key}}

显式蓝图集成

如果要更好地控制 Apache Camel 属性占位符机制在哪里找到其属性,您可以定义 propertyPlaceholder 元素并明确指定解析器位置。

例如,请考虑以下蓝图配置,它与上例不同,它会创建一个明确的 propertyPlaceholder 实例:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
           xsi:schemaLocation="
           http://www.osgi.org/xmlns/blueprint/v1.0.0 ">https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <!-- OSGI blueprint property placeholder -->
    <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint">
        <!-- list some properties for this test -->
        <cm:default-properties>
            <cm:property name="result" value="mock:result"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">

        <!-- using Camel properties component and refer to the blueprint property placeholder by its id -->
        <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder"/>

        <!-- in the route we can use {{ }} placeholders which will lookup in blueprint -->
        <route>
            <from uri="direct:start"/>
            <to uri="mock:foo"/>
            <to uri="{{result}}"/>
        </route>

    </camelContext>

</blueprint>

在前面的示例中,propertyPlaceholder 元素通过将位置设置为 blueprint:myblueprint.placeholder 元素明确指定要使用的 cm:property-placeholder bean。也就是说,蓝图: 解析器明确引用 cm:property-placeholder bean 的 ID、myblueprint.placeholder

如果蓝图文件中定义了多个 cm:property-placeholder bean,则需要指定要使用的配置,则这种配置样式很有用。它还可以通过指定以逗号分隔的位置列表来从多个位置 source 属性。例如,如果要从 cm:property-placeholder bean 和属性文件 myproperties.properties 中查找属性,您可以在 classpath 上定义 propertyPlaceholder 元素,如下所示:

<propertyPlaceholder id="properties"
  location="blueprint:myblueprint.placeholder,classpath:myproperties.properties"/>

与 Spring 属性占位符集成

如果您在 Spring XML 文件中使用 XML DSL 定义 Apache Camel 应用程序,您可以通过声明类型为 org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer 的 Spring property 占位符机制将 Apache Camel 属性占位符机制与 Spring 属性占位符机制集成。

定义 BridgePropertyPlaceholderConfigurer,它替换了 Spring XML 文件中的 Apache Camel 的 propertyPlaceholder 元素和 Spring 的 ctx:property-placeholder 元素。然后,您可以使用 Spring ${PropName} 语法或 Apache Camel {{ PropName}} 语法来引用配置的属性。

例如,定义网桥属性占位符从 cheese.properties 文件中读取其属性设置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ctx="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- Bridge Spring property placeholder with Camel -->
  <!-- Do not use <ctx:property-placeholder ... > at the same time -->
  <bean id="bridgePropertyPlaceholder"
        class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
    <property name="location"
              value="classpath:org/apache/camel/component/properties/cheese.properties"/>
  </bean>

  <!-- A bean that uses Spring property placeholder -->
  <!-- The ${hi} is a spring property placeholder -->
  <bean id="hello" class="org.apache.camel.component.properties.HelloBean">
    <property name="greeting" value="${hi}"/>
  </bean>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <!-- Use Camel's property placeholder {{ }} style -->
    <route>
      <from uri="direct:{{cool.bar}}"/>
      <bean ref="hello"/>
      <to uri="{{cool.end}}"/>
    </route>
  </camelContext>

</beans>
注意

另外,您可以设置 BridgePropertyPlaceholderConfigurerlocation 属性以指向 Spring 属性文件。Spring 属性文件语法被完全支持。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.