60.2. 注解


创建的注解允许将不同模型概念映射到 POJO,如下所示:

  • 记录类型(CSV、键值对(如 FIX 消息)、固定 length …​)
  • 链接(到另一个对象中的链接对象)
  • DataField 及其属性(int、type、…​)
  • KeyValuePairField (用于 key = value format,如 FIX 交易消息),
  • 部分(用于标识标头、正文和页脚部分)
  • OneToMany,
  • BindyConverter,
  • FormatFactories

本节将描述它们。

60.2.1. 1.CsvRecord

CsvRecord 注解用于识别模型的根类。它代表一个 record = "CSV 文件的一行",并可链接到几个子模型类。

注解名称记录类型级别

CsvRecord

CSV

参数名称类型必填默认值info

分隔符

字符串

 

用于在令牌中分割记录的分隔符(必需)- 可以是 '、' 或 ';' 或 'anything'。唯一支持的空格字符是标签(\t)。不支持其他空格字符(空格)。这个值被解释为正则表达式。如果要使用在正则表达式中具有特殊含义的符号,如 '|' 符号,则必须屏蔽它,如 '|'。

allowEmptyStream

布尔值

 

false

allowEmptyStream 参数允许调整 CSV 文件的不密集型流。

autospanLine

布尔值

 

false

最后记录跨越其余行(可选)- 如果启用,则最后一列会自动到行尾,例如,如果其注释,则允许行包含所有字符,还包含分隔符。

CRLF

字符串

 

WINDOWS

用于在每个记录(可选)后添加cariage 返回的字符 - 允许定义要使用的 carriage 返回字符。如果您指定了之前列出的三个值,则输入的值(custom)将用作 CRLF 字符。可以使用三个值:WINDOWS、UNIX、MAC 或 custom。

endWithLineBreak

布尔值

 

true

如果 CSV 文件应该以换行符或不结束(可选)结尾,则 endWithlineBreak 参数标志

generateHeaderColumns

布尔值

 

false

generateHeaderColumns 参数允许在 CSV 中添加,生成包含列名称的标头

isOrdered

布尔值

 

false

指明消息是否在输出中排序

name

字符串

  

描述记录的名称(可选)

quote

字符串

 

"

是否使用给定引号字符(可选) marshal 列 - 允许在生成 CSV 时指定字段的引号字符。此注解与模型的根类关联,必须一次声明。

quoting

布尔值

 

false

指定在 marshaling 时是否必须加引号值(可选)

quotingEscaped

布尔值

 

false

指定在引用时是否必须转义值(可选)

removeQuotes

布尔值

 

true

如果 unmarshalling 应该尝试删除每个字段的引号,则 remove quote 参数标记

skipField

布尔值

 

false

skipField 参数将允许跳过 CSV 文件的字段。如果不需要一些字段,可以跳过它们。

skipFirstLine

布尔值

 

false

skipFirstline 参数将允许跳过 CSV 文件的第一行。这个行通常包含列定义

case 1 : separator = ','

用于隔离 CSV 记录中的字段的分隔符是 :

10, J, Pauline, M, XD12345678, Fortis Dynamic 15/15, 2500, USD, 08-01-2009
@CsvRecord( separator = "," )
public Class Order {

}

case 2 : separator = ';'

与上一个情况进行比较,这里的分隔符是 ; 而不是

10; J; Pauline; M; XD12345678; Fortis Dynamic 15/15; 2500; USD; 08-01-2009
@CsvRecord( separator = ";" )
public Class Order {

}

case 3 : separator = '|'

与上一个情况进行比较,这里的分隔符是 | 而不是 ; :

10| J| Pauline| M| XD12345678| Fortis Dynamic 15/15| 2500| USD| 08-01-2009
@CsvRecord( separator = "\\|" )
public Class Order {

}

case 4 : separator = '\",\"'

适用于 Camel 2.8.2 或更早版本

当 CSV 记录解析的字段包含 ,; (也用作分隔符)时,应该找到另一个策略来告知 camel bindy 如何处理此问题单。要使用逗号定义包含数据的字段,您可以使用单引号或双引号作为分隔符(例如 : '10', 'Street 10, NY', 'USA' 或 "10", "Street 10, NY", "USA")。

__

在这种情况下,作为单引号或双引号的行的前和最后一个字符将通过 bindy 删除。

"10","J","Pauline"," M","XD12345678","Fortis Dynamic 15,15","2500","USD","08-01-2009"
@CsvRecord( separator = "\",\"" )
public Class Order {

}

