2.6. 转换消息内容

摘要

Apache Camel 支持多种方法来转换消息内容。除了用于修改消息内容的简单原生 API 外,Apache Camel 支持与几个不同的第三方库和转换标准集成。

2.6.1. 简单消息转换

概述

Java DSL 具有一个内置 API,允许您在传入和传出消息上执行简单的转换。例如,例 2.1 “引入消息的简单转换” 中显示的规则会将文本 World! 附加到传入消息正文的末尾。

例 2.1. 引入消息的简单转换

from("SourceURL").setBody(body().append(" World!")).to("TargetURL");

其中 setBody() 命令取代了传入邮件正文的内容。

用于简单转换的 API

您可以使用以下 API 类在路由器规则中执行消息内容的简单转换:

  • org.apache.camel.model.ProcessorDefinition
  • org.apache.camel.builder.Builder
  • org.apache.camel.builder.ValueBuilder

ProcessorDefinition class

org.apache.camel.model.ProcessorDefinition 类定义 DSL 命令,您可以在 例 2.1 “引入消息的简单转换” 中直接插入路由器 rule>_<-targetNamespaces 例如: 中的 setBody() 命令。表 2.5 “从处理器Definition 类转换方法” 显示与转换消息内容相关的 ProcessorDefinition 方法:

表 2.5. 从处理器Definition 类转换方法

方法描述

类型 convertBodyTo(Class type)

将 IN 消息正文转换为指定的类型。

类型 removeFaultHeader(字符串名称)

添加处理器,以删除 FAULT 消息上的标头。

type removeHeader(String name)

添加可移除 IN 消息上的标头的处理器。

键入 removeProperty(String name)

添加可移除交换属性的处理器。

ExpressionClause<ProcessorDefinition<Type>> setBody()

添加在 IN 消息上设置正文的处理器。

键入 setFaultBody(Expression expression)

添加在 FAULT 消息上设置正文的处理器。

type setFaultHeader(String name, Expression expression)

添加在 FAULT 消息上设置标头的处理器。

ExpressionClause<ProcessorDefinition<Type>> setHeader(String name)

添加在 IN 消息上设置标头的处理器。

type setHeader(String name, Expression expression)

添加在 IN 消息上设置标头的处理器。

ExpressionClause<ProcessorDefinition<Type>> setOutHeader(String name)

添加在 OUT 消息上设置标头的处理器。

type setOutHeader(String name, Expression expression)

添加在 OUT 消息上设置标头的处理器。

ExpressionClause<ProcessorDefinition<Type>> setProperty(String name)

添加可设置 Exchange 属性的处理器。

键入 setProperty(String name, Expression expression)

添加可设置 Exchange 属性的处理器。

ExpressionClause<ProcessorDefinition<Type>> transform()

添加在 OUT 消息上设置正文的处理器。

类型转换(Expression 表达式)

添加在 OUT 消息上设置正文的处理器。

builder 类

org.apache.camel.builder.Builder 类提供对预期表达式或 predicates 的上下文中的消息内容的访问。换句话说,在 DSL 命令的参数 中通常会调用 Builder 方法。例如,例 2.1 “引入消息的简单转换” 中的 body() 命令。表 2.6 “Builder 类中的方法” 总结 Builder 类中的静态方法。

表 2.6. Builder 类中的方法

方法描述

静态 <E 扩展 Exchange> ValueBuilder<E> body()

为交换上的入站正文返回 predicate 和 value builder。

静态 <E 扩展 Exchange,T> ValueBuilder<E> bodyAs(Class<T> type)

为入站邮件正文返回 predicate 和 value builder,作为特定类型的值。

静态 <E 扩展 Exchange> ValueBuilder<E> constant(Object value)

返回恒定表达式。

静态 <E 扩展 Exchange> ValueBuilder<E> faultBody()

为交换上的错误正文返回 predicate 和 value builder。

静态 <E 扩展 Exchange,T> ValueBuilder<E> faultBodyAs(Class<T> type)

为错误消息正文返回 predicate 和 value builder,作为特定类型的值。

静态 <E 扩展 Exchange> ValueBuilder<E> 标头(字符串名称)

为交换上的标头返回 predicate 和 value builder。

