36.3. 使用注释实施类型 Converter
概述
可以通过添加新的 worker 类型转换程序来轻松自定义类型转换机制。本节论述了如何实施 worker 类型转换器以及如何将其与 Apache Camel 集成,以便通过注解类型转换程序程序自动载入它。
如何实施类型转换器
实施注解的转换器类
您可以使用 @Converter
注释来实施自定义类型转换器类。您必须对类本身和要执行 类型转换的静态
方法进行注解。每个转换器方法都采用一个参数,该参数用于定义类型,可以选择使用第二个 Exchange
参数,并且具有定义 要类型的非void 返回值。 类型转换器加载程序使用 Java reflection 来查找注解的方法,并将它们集成到类型转换器机制中。例 36.3 “注解转换器类示例” 显示注解的转换器类示例,用于定义从 java.io.File
转换为 java.io.InputStream
和另一个转换器方法(使用 Exchange 参数)的转换器方法(使用 Exchange
参数)从 byte[]
转换为 String
。
例 36.3. 注解转换器类示例
package com.YourDomain.YourPackageName; import org.apache.camel.Converter; import java.io.*; @Converter public class IOConverter { private IOConverter() { } @Converter public static InputStream toInputStream(File file) throws FileNotFoundException { return new BufferedInputStream(new FileInputStream(file)); } @Converter public static String toString(byte[] data, Exchange exchange) { if (exchange != null) { String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class); if (charsetName != null) { try { return new String(data, charsetName); } catch (UnsupportedEncodingException e) { LOG.warn("Can't convert the byte to String with the charset " + charsetName, e); } } } return new String(data); } }
toInputStream ()
方法负责从 文件类型
到 InputStream
类型执行转换,而 toString ()
方法负责从 byte[]
类型执行转换到 String
[] 类型。
方法名称不重要,可以是您选择的任何内容。重要的是参数类型、返回类型和 @Converter
注释的存在。
创建 TypeConverter 文件
要为自定义转换器启用发现机制(通过注解 类型转换程序加载程序实现),请在以下位置创建一个 TypeConverter
文件:
META-INF/services/org/apache/camel/TypeConverter
TypeConverter
文件必须包含以逗号分隔的类型转换器类的 Fully Qualified Names (FQN)列表。例如,如果您希望类型转换器加载程序来搜索 您的PackageName.
YourClassName 软件包,用于注释的转换器类,TypeConverter
文件应当包含以下内容:
com.PackageName.FooClass
启用发现机制的替代方法是在 TypeConverter
文件中添加软件包名称。例如,TypeConverter
文件应当包含以下内容:
com.PackageName
这会导致软件包扫描程序通过 @Converter
标签的软件包进行扫描。使用 FQN 方法较快,是首选的方法。
软件包类型转换器
类型转换器被打包为 JAR 文件,其中包含自定义类型转换器编译的类和 META-INF
目录。将此 JAR 文件放到您的类路径上,使其可用于您的 Apache Camel 应用程序。
回退转换器方法
除了使用 @Converter
注释定义常规转换器方法外,您还可以选择使用 @FallbackConverter
注释来定义回退转换器方法。只有控制器类型转换器未能在类型 registry 中找到常规转换器方法时,才会尝试回退转换器方法。
常规转换方法和回退转换器方法之间的基本区别在于,定义了常规转换器以在特定类型的对类型之间执行转换(例如,从 字节[]
到 String
),回退转换器可以在 任何类型的 类型之间执行转换。取决于回退转换器方法正文中的代码,可以找出它能够执行的转换。在运行时,如果无法使用常规转换器执行转换,控制器类型转换器会迭代每个可用的回退转换器,直到它找到了可以执行转换的转换。
回退转换器的方法可采用以下形式之一:
// 1. Non-generic form of signature @FallbackConverter public static Object MethodName( Class type, Exchange exchange, Object value, TypeConverterRegistry registry ) // 2. Templating form of signature @FallbackConverter public static <T> T MethodName( Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry )
其中 MethodName 是回退转换器的任意方法名称。
例如,以下代码提取(从文件组件的实现中)显示回退转换器,该转换器可以转换 GenericFile
对象的正文,利用了类型转换器 registry 中已经可用的类型转换器:
package org.apache.camel.component.file; import org.apache.camel.Converter; import org.apache.camel.FallbackConverter; import org.apache.camel.Exchange; import org.apache.camel.TypeConverter; import org.apache.camel.spi.TypeConverterRegistry; @Converter public final class GenericFileConverter { private GenericFileConverter() { // Helper Class } @FallbackConverter public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry) { // use a fallback type converter so we can convert the embedded body if the value is GenericFile if (GenericFile.class.isAssignableFrom(value.getClass())) { GenericFile file = (GenericFile) value; Class from = file.getBody().getClass(); TypeConverter tc = registry.lookup(type, from); if (tc != null) { Object body = file.getBody(); return tc.convertTo(type, exchange, body); } } return null; } ... }