bindy 会自动检测记录是否用单引号或双引号括起来,并在从 CSV 到对象取消编译时自动删除这些引号。因此 ,不要在 分隔符中包含引号,但如下所示:

"10","J","Pauline"," M","XD12345678","Fortis Dynamic 15,15","2500","USD","08-01-2009"
@CsvRecord( separator = "," )
public Class Order {

}

请注意,如果要从对象到 CSV 并使用引号,则需要使用 @CsvRecord 上的 quote 属性来指定要使用的字符,如下所示:

@CsvRecord( separator = ",", quote = "\"" )
public Class Order {

}

问题单 5:分隔符和跳过行

当客户端想要在文件的第一行中时,这个功能值得注意,数据字段的名称:

order id, client id, first name, last name, isin code, instrument name, quantity, currency, date

要告知绑定此第一行必须在解析过程中跳过,然后我们使用属性 :

@CsvRecord(separator = ",", skipFirstLine = true)
public Class Order {

}

case 6 : generateHeaderColumns

要在生成的 CSV 的第一行中添加,在注解中必须将属性 generateHeaderColumns 设置为 true,如下所示:

@CsvRecord( generateHeaderColumns = true )
public Class Order {

}

因此,在 unmarshaling 过程中绑定将生成 CSV,如下所示:

order id, client id, first name, last name, isin code, instrument name, quantity, currency, date
10, J, Pauline, M, XD12345678, Fortis Dynamic 15/15, 2500, USD, 08-01-2009

问题单 7:cariage 返回

如果运行 camel-bindy 的平台不是 Windows,但 Macintosh 或 Unix,您可以更改 crlf 属性,如下所示。三个值可用:WINDOWS、UNIX 或 MAC

@CsvRecord(separator = ",", crlf="MAC")
public Class Order {

}

另外,如果您需要添加不同的行结尾字符,您可以选择使用 crlf 参数指定它。在以下示例中,我们可以使用逗号结尾行,后跟换行符:

@CsvRecord(separator = ",", crlf=",\n")
public Class Order {

}

case 8 : isOrdered

有时,从模型创建 CSV 记录期间遵循的顺序与解析过程中使用的顺序不同。然后,在这种情况下,我们可以使用属性 isOrdered = true 来将这个属性与 DataField 注解的属性 位置 结合使用。

@CsvRecord(isOrdered = true)
public Class Order {

   @DataField(pos = 1, position = 11)
   private int orderNr;

   @DataField(pos = 2, position = 10)
   private String clientNr;

}

__

pos 用于解析文件流,而 位置 则用于生成 CSV。

60.2.3. 3.DataField

DataField 注释定义字段的属性。每个 datafield 都由记录中的位置、类型(字符串、int、date、…​)以及可选的模式来标识。

注解名称记录类型级别

DataField

all

属性

参数名称类型必填默认值info

pos

int

 

在输入记录中数据的位置,必须从 1 开始(必需)。请参阅 position 参数。

校准

字符串

 

R

将文本与右或左处对齐。使用 <tt>R</tt> 或 <tt>L</tt> 的值。

Clip

布尔值

 

false

如果在使用固定长度时超过允许的长度,则指示在字段中清除数据。

columnName

字符串

  

标题栏的名称(可选)。使用属性的名称作为默认值。仅在 CsvRecord 具有 generateHeaderColumns = true时才适用

decimalSeparator

字符串

  

与数字一起使用的十进制 9 月

defaultValue

字符串

  

如果没有设置值,则字段的默认值

delimiter

字符串

  

如果字段具有变量长度,则使用可选分隔符

groupingSeparator

字符串

  

当我们想将/解析分成带有分组(例如 123,456.789 )的数字时,将分号号分组到数字中

impliedDecimalSeparator

布尔值

 

false

指明在指定位置是否表示十进制点

length

int

 

0

如果记录设置为固定长度,则数据块的长度(字符数)

lengthPos

int

 

0

标识记录中为此字段定义预期固定长度的 data 字段

方法

字符串

  

调用在 DataField 上应用此类自定义的方法名称。这必须是 datafield 本身的方法,或者您必须提供类方法的静态完全限定名称,例如:查看 test org.apache.camel.dataformat.bindy.csv.BindySimpleCsvFunctionWithExternalMethodTest.replaceToBar

name

字符串

  

字段的名称(可选)

paddingChar

char

  

如果记录被设置为固定长度,则 char to pad

pattern

字符串

  