静态 <E 扩展 Exchange> ValueBuilder<E> outBody()

为交换上的出站正文返回 predicate 和 value builder。

静态 <E 扩展 Exchange> ValueBuilder<E> outBodyAs(Class<T> type)

为出站邮件正文返回 predicate 和 value builder,作为特定类型的特定类型。

static ValueBuilder 属性(字符串名称)

为交换的属性返回 predicate 和 value builder。

static ValueBuilder regexReplaceAll(Expression content, String regex, Expression replacement)

返回表达式将所有出现正则表达式的表达式替换为给定的替换。

static ValueBuilder regexReplaceAll(Expression content, String regex, String replacement)

返回表达式将所有出现正则表达式的表达式替换为给定的替换。

static ValueBuilder sendTo(String uri)

返回将交换发送到给定端点 uri 的表达式。

静态 <E 扩展 Exchange> ValueBuilder<E> systemProperty(String name)

返回给定系统属性的表达式。

静态 <E 扩展 Exchange> ValueBuilder<E> systemProperty(String name, String defaultValue)

返回给定系统属性的表达式。

ValueBuilder 类

org.apache.camel.builder.ValueBuilder 类允许您修改 Builder 方法返回的值。换句话说,ValueBuilder 中的方法提供了一个简单的修改消息内容的方法。表 2.7 “ValueBuilder 类的修饰符方法” 总结了 ValueBuilder 类中可用的方法。也就是说,该表只显示用于修改在其所调用的值的方法(查看完整详情,请参阅 API 参考文档 )。

表 2.7. ValueBuilder 类的修饰符方法

方法描述

ValueBuilder<E> append(Object value)

使用所给值附加此表达式的字符串评估。

predicate 包含(Object 值)

创建一个 predicate,使左手表达式包含右手表达式的值。

ValueBuilder<E> convertTo(Class type)

使用已注册类型转换器将当前值转换为给定类型。

ValueBuilder<E> convertToString()

使用注册的类型转换器转换当前值 String。

predicate 结束(Object value)

 

<T> T evaluate(Exchange exchange, Class<T> type)

 

predicate in(Object…​ values)

 

predicate in(Predicate…​ predicates)

 

predicate 是EqualTo(Object value)

返回 true,如果当前值等于给定 参数。

predicate 是GreaterThan(Object 值)

返回 true,如果当前值大于给定 参数。

predicate 是GreaterThanOrEqualTo(Object value)

返回 true,如果当前值大于或等于给定 参数。

predicate 是InstanceOf(Class type)

返回为 true,如果当前值是给定类型的实例。

predicate isLessThan(Object value)

返回为 true,如果当前值小于给定 参数。

predicate 是 LessThanOrEqualTo(Object value)

返回为 true,如果当前值小于或等于给定 参数。

predicate 是NotEqualTo(Object value)

返回 true,如果当前值不等于给定 参数。

predicate 是NotNull()

返回 true,如果当前值不是 null,则返回。

predicate isNull()

返回 true,如果当前值是 null

predicate matches(Expression 表达式)

 

predicate not(Predicate predicate)

导航 predicate 参数。

ValueBuilder prepend(Object value)

将这个表达式的字符串评估添加到所给值。

predicate regex(字符串 regex)

 

ValueBuilder<E> regexReplaceAll(String regex, Expression<E> 替换)

将正则表达式的所有发生情况替换为给定的替换。

ValueBuilder<E> regexReplaceAll(String regex, String replacement)

将正则表达式的所有发生情况替换为给定的替换。

ValueBuilder<E> regexTokenize(String regex)

使用给定的正则表达式对这个表达式的字符串转换进行令牌。

ValueBuilder sort(Comparator comparator)

使用给定比较器对当前值进行排序。

predicate 启动With(Object 值)

返回 true,如果当前值与 value 参数的字符串值匹配。

ValueBuilder<E> tokenize()

使用逗号令牌分隔符标记此表达式的字符串转换。

ValueBuilder<E> 令牌化(字符串令牌)

使用给定令牌分隔符对这个表达式的字符串转换进行令牌转换。

2.6.2. marshalling 和 Unmarshalling

Java DSL 命令

