2.7. attribute Placeholders
概述 复制链接链接已复制到粘贴板!
属性占位符功能可用于将字符串替换为不同的上下文(如 XML DSL 元素中的端点 URI 和属性),其中占位符设置存储在 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 “Property 文件示例” 所示。
例 2.4. Property 文件示例
# 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,…- (默认) 指定类路径中的位置,其中 PathName 是使用正斜杠分隔的文件路径名。
file:PathName,PathName,…- 指定文件系统中的位置,其中 PathName 是以正斜杠分隔的文件路径名。
ref:BeanID-
指定 registry 中的
java.util.Properties对象的 ID。 蓝图:BeanID-
指定
cm:property-placeholderbean 的 ID,该 ID 可用于访问 OSGi 配置管理服务中定义的属性。详情请查看 “与 OSGi 蓝图属性占位符集成”一节。
例如,要指定 com/fusesource/cheese.properties 属性文件和 com/fusesource/bar.properties 属性文件,两者均位于 classpath 上,您需要使用以下位置字符串:
com/fusesource/cheese.properties,com/fusesource/bar.properties
您可以省略本例中的 classpath: 前缀,因为默认情况下使用 classpath 解析器。
使用系统属性和环境变量指定位置 复制链接链接已复制到粘贴板!
您可以在位置 PathName 中嵌入 Java 系统属性和 O/S 环境变量。
Java 系统属性可以使用语法 ${PropertyName} 嵌入在位置解析器中。例如,如果 Red Hat 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 文件中 InventoryService-","the 占位符被指定为 {
{Key}}。 当设置 XML DSL 属性时 ,使用以下语法设置
字符串属性:AttributeName="{{Key}}"必须使用以下语法设置其他属性类型(例如
xs:int或xs:boolean):prop:AttributeName="Key"其中
prop与http://camel.apache.org/schema/placeholder命名空间关联。在设置 Java DSL EIP 选项 targetNamespaces 选项 InventoryService-jaxbto 时,在 Java DSL 中对企业级集成模式(EIP)命令设置选项时,请在流畅的 DSL 中添加类似于以下内容的
占位符()子句:.placeholder("OptionName", "Key")-
在简单语言表达式中 ,placeholder指定为
${properties:Key}。
在端点 URI 中替换 复制链接链接已复制到粘贴板!
只要端点 URI 字符串出现在路由中,解析端点 URI 的第一步是应用属性占位符解析器。占位符解析器自动替换双花括号之间出现的任何属性名称 {{ Key}}。例如,如果 例 2.4 “Property 文件示例” 中显示的属性设置,您可以定义路由,如下所示:
from("{{cool.start}}")
.to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}")
.to("mock:{{cool.result}}");
默认情况下,占位符解析器查找 registry 中的 属性 bean ID 来查找属性组件。如果愿意,您可以在端点 URI 中明确指定方案。例如,通过为每个端点 URI 加上前缀 属性: 到每个端点 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 元素的各种属性。在此上下文中,拥有者语法也使用双花括号 {{ 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 typegradle-sHistoryLimitfor example, < jmxAgent registryPort="{{myjmx.port}}" … >。但是,对于任何其他类型的属性(例如,xs:int 或 xs: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>
必须明确分配给 Spring 文件中的 http://camel.apache.org/schema/placeholder 命名空间,如上例的 Bean 元素中所示。
替换 Java DSL EIP 选项 复制链接链接已复制到粘贴板!
在 Java DSL 中调用 EIP 命令时,您可以通过添加表单、占位符(" options Name", "Key") 值,使用属性值来设置任何 EIP 选项。
例如,如果某个属性文件定义了 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 DSL 中属性中的 prop 前缀。
在多播中,将选项 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}})通过查找 蓝图属性占位符 机制来隐式解析。
例如,考虑在 OSGi 蓝图文件中定义以下路由,路由中最后一个端点由属性占位符定义,{{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>
蓝图属性占位符机制通过创建一个 cm:property-placeholder an 初始化。在前面的示例中,cm:property-placeholder bean 与 camel.blueprint 持久 ID 关联,持久 ID 是引用 OSGi 配置管理 服务中一组相关属性的标准方式。换句话说,cm:property-placeholder an 提供了对 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。该 蓝图: 解析器明确引用 cm:property-placeholder 的 ID、myblueprint.placeholder。
这种配置方式很有用,如果蓝图文件中定义了多个 cm:property-placeholder an,并且您需要指定要使用的选项。它还可通过指定以逗号分隔的位置列表,从多个位置的源属性。例如,如果要从 cm:property-placeholder bean 和 properties 文件( myproperties.properties )在 classpath 上查找属性,您可以按照如下所示定义 propertyPlaceholder 元素:
<propertyPlaceholder id="properties"
location="blueprint:myblueprint.placeholder,classpath:myproperties.properties"/>
与 Spring 属性占位符集成 复制链接链接已复制到粘贴板!
如果您在 Spring XML 文件中使用 XML DSL 定义 Apache Camel 应用程序,您可以通过声明类型为 Spring 片段机制来将 Apache Camel 属性占位符机制集成,org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer。
定义 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>
另外,您可以设置 BridgePropertyPlaceholderConfigurer 的 location 属性,使其指向 Spring 属性文件。完全支持 Spring 属性文件语法。