Java 格式化器(示例为SimpleDateFormat)的模式将用于转换数据(可选)。如果使用模式,则建议在绑定数据格式上设置区域设置。设置为已知区域设置,如 "us" 或使用 "default" 来使用平台默认区域设置。

position

int

 

0

生成输出消息中的字段位置(从 1 开始)。当 CSV 生成的字段的位置(输出消息)必须与输入位置(可能)进行比较时,必须使用。请参阅 pos 参数。

精度

int

 

0

要创建的 \{@link java.math.BigDecimal} 编号的精度

required

布尔值

 

false

指明字段是否是必需的

舍入

字符串

 

CEILING

用于舍入/scale 定制值 : UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_UP, HALF_DOWN,HALF_EVEN, UNNECESSARY e.g : Number = 123456.789, Precision = 2, Rounding = CEILING Result : 123456.79

timezone

字符串

  

要使用的时区。

trim

布尔值

 

false

指明值是否应修剪

问题单 1:pos

此参数/属性代表 CSV 记录中字段的位置。

position

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @DataField(pos = 5)
    private String isinCode;

}

如本例中看到的那样,位置从 1 开始,但从类顺序中的 5 开始。类客户端中定义了从 24 的数字(请参阅 之后)。

位置继续在另一个模型类中

public class Client {

    @DataField(pos = 2)
    private String clientNr;

    @DataField(pos = 3)
    private String firstName;

    @DataField(pos = 4)
    private String lastName;
}

问题单 2:模式

该模式可用于增强或验证您的数据格式

pattern

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @DataField(pos = 5)
    private String isinCode;

    @DataField(name = "Name", pos = 6)
    private String instrumentName;

    @DataField(pos = 7, precision = 2)
    private BigDecimal amount;

    @DataField(pos = 8)
    private String currency;

    // pattern used during parsing or when the date is created
    @DataField(pos = 9, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 3:精度

当您要定义数字的十进制部分时,精度很有用。

精度

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @Link
    private Client client;

    @DataField(pos = 5)
    private String isinCode;

    @DataField(name = "Name", pos = 6)
    private String instrumentName;

    @DataField(pos = 7, precision = 2)
    private BigDecimal amount;

    @DataField(pos = 8)
    private String currency;

    @DataField(pos = 9, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 4:输出中的位置不同

location 属性将告知绑定如何将字段放在生成的 CSV 记录中。默认情况下,使用的位置对应于通过属性 pos 定义的位置。如果位置不同(这意味着,我们有一个 asymetric 进程与 unmarshaling 的 marshaling 的比较),则我们可以使用 位置 来指示这一点。

下面是一个示例:

位置在输出中有所不同

@CsvRecord(separator = ",", isOrdered = true)
public class Order {

    // Positions of the fields start from 1 and not from 0

    @DataField(pos = 1, position = 11)
    private int orderNr;

    @DataField(pos = 2, position = 10)
    private String clientNr;

    @DataField(pos = 3, position = 9)
    private String firstName;

    @DataField(pos = 4, position = 8)
    private String lastName;

    @DataField(pos = 5, position = 7)
    private String instrumentCode;

    @DataField(pos = 6, position = 6)
    private String instrumentNumber;
}

注释 @DataField 的此属性必须与注解 @CsvRecord 的属性 isOrdered = true 结合使用。

问题单 5:必需

如果字段是必需的,只需使用 所需的 属性设为 true。

必填

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @DataField(pos = 2, required = true)
    private String clientNr;

    @DataField(pos = 3, required = true)
    private String firstName;

    @DataField(pos = 4, required = true)
    private String lastName;
}

如果记录中没有此字段,则解析器将引发一个错误,其中包含以下信息:

Some fields are missing (optional or mandatory), line :

case 6 : trim

如果字段有前导和/或尾随空格,则应在处理前删除它们,只需使用属性 trim set 为 true。

Trim

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1, trim = true)
    private int orderNr;

    @DataField(pos = 2, trim = true)
    private Integer clientNr;

    @DataField(pos = 3, required = true)
    private String firstName;

    @DataField(pos = 4)
    private String lastName;
}

问题单 7:defaultValue

如果没有定义字段,则使用 defaultValue 属性表示的值。

默认值

@CsvRecord(separator = ",")
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @DataField(pos = 2)
    private Integer clientNr;

    @DataField(pos = 3, required = true)
    private String firstName;

    @DataField(pos = 4, defaultValue = "Barin")
    private String lastName;
}

问题单 8 : columnName

仅在 @CsvRecord 带有注解 generateHeaderColumns = true 时指定属性的列名称。

