如何用Camel EIP Splitter跳过CSV表头、转换记录日期并聚合全量行?
解决Camel EIP Splitter处理CSV时跳过表头并聚合的问题
嘿,这个需求其实很好实现!核心思路就是:把CSV按行拆分后,单独保留第一行的表头,只对后面的数据行做日期转换,最后再把表头和处理完的数据行重新聚合在一起。我给你具体的实现方案和代码示例:
完整路由配置示例
先补全你的路由代码,结合Splitter、Choice和自定义聚合策略来实现:
<route id="core.predix.consumer.route" autoStartup="true" > <from id="predixConsumer" ref="predixConsumer" /> <convertBodyTo type="java.lang.String" /> <!-- 按换行符拆分CSV每行,开启流式处理适合大文件,指定自定义聚合策略 --> <split streaming="true" strategyRef="csvAggregationStrategy"> <tokenize token="\n" /> <choice> <!-- 第一行是表头,直接跳过处理,直接进入聚合 --> <when> <simple>${property.CamelSplitIndex} == 0</simple> </when> <!-- 从第二行开始是数据,执行日期转换逻辑 --> <otherwise> <!-- 这里替换成你的日期转换Bean和方法 --> <bean ref="dateConversionHandler" method="convertDateFields" /> <!-- 如果你不想用Bean,也可以直接在路由里写简单转换逻辑,比如: <setBody> <simple>${bean:dateUtils?method=parseDate(${body})}</simple> </setBody> --> </otherwise> </choice> </split> </route> <!-- 配置自定义聚合策略和日期转换Bean --> <bean id="csvAggregationStrategy" class="com.yourpackage.CSVAggregationStrategy" /> <bean id="dateConversionHandler" class="com.yourpackage.DateConversionHandler" />
自定义聚合策略实现
这个聚合策略的作用是把表头放在第一行,然后依次追加处理后的数据行,保证最终输出的CSV格式正确:
import org.apache.camel.AggregationStrategy; import org.apache.camel.Exchange; public class CSVAggregationStrategy implements AggregationStrategy { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (oldExchange == null) { // 第一个Exchange是表头,直接返回作为初始聚合结果 return newExchange; } // 将新的处理后的数据行追加到已有内容后,用换行符分隔 String existingContent = oldExchange.getIn().getBody(String.class); String newContent = newExchange.getIn().getBody(String.class); oldExchange.getIn().setBody(existingContent + "\n" + newContent); return oldExchange; } }
日期转换Bean示例
这里给你一个简单的日期转换逻辑示例,你可以根据自己的CSV字段格式调整:
import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class DateConversionHandler { // 假设CSV每行的第3个字段是需要转换的日期(比如从"yyyyMMdd"转成"yyyy-MM-dd") public String convertDateFields(String csvLine) { String[] fields = csvLine.split(","); if (fields.length >= 3) { // 解析原始日期格式 LocalDate date = LocalDate.parse(fields[2], DateTimeFormatter.ofPattern("yyyyMMdd")); // 转换为目标格式 fields[2] = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); } // 重新拼接成CSV行 return String.join(",", fields); } }
关键注意点
- 流式处理:开启
streaming="true"可以避免把大CSV文件全部加载到内存,适合处理超大文件。 - 拆分索引:
${property.CamelSplitIndex}是Camel自动给每个拆分元素设置的属性,从0开始计数,所以索引0就是CSV的表头行。 - 聚合顺序:默认情况下Splitter是按顺序处理拆分元素的,所以聚合时直接追加就能保证表头在最前面,数据行顺序不变。
- 日期转换灵活性:你可以根据自己的CSV结构,修改
DateConversionHandler里的逻辑,比如处理不同位置的日期字段、不同的日期格式等。
内容的提问来源于stack exchange,提问作者GLMills
相关产品推荐
相关产品推荐