您可以使用以下命令在低级和高级别消息格式转换:

  • marshal() abrt-abrt 将高级别数据格式转换为低级数据格式。
  • unmarshal() jaxb-abrt 将低级数据格式转换为高级别数据格式。

数据格式

Apache Camel 支持以下数据格式的 marshalling 和 unmarshalling:

  • Java序列化
  • JAXB
  • XMLBeans
  • XStream

Java序列化

允许您将 Java 对象转换为二进制数据的 Blob。对于这个数据格式,取消marshall 会将二进制 blob 转换为 Java 对象,并将 Java 对象转换为二进制 blob。例如,若要从端点 SourceURL 读取序列化 Java 对象,并将其转换为 Java 对象,您可以使用类似如下的规则:

from("SourceURL").unmarshal().serialization()
.<FurtherProcessing>.to("TargetURL");

或者,在 Spring XML 中:

<camelContext id="serialization" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <serialization/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

JAXB

提供 XML 模式类型和 Java 类型之间的映射(请参阅 https://jaxb.dev.java.net/)。对于 JAXB,unmarshalling 会将 XML 数据类型转换为 Java 对象,并总结 Java 对象转换为 XML 数据类型。在可以使用 JAXB 数据格式之前,您必须使用 JAXB 编译器编译您的 XML 架构,以在架构中生成代表 XML 数据类型的 Java 类。这称为 绑定模式。绑定模式后,您可以使用类似如下的代码定义将 XML 数据解压缩到 Java 对象的规则:

org.apache.camel.spi.DataFormat jaxb = new org.apache.camel.converter.jaxb.JaxbDataFormat("GeneratedPackageName");

from("SourceURL").unmarshal(jaxb)
.<FurtherProcessing>.to("TargetURL");

其中 generateedPackagename 是 JAXB 编译器生成的 Java 软件包的名称,其中包含代表您的 XML 架构的 Java 类。

或者,在 Spring XML 中:

<camelContext id="jaxb" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <jaxb prettyPrint="true" contextPath="GeneratedPackageName"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XMLBeans

提供 XML 模式类型和 Java 类型之间的备选映射(请参阅 http://xmlbeans.apache.org/)。对于 XMLBeans,unmarshalling 会将 XML 数据类型转换为 Java 对象,并将 Java 对象转换为 XML 数据类型。例如,要使用 XMLBeans 将 XML 数据解压缩到 Java 对象,您可以使用类似如下的代码:

from("SourceURL").unmarshal().xmlBeans()
.<FurtherProcessing>.to("TargetURL");

或者,在 Spring XML 中:

<camelContext id="xmlBeans" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <xmlBeans prettyPrint="true"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XStream

提供 XML 类型和 Java 类型之间的另一个映射(请参阅 http://www.xml.com/pub/a/2004/08/18/xstream.html)。XStream 是一个序列化库(如 Java序列化),可让您将任何 Java 对象转换为 XML。对于 XStream,解压缩将 XML 数据类型转换为 Java 对象,并汇总 Java 对象,将 Java 对象转换为 XML 数据类型。

from("SourceURL").unmarshal().xstream()
.<FurtherProcessing>.to("TargetURL");
注意

Spring XML 目前不支持 XStream 数据格式。

2.6.3. 端点绑定

什么是绑定?

在 Apache Camel 中,绑定 是一种将端点嵌套在 contract contract-sHistoryLimit 例如,通过应用数据格式、内容增强器或验证步骤的方法。条件或转换应用于传入消息的消息,并应用于消息的补充条件或转换。

DataFormatBinding

对于您要定义 marshals 和 unmarshals 特定数据格式的绑定(请参阅 第 2.6.2 节 “marshalling 和 Unmarshalling”,请参阅 在这种情况下,您需要进行创建绑定的所有操作都是创建 DataFormatBinding 实例,在 constructor 中传递对相关数据格式的引用。

例如: 例 2.2 “JAXB Binding” 中的 XML DSL 片断会显示一个绑定(带有 ID、jaxb)的绑定(使用 ID, jaxb ),当它与 Apache Camel 端点关联时,能够放宽和取消汇总 JAXB 数据格式:

例 2.2. JAXB Binding

<beans ... >
    ...
    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

将绑定与端点关联

以下的替代方法可用于将绑定与端点关联:

绑定 URI

要将绑定与端点关联,您可以将端点 URI 前缀为 binding:NameOfBinding,其中 NameOfBinding 是绑定的 bean ID(例如,在 Spring XML 中创建绑定 bean 的 ID)。

例如,以下示例演示了如何将 ActiveMQ 端点与 例 2.2 “JAXB Binding” 中定义的 JAXB 绑定关联。

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:orderQueue"/>
            <to uri="binding:jaxb:activemq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

BindingComponent

您可以做出隐式关联绑定而不是将绑定与端点关联,而不必在 URI 中显示绑定。对于没有隐式绑定的现有端点,实现此目的的最简单方法是使用 BindingComponent 类包装端点。

例如,要将 jaxb 绑定与 activemq 端点关联,您可以定义新的 BindingComponent 实例,如下所示:

<beans ... >
    ...
    <bean id="jaxbmq" class="org.apache.camel.component.binding.BindingComponent">
        <constructor-arg ref="jaxb"/>
        <constructor-arg value="activemq:foo."/>
    </bean>

    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

其中(可选) jaxbmq 的第二个构造器参数定义了 URI 前缀。现在,您可以使用 jaxbmq ID 作为端点 URI 的方案。例如,您可以使用这个绑定组件定义以下路由:

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="jaxbmq:firstQueue"/>
            <to uri="jaxbmq:otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>

前面的路由等同于以下路由,它使用绑定 URI 方法:

<beans ...>
    ...
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:foo.firstQueue"/>
            <to uri="binding:jaxb:activemq:foo.otherQueue"/>
        </route>
    </camelContext>
    ...
</beans>
注意

对于实施自定义 Apache Camel 组件的开发人员,可以通过实施从 org.apache.camel.spi.HasBinding 接口继承的端点类来实现这一点。

BindingComponent constructors

BindingComponent 类支持以下 constructors:

public BindingComponent()
无参数形式。使用属性注入配置绑定组件实例。
public BindingComponent(Binding binding)
将此绑定组件与指定的 Binding 对象关联,并且 绑定
public BindingComponent(Binding binding, String uriPrefix)
将此绑定组件与指定的 Binding 对象、绑定和 URI 前缀关联,uriPrefix。这是最常用的构造器。
public BindingComponent(Binding binding, String uriPrefix, String uriPostfix)
此构造器支持额外的 URI post-fix, uri postfix , 参数,该参数会自动附加到使用此绑定组件定义的任何 URI。

实现自定义绑定

除了 DataFormatBinding 之外,可用于汇总和解包数据格式,您可以实施自己的自定义绑定。定义自定义绑定,如下所示:

  1. 实施 org.apache.camel.Processor 类,对传入到消费者端点的消息执行转换( 元素推断)。
  2. 实施补充 org.apache.camel.Processor 类,对从制作者端点(位于元素中)发出的消息执行反向转换。
  3. 实施 org.apache.camel.spi.Binding 接口,它充当处理器实例的工厂。

绑定接口

例 2.3 “org.apache.camel.spi.Binding 接口” 显示 org.apache.camel.spi.Binding 接口的定义,您必须实现它们来定义自定义绑定。

例 2.3. org.apache.camel.spi.Binding 接口

// Java
package org.apache.camel.spi;

import org.apache.camel.Processor;

/**
 * Represents a <a href="http://camel.apache.org/binding.html">Binding</a> or contract
 * which can be applied to an Endpoint; such as ensuring that a particular
 * <a href="http://camel.apache.org/data-format.html">Data Format</a> is used on messages in and out of an endpoint.
 */
public interface Binding {

    /**
     * Returns a new {@link Processor} which is used by a producer on an endpoint to implement
     * the producer side binding before the message is sent to the underlying endpoint.
     */
    Processor createProduceProcessor();

    /**
     * Returns a new {@link Processor} which is used by a consumer on an endpoint to process the
     * message with the binding before its passed to the endpoint consumer producer.
     */
    Processor createConsumeProcessor();
}

何时使用绑定

当您需要应用相同的转换到许多不同类型的端点时,绑定很有用。