列名称

@CsvRecord(separator = ",", generateHeaderColumns = true)
public class Order {

    @DataField(pos = 1)
    private int orderNr;

    @DataField(pos = 5, columnName = "ISIN")
    private String isinCode;

    @DataField(name = "Name", pos = 6)
    private String instrumentName;
}

此属性仅适用于可选字段。

60.2.4. 4.FixedLengthRecord

FixedLengthRecord 注解用于识别模型的根类。它代表一个 record = "一个文件/消息行,其中包含数据固定长度(字符数)格式,并可链接到几个子模型类。这种格式是特定于位的,因为字段的数据可以与右侧或左处一致。

当数据大小没有完全填写字段长度时,我们可以添加"平板"字符。

注解名称记录类型级别

FixedLengthRecord

FIXED

参数名称类型必填默认值info

countGrapheme

布尔值

 

false

指明如何计算计费

CRLF

字符串

 

WINDOWS

用于在每个记录后(可选)添加cariage 返回的字符。可能的值:WINDOWS、UNIX、MAC 或 custom。这个选项仅在 marshalling 期间使用,unmarshalling 使用系统默认的 JDK 提供行分隔符,除非自定义 eol。

EOL

字符串

  

在未记录时考虑每个记录之后的字符(可选 - default: "",它可帮助使用默认的 JDK 提供行分隔符),除非提供了任何其他值,否则此选项仅在 unmarshalling 时使用,其中 marshalling 使用系统默认提供的行分隔符,除非提供了任何其他值。

footer

 

void

表示此类型的记录后面可以跟随一个页记录(在文件的末尾)

header

 

void

表示此类型的记录可以在文件开头的单个标头记录前面。

ignoreMissingChars

布尔值

 

false

指明是否忽略了太短行

ignoreTrailingChars

布尔值

 

false

表示在未记录/解析时,可以忽略超过最后一个映射文件的字符。此注解与模型的根类关联,必须一次声明。

length

int

 

0

记录的固定长度(字符数)。这意味着,记录始终为使用 \{114paddingChar ()} 的长添加

name

字符串

  

描述记录的名称(可选)

paddingChar

char

  

平板的费用。

skipFooter

布尔值

 

false

配置数据格式,以跳过页脚记录的 marshalling / unmarshalling。在主记录上配置此参数(例如,不是标头或页脚)。

skipHeader

布尔值

 

false

配置数据格式,以跳过标头记录的 marshalling / unmarshalling。在主记录上配置此参数(例如,不是标头或页脚)。

记录可能不是标头/页脚和主固定长度记录。

问题单 1:简单固定长度记录

这个简单示例演示了如何设计模型来解析/格式化固定消息

10A9PaulineMISINXD12345678BUYShare2500.45USD01-08-2009

fixed-simple

@FixedLengthRecord(length=54, paddingChar=' ')
public static class Order {

    @DataField(pos = 1, length=2)
    private int orderNr;

    @DataField(pos = 3, length=2)
    private String clientNr;

    @DataField(pos = 5, length=7)
    private String firstName;

    @DataField(pos = 12, length=1, align="L")
    private String lastName;

    @DataField(pos = 13, length=4)
    private String instrumentCode;

    @DataField(pos = 17, length=10)
    private String instrumentNumber;

    @DataField(pos = 27, length=3)
    private String orderType;

    @DataField(pos = 30, length=5)
    private String instrumentType;

    @DataField(pos = 35, precision = 2, length=7)
    private BigDecimal amount;

    @DataField(pos = 42, length=3)
    private String currency;

