spring集成 - 如何将分割线聚合成批x?

时间:2018-04-19 09:15:03

标签: spring-boot spring-integration spring-integration-aws

我们需要向kinesis发送事件,并且由于定价,我们计划将记录分批存放到kinesis。

我们读入csv文件,然后使用文件分割器吐出行并将每行转换为json。

因此,在转换为json之后,我们如何将这些行批处理为每批25行,以便我们的kinesis serviceActivator可以发送批处理?

任何例子都会受到赞赏。

public class Main2Activity extends AppCompatActivity {

DBHelper myDb;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.content_main2);

    ListView listView = (ListView) findViewById(R.id.list);
    myDb = new DBHelper(this);

    //populate an ArrayList<String> from the database and then view it
    ArrayList<String> theList = new ArrayList<>();
    Cursor data = myDb.getAllData();
    if(data.getCount() == 0){
        Toast.makeText(this, "There are no contents in this list!",Toast.LENGTH_LONG).show();
    }else{
        while(data.moveToNext()){
            final StringBuffer buffer = new StringBuffer();
            buffer.append("id: " + data.getString(0) + "\n");
            theList.add(data.getString(1));
            ListAdapter listAdapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,theList);
            listView.setAdapter(listAdapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    int i = 0;

                    final StringBuffer buffer = new StringBuffer();
                    Cursor res = myDb.getAllData();
                    while (res.moveToNext()) {


                        if (position == i) {
                            buffer.append("Url: " + res.getString(1) + "\n");
                            buffer.append("Name: " + res.getString(2) + "\n");
                            showMessage("Data", buffer.toString());

                        }
                        i++;
                    }
                    //Toast.makeText(Main2Activity.this,buffer,Toast.LENGTH_LONG).show();

                }
            });
        }
    }
}

public void showMessage(String title,String Message){
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setTitle(title);
    builder.setMessage(Message);
    builder.show();
}
}
编辑:我添加了#34; Artem Bilan&#34;建议并且有效

    <int-file:splitter id="fileLineSplitter"
                       input-channel="fileInputChannel"
                       output-channel="splitterOutputChannel"
                       markers="true" />


<int:transformer id="csvToDataCdrTransformer"
                     ref="dataCdrLineTransformer"
                     method="transform"
                     input-channel="lineOutputChannel"
                     output-channel="dataCdrObjectInputChannel">
    </int:transformer>


    <int:object-to-json-transformer input-channel="dataCdrObjectInputChannel"
                                    output-channel="kinesisSendChannel">
        <int:poller fixed-delay="50"/>
    </int:object-to-json-transformer>

但我收到错误:

  1. 我正在使用markers =&#34; true&#34;所以我们知道文件的结尾,所以我们可以将其重命名为&#34; .done&#34;。

  2. 在分路器和变压器之间增加了一个路由器,它只是路由到&#34; nullChannel&#34;或&#34; fileProcessedChannel&#34;当FileMarker为END时,否则,分割线进入default-output-channel =&#34; lineOutputChannel&#34;

    <int:aggregator input-channel="aggregateChannel"
                    output-channel="toJsonChannel"
                    release-strategy-expression="#this.size() eq 2"
                    expire-groups-upon-completion="true"/>
    
  3. ,路由器代码如下所示

    <int:router ref="fileMarkerCustomRouter" inputchannel="splitterOutputChannel" default-output-channel="lineOutputChannel"/>
    

    但是我收到了这个错误:

     @Override
        protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
            Collection<MessageChannel> targetChannels = new ArrayList<MessageChannel>();
    
            if (isPayloadTypeFileMarker(message)) {
    
                FileSplitter.FileMarker payload = (FileSplitter.FileMarker) message.getPayload();
    
                if (isStartOfFile(payload)) {
    
                    targetChannels.add(nullChannel);
    
                } else if (isEndOfFile(payload)) {
    
                    targetChannels.add(fileProcessedChannel);
                }
            }
            return targetChannels;
        }
    

    有什么想法吗?

1 个答案:

答案 0 :(得分:1)

为此目的,你肯定需要一个<aggregator>release-strategy-expression="25"expire-groups-upon-completion="true",以便在发布一个correlationKey之后为其创建一个新组。

不确定为什么需要markers="true",但如果没有,<int-file:splitter>会填充相应的相关标头。因此,您甚至可以考虑仅依靠默认的拆分和默认聚合。

此外,您应该考虑将聚合器的结果转换为JSON。它会发出List<?>。将整个列表序列化为JSON非常有效。另外,在发送给Kinesis之前,您可能还需要一次转换。

因此,配置的原型应该是这样的:

<int-file:splitter id="fileLineSplitter"
                   input-channel="fileInputChannel"
                   output-channel="splitterOutputChannel"/>

<int:transformer id="csvToDataCdrTransformer"
                 ref="dataCdrLineTransformer"
                 method="transform"
                 input-channel="lineOutputChannel"
                 output-channel="aggregateChannel">
</int:transformer>

<int:aggregator input-channel="aggregateChannel" 
                output-channel="toJsonChannel"
                expire-groups-upon-completion="true" />

<int:object-to-json-transformer input-channel="toJsonChannel"
                                output-channel="kinesisSendChannel"/>

这样整个文件将被视为批处理。您将其拆分,处理每一行,将它们汇总回列表,然后转换为JSON,然后再发送给Kinesis。

从这里开始,我想请您提出一个JIRA来添加ObjectToJsonTransformer.ResultType.BYTES模式,以便更好地利用基于byte[] KinesisMessageHandler的下游组件。