Spring integration学习总结

Spring integration学习总结

1       基本概念

Spring integration是一个企业应用集成系统。主要通过消息、通道、消息端点等概念完成不同系统之间的集成。

2       主要的功能实体

2.1       消息(Message

消息包括header(头)和payload(负载)

messageheader一般是id,时间戳或者目的地址什么的,比如如果你发的消息是个文件,那么header应该存放文件的名称,消息头可以根据需要修改。Payload就是负载,也就睡消息的主要内容,主要通过这个进行通信。

2.2       消息通道(Message channel

消息传输的通道。分两种,一种是point-to-point点对点的,一种是publish-subscribe发布订阅形式的。如果是点对点的channel,至少会有一个消费者consumer能收到发送的message,另一种订阅发布的channelspring integration试图去用广播的形式发布message给那些订阅者subscriber

主要实现如下:

PublishSubscribeChannel:将消息广播给所有的订阅者。

QueueChannel:可以缓存消息,在缓存消息没有达到上限时,消息发送者将消息发送到该通道后立即返回。如果缓存消息数量达到设定的容量,则消息发送者发送消息后会被阻塞,直到消息队列中有空间为止或者超时。对于消息接收者正好相反,尝试获取消息时,如果队列中有消息会立即返回,如果队列中没有消息则会一直阻塞直到超时(需要设定超时时间,不设定的话一直阻塞)。

PriorityChannel:一个排序队列。默认是根据消息头中的“priority”属性值进行排序,也可以通过实现Comparator>接口的逻辑来进行排序。

RendezvousChannel:类似于QueueChannel,只是容量为0。也就是发送者发送消息时,接受者必须将其接收才会返回,否则一直被阻塞。接受者也是一样。

DirectChannel:用于点对点场景,但实现的是PublishSubscribeChannel接口,因此该通道会将消息直接分发给接收者,和PublishSubscribeChannel的区别就是,接收者只有一个。除此之外,DirectChannel还有一个最重要的特点就是发送和接收双方处于一个线程当中,如下:发送者发送消息->接收者接收消息并触发处理操作->返回。Spring Integration中的缺省的通道就是DirectChannel。例如

ExecutorChannel:用于点对点场景,和DirectChannel的配置相同,但主要的区别是ExecutorChannel将消息分发的操作委派给一个TaskExecutor的实例来进行,因此发送消息时不会进行阻塞。

Scoped Channel:暂不理解。

2.3       消息端点(Message Endpoint

可以对消息进行处理的地方。包括如下的主要构件:

2.3.1       Transformer

可以对消息的内容或者结构进行修改,最常见的是修改消息内容的格式,或者对消息头的内容进行添加、修改和删除。用法如下:

             method="transform" output-channel="outChannel"/>

2.3.2       Filter

决定一个消息是否被过滤掉,只有没有被过滤掉的消息才发送到输出通道上。filter多用于publish subscribe模式中,很多consumer消费者可以收到相同的message并且可以用filter来接收指定类型的消息并将其加工处理。

         ref="exampleObject" method="someBooleanReturningMethod"/>

 

2.3.3       Router

路由器,通常是一个输入通道,多个输出通道。根据消息头或者消息体的内容,决定将消息转发到哪个输出通道上。

2.3.4       Splitter

对应一个输入通道,多个输出通道。Splitter把消息从输入通道上分割发送到它的输出通道上。比如用于把一个复合型的payload负载分割成很多子负载payloads,发送到多个输出通道上。

2.3.5       Aggregator

集合器,和splitter对应。用于把多种message组合成一个单一的message。事实上aggregatorsplitter要复杂一些,因为它需要维持message的状态,决定什么时候提供组合,什么时候超时timeout,甚至可以将一个局部的结果放弃,并发送到一个隔离的channel里。Spring integration提供了一个CompletionStrategy来配置timeout超时,是否在超时的时候发送一个结果并且废弃这个channel(这里应该是说消息废弃这个channel)。Aggregator在聚合时,会将消息头中消息ID相同的消息进行聚合。

             

2.3.6       Service Activator

用来连接应用的接口和message framework消息框架的组件,一个输入的频道input message channel必须被设定,一个service activator的方法被执行并且返回了一个值,那么可以提供一个输出频道output message channel(如果消息提供自己的返回地址,那么这是可选的)。这个规则适用于所有的consumer endpoints。输入从input channelservice activator再到message handler,然后返回output messageservice activatoroutput message channel。归根结底:被继承组件的主要对外接口。

2.3.7       Channel Adapter

连接一个消息通道和其他实体之间的对象。channel adapter也分inbound内绑定和outbound外绑定。

Inbound通道适配:通常的作用是将一个外部系统的资源进行转换,通过消息通道输送到系统中,用于进行后续的处理。

Outbound通道适配:将系统中的资源通过消息通道发送给Outbound通道适配,然后该“Outbound通道适配”将其转换为外部的资源。

举例:的作用,将文件系统中的文件进行读取,将文件对象或者文件内容发送到消息通道中。

的作用,将处理好的文件资源输出到文件系统中。

 

Spring Integration目前支持的常用channel-adapter如下:

File

FTP/FTPS

HTTP

JDBC

SFTP

Mail

XML

等等。

3       使用经验

3.1       重复下载远程服务器上的文件

Spring Integration下载远程服务器可以使用,其工作原理是监控远程服务器上的文件,一旦有新的文件就会首先下载到本地,然后将文件对象装载到channel中。在测试的过程中发现,这两步是各自独立进行的,也就是说,下载部分只下载远程服务器上存在但本地目录不存在的文件,将文件对象装载到channel的操作是监控本地目录中的文件,如果没有装载过就进行处理。有时候远程服务器上的相同文件名的文件是定期更新的,需要客户端定期下载,这种情况下的默认处理就有问题了:

1)          下载一次后,如果本地文件已经存在,就不会重复下载。

2)          即使将本地文件进行删除,此时虽然会下载,但下载到本地后不会将文件对象装载到channel中进行后续的处理。

Spring社区中也没有好的处理办法,这种情况下,可以使用下载到本地后对文件进行改名的方法进行规避,使用方法如下,见红色部分:

        id="sftpInboundAdapter"

        session-factory="sftpSessionFactory"

        remote-directory="/srv/data/stc/crm/"

        local-directory="file:///srv/data/stc/crm/upload"

        local-filename-generator-expression="substring(0,lastIndexOf('.'))

                   + '_' + T(java.lang.System).currentTimeMillis()

                   + substring(lastIndexOf('.'))"

        channel="downloadFileChannel"

        delete-remote-files="true"

        auto-startup="true"

        filter="entryListFilter">

        

进行了上面的配置后,下载下来的文件名会变成原来的文件名中加上了时间戳,这样就规避了上述的问题,如果也许需要还原原来的文件名,可以在进入channel后的后续的处理中再进行处理。

3.2       如何控制inbound-channel-adapter类的对象是否工作

context = new FileSystemXmlApplicationContext("/conf/stc-job.xml");

    SourcePollingChannelAdapter adapter = context.getBean("sftpInboundAdapter", SourcePollingChannelAdapter.class);

    adapter.stop(); //停止工作

    adapter.start(); //开始工作

 

3.3       Spring Integration触发Spring batchjob

Spring Integration的配置如下:

        channel="inputFileChannel" filename-pattern="*.csv">

       

 

   

 

                       output-channel="jobLaunchRequestChannel"

                       ref="fileToJobLaunchRequestAdapter"

                       method="adapt"/>

                      

       

           

       

        stcJob"/>

其中,红色stcJobSpring batchjob名称,需要做如下的配置:

stcJob">

  …….

对于Spring  Job的触发类FileToJobLaunchRequestAdapter,代码如下:

 

public class FileToJobLaunchRequestAdapter implements InitializingBean

{

    private Job job;

    

    public void setJob(Job job)

    {

        this.job = job;

    }

    

    public void afterPropertiesSet() throws Exception

    {

        Assert.notNull(job, "A Job must be provided");

    }

    

    @ServiceActivator

    public JobLaunchRequest adapt(File file) throws NoSuchJobException

    {        

        String fileName = file.getAbsolutePath();

        

        if (!fileName.startsWith("/"))

        {

            fileName = "/" + fileName;

        }

        

        fileName = "file://" + fileName;

        

        String outPutPath = "file:///srv/smartcare/export/";

        

        String outPutFilePath = outPutPath + file.getName();

        

        String outPutTmpFilePath = outPutFilePath;

        

        JobParameters jobParameters = new JobParametersBuilder().addString("input.file.path",

                fileName)

                .addString("output.file.path", outPutTmpFilePath)

                .addString("file.src", outPutTmpFilePath)

                .addString("file.original.name", file.getName())

                .addString("file.dst", outPutFilePath)

                .addLong("time.stamp", System.currentTimeMillis())

                .toJobParameters();

        

        //确保job多次执行时,通过让jobParameters发生变化,从而区分job

        if (job.getJobParametersIncrementer() != null)

        {

            jobParameters = job.getJobParametersIncrementer()

                    .getNext(jobParameters);

        }

        

        return new JobLaunchRequest(job, jobParameters);

        

    }

    

    public void output(File file)

    {

        System.out.println("receive file = " + file.getName() + ", path = "

                + file.getPath());

        return;

    }

    

}


3.4       JAVA代码中发消息给Spring Integrationchannel

Java代码:

Message message = MessageBuilder.withPayload(file).build();

sftpChannel.send(message);

sftpChannelSpring integrationchannel名称。

Spring Integration的配置文件中,做如下的配置:

            session-factory="sftpSessionFactory"

            channel="outFileChannel"

            charset="UTF-8"

            temporary-file-suffix=".uploading"

            remote-directory="/srv"/>

 

其中,sftpChannel的名称等于outFileChannel就可以了。

你可能感兴趣的:(个人总结)