    @DataField(pos = 45, length=10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 2:使用校准和 padding修复长度记录

这个更详细的示例演示了如何为字段定义对齐以及如何分配为 '' here padding 字符:

10A9 PaulineM ISINXD12345678BUYShare2500.45USD01-08-2009

fixed-padding-align

@FixedLengthRecord(length=60, paddingChar=' ')
public static class Order {

    @DataField(pos = 1, length=2)
    private int orderNr;

    @DataField(pos = 3, length=2)
    private String clientNr;

    @DataField(pos = 5, length=9)
    private String firstName;

    @DataField(pos = 14, length=5, align="L")   // align text to the LEFT zone of the block
    private String lastName;

    @DataField(pos = 19, length=4)
    private String instrumentCode;

    @DataField(pos = 23, length=10)
    private String instrumentNumber;

    @DataField(pos = 33, length=3)
    private String orderType;

    @DataField(pos = 36, length=5)
    private String instrumentType;

    @DataField(pos = 41, precision = 2, length=7)
    private BigDecimal amount;

    @DataField(pos = 48, length=3)
    private String currency;

    @DataField(pos = 51, length=10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 3:字段 padding

有时,为记录定义的默认 padding不能应用于字段,因为我们有数字格式,其中我们想使用 '0' 而不是 '0' 而不是 '。在这种情况下,您可以在模型中使用 @DataField 上的属性 paddingChar 来设置此值。

10A9 PaulineM ISINXD12345678BUYShare000002500.45USD01-08-2009

fixed-padding-field

@FixedLengthRecord(length = 65, paddingChar = ' ')
public static class Order {

    @DataField(pos = 1, length = 2)
    private int orderNr;

    @DataField(pos = 3, length = 2)
    private String clientNr;

    @DataField(pos = 5, length = 9)
    private String firstName;

    @DataField(pos = 14, length = 5, align = "L")
    private String lastName;

    @DataField(pos = 19, length = 4)
    private String instrumentCode;

    @DataField(pos = 23, length = 10)
    private String instrumentNumber;

    @DataField(pos = 33, length = 3)
    private String orderType;

    @DataField(pos = 36, length = 5)
    private String instrumentType;

    @DataField(pos = 41, precision = 2, length = 12, paddingChar = '0')
    private BigDecimal amount;

    @DataField(pos = 53, length = 3)
    private String currency;

    @DataField(pos = 56, length = 10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 4:使用分隔符修复长度记录

固定长度记录有时在记录中以分隔的内容。firstName 和 lastName 字段使用以下示例中的 ^ 字符分隔:

10A9Pauline^M^ISINXD12345678BUYShare000002500.45USD01-08-2009

固定分隔

@FixedLengthRecord
public static class Order {

    @DataField(pos = 1, length = 2)
    private int orderNr;

    @DataField(pos = 2, length = 2)
    private String clientNr;

    @DataField(pos = 3, delimiter = "^")
    private String firstName;

    @DataField(pos = 4, delimiter = "^")
    private String lastName;

    @DataField(pos = 5, length = 4)
    private String instrumentCode;

    @DataField(pos = 6, length = 10)
    private String instrumentNumber;

    @DataField(pos = 7, length = 3)
    private String orderType;

    @DataField(pos = 8, length = 5)
    private String instrumentType;

    @DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
    private BigDecimal amount;

    @DataField(pos = 10, length = 3)
    private String currency;

    @DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

固定长度记录中的 pos 值可以选择使用正数、顺序值而不是精确列号来定义。

问题单 5:使用记录定义字段长度修复长度记录

有时,一个固定长度记录可能会包含一个字段,该字段定义同一记录中另一个字段的预期长度。在以下示例中,detect Number 字段值 的长度由记录中的 detect NumberLen 字段的值定义。

10A9Pauline^M^ISIN10XD12345678BUYShare000002500.45USD01-08-2009

固定分隔

@FixedLengthRecord
public static class Order {

    @DataField(pos = 1, length = 2)
    private int orderNr;

    @DataField(pos = 2, length = 2)
    private String clientNr;

    @DataField(pos = 3, delimiter = "^")
    private String firstName;

    @DataField(pos = 4, delimiter = "^")
    private String lastName;

    @DataField(pos = 5, length = 4)
    private String instrumentCode;

    @DataField(pos = 6, length = 2, align = "R", paddingChar = '0')
    private int instrumentNumberLen;

    @DataField(pos = 7, lengthPos=6)
    private String instrumentNumber;

    @DataField(pos = 8, length = 3)
    private String orderType;

    @DataField(pos = 9, length = 5)
    private String instrumentType;

    @DataField(pos = 10, precision = 2, length = 12, paddingChar = '0')
    private BigDecimal amount;

    @DataField(pos = 11, length = 3)
    private String currency;

    @DataField(pos = 12, length = 10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

问题单 6:使用标头和页脚修复长度记录

bindy 将发现配置为模型一部分的固定长度标头和页脚记录 - 如果注解类与主 @FixedLengthRecord 类或配置在一个配置的扫描软件包之一中存在。以下文本演示了两个固定长度记录,它们由标头记录和页脚记录阻止。

101-08-2009
10A9 PaulineM ISINXD12345678BUYShare000002500.45USD01-08-2009
10A9 RichN ISINXD12345678BUYShare000002700.45USD01-08-2009
9000000002

fixed-header-and-footer-main-class

@FixedLengthRecord(header = OrderHeader.class, footer = OrderFooter.class)
public class Order {

    @DataField(pos = 1, length = 2)
    private int orderNr;

    @DataField(pos = 2, length = 2)
    private String clientNr;

    @DataField(pos = 3, length = 9)
    private String firstName;

    @DataField(pos = 4, length = 5, align = "L")
    private String lastName;

    @DataField(pos = 5, length = 4)
    private String instrumentCode;

    @DataField(pos = 6, length = 10)
    private String instrumentNumber;

    @DataField(pos = 7, length = 3)
    private String orderType;

    @DataField(pos = 8, length = 5)
    private String instrumentType;

    @DataField(pos = 9, precision = 2, length = 12, paddingChar = '0')
    private BigDecimal amount;

    @DataField(pos = 10, length = 3)
    private String currency;

    @DataField(pos = 11, length = 10, pattern = "dd-MM-yyyy")
    private Date orderDate;
}

@FixedLengthRecord
public  class OrderHeader {
    @DataField(pos = 1, length = 1)
    private int recordType = 1;

    @DataField(pos = 2, length = 10, pattern = "dd-MM-yyyy")
    private Date recordDate;
}

@FixedLengthRecord
public class OrderFooter {

    @DataField(pos = 1, length = 1)
    private int recordType = 9;

    @DataField(pos = 2, length = 9, align = "R", paddingChar = '0')
    private int numberOfRecordsInTheFile;
}

问题单 7:在解析固定长度记录时跳过内容

通常与提供固定长度记录的系统集成,它们包含比目标用例所需信息更多的信息。在这种情况下,可以跳过那些我们不需要的字段的声明和解析。为此,如果下一个声明字段的 pos 值超过最后一个解析字段的光标位置,则 Bindy 将跳过转发到记录中的下一个映射字段。对感兴趣的字段使用绝对 pos 位置(而不是 ordinal 值)会导致 Bindy 在两个字段之间跳过内容。

同样,可能不包括一些字段以外的任何内容是值得关注的。在这种情况下,您可以通过在 @FixedLengthRecord 声明上设置 ignoreTrailingChars 属性来告知 Bindy 来跳过除最后一个映射字段外的所有内容的解析。

@FixedLengthRecord(ignoreTrailingChars = true)
public static class Order {

    @DataField(pos = 1, length = 2)
    private int orderNr;

    @DataField(pos = 3, length = 2)
    private String clientNr;

    // any characters that appear beyond the last mapped field will be ignored

}

60.2.5. 5.消息

Message 注解用于识别模型的类,它们将包含键值对字段。这种类型的格式主要用于电信交换协议消息(FIX)。但是,此注解可用于通过键识别数据的任何其他格式。密钥对值通过分隔符相互分隔,可以是类似标签页的特殊字符(unicode 表示: \u0009)或标题起始(unicode 表示: \u0001)

注意

要使用 FIX 消息,模型必须包含链接到根消息类的标头和 Trailer 类,该类可以是 Order 类。这并不是必须的,但当您将 camel-bindy 与 camel-fix 结合使用时,这是基于快速Fix 项目的修复网关时非常有用。

注解名称记录类型级别

消息

键值对

参数名称类型必填默认值info

keyValuePairSeparator

字符串

 

键值对分隔符用于从其键(必需)中分割值。可以是 '\u0001'、'\u0009'、'Evolution' 或 'anything'。

pairSeparator

字符串

 

用于在令牌中分割键值对的对分隔符(必需)。可以是 '='、';' 或 'anything'。

CRLF

字符串

 

WINDOWS

用于在每个记录后(可选)添加cariage 返回的字符。可能的值 = WINDOWS、UNIX、MAC 或 custom。如果您指定了之前列出的三个值,则输入的值(custom)将用作 CRLF 字符。

isOrdered

布尔值

 

false

指明消息必须在输出中排序。此注解与模型的消息类关联,必须一次声明。

name

字符串

  

描述消息的名称(可选)

type

字符串

 

FIX

type 用于定义消息的类型(如 FIX、EMX、…​)(可选)

version

字符串

 

4.1

version 定义消息的版本(如 4.1、…​)(可选)

case 1 : separator = 'u0001'

用于隔离 FIX 消息中的键值对字段的分隔符是 ASCII 01 字符或 unicode 格式 \u0001。必须再次转义此字符,以避免 java 运行时错误。下面是一个示例:

8=FIX.4.1 9=20 34=1 35=0 49=INVMGR 56=BRKR 1=BE.CHM.001 11=CHM0001-01 22=4 ...

如何使用注解:

FIX - 消息

@Message(keyValuePairSeparator = "=", pairSeparator = "\u0001", type="FIX", version="4.1")
public class Order {

}

查看测试问题单

选项卡等 ASCII 字符 …​ 无法在 WIKI 页面中显示。因此,有一个 camel-bindy 的测试问题单,以查看 FIX 消息看起来如何(https://github.com/apache/camel/blob/main/components/camel-bindy/src/test/data/fix/fix.txt)和 Order,Trailer, Header 类(https://github.com/apache/camel/blob/main/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/model/fix/simple/Order.java)。

60.2.6. 6.KeyValuePairField

KeyValuePairField 注释定义键值对字段的属性。每个 KeyValuePairField 都由标签(= key)及其值关联、类型(字符串、int、date、…​)标识,可选模式,如果需要该字段。

注解名称记录类型级别

KeyValuePairField

关键价值 - FIX

属性

参数名称类型必填默认值info

tag

int

 

标签标识消息中的字段(必需)- 必须是唯一的

impliedDecimalSeparator

布尔值

 

false

<b>Camel 2.11:</b> 指示一个十进制点,代表在指定位置上代表的十进制点

name

字符串

  

字段的名称(可选)

pattern

字符串

  

格式器将用于转换数据的模式(可选)

position

int

 

0

生成的消息中的字段位置 - 当 FIX 消息中的键/标签的位置必须不同

精度

int

 

0

要创建的 BigDecimal 数的精度

required

布尔值

 

false

指明字段是否是必需的

timezone

字符串

  

要使用的时区。

问题单 1:标签

此参数表示消息中字段的键:

FIX 消息 - Tag

@Message(keyValuePairSeparator = "=", pairSeparator = "\u0001", type="FIX", version="4.1")
public class Order {

    @Link Header header;

    @Link Trailer trailer;

    @KeyValuePairField(tag = 1) // Client reference
    private String Account;

    @KeyValuePairField(tag = 11) // Order reference
    private String ClOrdId;

    @KeyValuePairField(tag = 22) // Fund ID type (Sedol, ISIN, ...)
    private String IDSource;

    @KeyValuePairField(tag = 48) // Fund code
    private String SecurityId;

    @KeyValuePairField(tag = 54) // Movement type ( 1 = Buy, 2 = sell)
    private String Side;

    @KeyValuePairField(tag = 58) // Free text
    private String Text;
}

问题单 2: 输出中的不同位置

如果我们放入 FIX 消息的 tag/keys 必须根据预定义的顺序进行排序,则使用注解 @KeyValuePairField 的属性 位置

FIX message - Tag - sort

@Message(keyValuePairSeparator = "=", pairSeparator = "\\u0001", type = "FIX", version = "4.1", isOrdered = true)
public class Order {

    @Link Header header;

    @Link Trailer trailer;

    @KeyValuePairField(tag = 1, position = 1) // Client reference
    private String account;

    @KeyValuePairField(tag = 11, position = 3) // Order reference
    private String clOrdId;
}

60.2.7. 7.部分

在固定长度记录的 FIX 消息中,通常以信息 : header, body 和 部分表示不同部分。注释 @Section 的目的是告知绑定模型的类代表标头(= section 1)、正文(= section 2)和页脚(= section 3)

此注解只有一个属性/参数。

注解名称记录类型级别

部分

FIX

参数名称类型必填默认值info

number

int

 

部分的数量

问题单 1:部分

header 部分的定义:

FIX message - Section - Header

@Section(number = 1)
public class Header {

    @KeyValuePairField(tag = 8, position = 1) // Message Header
    private String beginString;

    @KeyValuePairField(tag = 9, position = 2) // Checksum
    private int bodyLength;
}

body 部分的定义:

FIX message - Section - Body

@Section(number = 2)
@Message(keyValuePairSeparator = "=", pairSeparator = "\\u0001", type = "FIX", version = "4.1", isOrdered = true)
public class Order {

    @Link Header header;

    @Link Trailer trailer;

    @KeyValuePairField(tag = 1, position = 1) // Client reference
    private String account;

    @KeyValuePairField(tag = 11, position = 3) // Order reference
    private String clOrdId;

footer 部分的定义:

FIX 消息 - 第 - Footer

@Section(number = 3)
public class Trailer {

    @KeyValuePairField(tag = 10, position = 1)
    // CheckSum
    private int checkSum;

    public int getCheckSum() {
        return checkSum;
    }

60.2.8. 8.OneToMany

注解 @OneToMany 的目的是允许使用 List<?& gt; 字段定义 POJO 类或包含重复组的记录。

注意

一个ToMany
的限制会小心,到许多绑定者的限制不允许处理在多个层次结构级别上定义的重复副本。

在以下情况下,关系 oneToMany WORKS:

  • 读取包含重复组的 FIX 消息(= 标签/密钥组)
  • 使用重复数据生成 CSV
注解名称记录类型级别

OneToMany

all

属性

参数名称类型必填默认值info

mappedTo

字符串

  

与 Class> 的 List<Type 类型关联的类名称

问题单 1:使用重复数据生成 CSV

以下是我们需要的 CSV 输出:

Claus,Ibsen,Camel in Action 1,2010,35
Claus,Ibsen,Camel in Action 2,2012,35
Claus,Ibsen,Camel in Action 3,2013,35
Claus,Ibsen,Camel in Action 4,2014,35
注意

重复数据涉及本书的标题及其发布日期,而第一个、姓氏和年龄是通用的,用于建模这一点的类。Author 类包含书签列表。

使用重复数据生成 CSV

@CsvRecord(separator=",")
public class Author {

    @DataField(pos = 1)
    private String firstName;

    @DataField(pos = 2)
    private String lastName;

    @OneToMany
    private List<Book> books;

    @DataField(pos = 5)
    private String Age;
}

public class Book {

    @DataField(pos = 3)
    private String title;

    @DataField(pos = 4)
    private String year;
}

问题单 2:读取包含标签/密钥组的 FIX 消息

以下是在我们的模型中处理的消息:

8=FIX 4.19=2034=135=049=INVMGR56=BRKR
1=BE.CHM.00111=CHM0001-0158=this is a camel - bindy test
22=448=BE000124567854=1
22=548=BE000987654354=2
22=648=BE000999999954=3
10=220

标签 22、48 和 54 会被重复。

和代码:

读取包含标签/密钥组的 FIX 消息

public class Order {

    @Link Header header;

    @Link Trailer trailer;

    @KeyValuePairField(tag = 1) // Client reference
    private String account;

    @KeyValuePairField(tag = 11) // Order reference
    private String clOrdId;

    @KeyValuePairField(tag = 58) // Free text
    private String text;

    @OneToMany(mappedTo = "org.apache.camel.dataformat.bindy.model.fix.complex.onetomany.Security")
    List<Security> securities;
}

public class Security {

    @KeyValuePairField(tag = 22) // Fund ID type (Sedol, ISIN, ...)
    private String idSource;

    @KeyValuePairField(tag = 48) // Fund code
    private String securityCode;

    @KeyValuePairField(tag = 54) // Movement type ( 1 = Buy, 2 = sell)
    private String side;
}

60.2.9. 9.BindyConverter

注释 @BindyConverter 的目的是定义一个在字段级别使用的转换器。提供的类必须实施 Format 接口。

@FixedLengthRecord(length = 10, paddingChar = ' ')
public static class DataModel {
    @DataField(pos =  1, length = 10, trim = true)
    @BindyConverter(CustomConverter.class)
    public String field1;
}

public static class CustomConverter implements Format<String> {
    @Override
    public String format(String object) throws Exception {
        return (new StringBuilder(object)).reverse().toString();
    }

    @Override
    public String parse(String string) throws Exception {
        return (new StringBuilder(string)).reverse().toString();
    }
}

60.2.10. 10.FormatFactories

注释 @FormatFactories 的目的是在记录级别定义一组转换器。提供的类必须实施 FormatFactoryInterface 接口。

@CsvRecord(separator = ",")
@FormatFactories({OrderNumberFormatFactory.class})
public static class Order {

    @DataField(pos = 1)
    private OrderNumber orderNr;

    @DataField(pos = 2)
    private String firstName;
}

public static class OrderNumber {
    private int orderNr;

    public static OrderNumber ofString(String orderNumber) {
        OrderNumber result = new OrderNumber();
        result.orderNr = Integer.valueOf(orderNumber);
        return result;
    }
}

public static class OrderNumberFormatFactory extends AbstractFormatFactory {

    {
        supportedClasses.add(OrderNumber.class);
    }

    @Override
    public Format<?> build(FormattingOptions formattingOptions) {
        return new Format<OrderNumber>() {
            @Override
            public String format(OrderNumber object) throws Exception {
                return String.valueOf(object.orderNr);
            }

            @Override
            public OrderNumber parse(String string) throws Exception {
                return OrderNumber.ofString(string);
            }
        };
    }
}
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.