Camel-学习笔记(二)关于camel-file的使用案例

Camel 为使用许多不同的通信技术实现的端点提供开箱即用的支持。下面是 Camel 支持的端点技术的一些示例。

  • JMS 队列。
  • Web 服务。
  • 一个文件(本文样例)。文件可能听起来像是不太可能的终结点类型,直到您意识到在某些系统中,一个应用程序可能会将信息写入文件,而稍后,另一个应用程序可能会读取该文件。
  • FTP 服务器。
  • 电子邮件地址。客户端可以向电子邮件地址发送消息,服务器可以从邮件服务器读取传入邮件。
  • POJO(普通旧 Java 对象)。

使用案例

基于文件的camel的使用案例

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>it.lukegroupId>
    <artifactId>Camel_ProartifactId>
    <version>1.0-SNAPSHOTversion>


    <dependencies>

         <dependency>
             <groupId>org.apache.camelgroupId>
             <artifactId>camel-coreartifactId>
             <version>2.25.1version>
         dependency>

    dependencies>
project>

1.从目录读取并写入另一个目录

from(“file://inputdir/?delete=true”).to(“file://outputdir”)

package it.luke.camel_fileTofile;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

/**
 * @author luke
 * @date 2020/11/70:33
 */
public class CamelFile {
     

    public static void main(String[] args) {
     
        //创建一个CamelContext对象
        CamelContext camelContext = new DefaultCamelContext();
        //定义路由规则
        try {
     
            camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 ?后拼接配置参数(delete=true)写入后删除源文件
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\?delete=true")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\");
                }
            });
            //启动线程
            camelContext.start();
            Thread.sleep( 5000);
            //关闭线程
            camelContext.stop();
        } catch (Exception e) {
     
            e.printStackTrace();
        }
    }
}

Camel-学习笔记(二)关于camel-file的使用案例_第1张图片

Camel-学习笔记(二)关于camel-file的使用案例_第2张图片

2.递归地从目录读取并写入另一个目录

路由:from(“file://inputdir/?recursive=true&delete=true”).to(“file://outputdir”)

camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 ?后拼接配置参数(recursive=true)递归采集目录下的文件
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\?delete=true&recursive=true")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\");
                }
            });

Camel-学习笔记(二)关于camel-file的使用案例_第3张图片

Camel-学习笔记(二)关于camel-file的使用案例_第4张图片

补充:delete=true 虽然可以删除源文件,但是并不能删除源目录

如果仅需要采集文件而不需要目录结构的话,可以在输出路由添加参数?flatten=true

from("file://D:\\Server\\Camel_Pro\\testData\\input\\?delete=true&recursive=true")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\?flatten=true");

Camel-学习笔记(二)关于camel-file的使用案例_第5张图片

便可以得到平铺后的文件

3.从目录读取并处理 JAVA 中的消息

提取目录下的文件的内容,经过处理后,写入到另一个文件中

package it.luke.camel_fileTofile;

import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

/**
 * @author luke
 * @date 2020/11/71:10
 */
public class CamelFileObj {
     
    public static void main(String[] args) {
     

        //创建一个CamelContext对象
        CamelContext camelContext = new DefaultCamelContext();
        //定义路由规则
        try {
     
            camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\").process(new Processor() {
     
                        public void process(Exchange exchange) throws Exception {
     
                            Object body = exchange.getIn().getBody(String.class);
                            System.out.println(body);
                            exchange.getMessage().setBody("我是重新处理过的数据"+body);
                            // do some business logic with the input body
                        }
                    }).to("file://D:\\Server\\Camel_Pro\\testData\\output\\?flatten=true");
                }
            });
            //启动线程
            camelContext.start();
            Thread.sleep( 5000);
            //关闭线程
            camelContext.stop();
        } catch (Exception e) {
     
            e.printStackTrace();
        }
    }
}

Camel-学习笔记(二)关于camel-file的使用案例_第6张图片

Camel-学习笔记(二)关于camel-file的使用案例_第7张图片

可以看到写入内容已经被我们修改了

4.通过相对于最终目标的临时目录写入文件

写入临时目录,然后通过原子操作,将数据直接移动到目的目录,主要是为了防止正在写入时被其它程序异常读取,这样可以保证数据的完整性

to(“file:///var/myapp/finalDirectory?tempPrefix=/…/filesInProgress/”);

camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 ?后拼接配置参数tempPrefix=/../filesInProgress/  将文件的写入操作指向临时目录以作原子转移操作
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\?delete=true&recursive=true")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\?tempPrefix=/../filesInProgress/");
                }
            });

Camel-学习笔记(二)关于camel-file的使用案例_第8张图片

Camel-学习笔记(二)关于camel-file的使用案例_第9张图片

5.对文件名使用表达式

from(“file://inbox?move=backup/ d a t e : n o w : y y y y M M d d / {date:now:yyyyMMdd}/ date:now:yyyyMMdd/{file:name}”).to("…");

注意move参数和delete不能共存

camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 ?后拼接配置参数move=backup/${date:now:yyyyMMdd}/${file:name} 在读取完文件后将文件转移到指定目录
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\?recursive=true&move=backup/${date:now:yyyyMMdd}/${file:name}")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\?tempPrefix=/../filesInProgress/");
                }
            });

move常用来指定文件在哪个时间段完成读取,读取的内容是什么,是问题回溯的一大利器

6.避免重复读取同一文件(幂等使用者)+ 定时调度

from(“file://inbox?idempotent=true”).to("…");

按照一定的规则拒绝重复读取

为了方便观察,这边开启定时任务

添加依赖

		<dependency>
            <groupId>org.apache.camelgroupId>
            <artifactId>camel-quartz2artifactId>
            <version>2.16.2version>
        dependency>
package it.luke.camel_fileTofile;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

/**
 * @author luke
 * @date 2020/11/712:06
 */
public class CamelQuzFile {
     
    public static void main(String[] args) {
     

        //创建一个CamelContext对象
        CamelContext camelContext = new DefaultCamelContext();
        //定义路由规则
        try {
     
            camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //配置定时器quartz2:Demo?cron=1/10 * * * * ?
                    from("quartz2:Demo?cron=1/10 * * * * ?").
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\");
                }
            });
            //启动线程
            camelContext.start();
            synchronized (CamelQuzFile.class) {
     
                CamelQuzFile.class.wait();
            }
        } catch (Exception e) {
     
            e.printStackTrace();
            //关闭线程
            try {
     
                camelContext.stop();
            } catch (Exception e1) {
     
                e1.printStackTrace();
            }
        }

    }
}

没有添加幂等的情况下,往input目录里面添加重复名字的文件是会重复读取写入的

Camel-学习笔记(二)关于camel-file的使用案例_第10张图片

Camel-学习笔记(二)关于camel-file的使用案例_第11张图片

Camel-学习笔记(二)关于camel-file的使用案例_第12张图片

故添加幂等

camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 ?后拼接配置参数idempotent=true幂等文件名,通过判断文件名是否一致,拒绝重复读取
                    from("quartz2:Demo?cron=1/10 * * * * ?").
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\?idempotent=true")
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\");
                }

Camel-学习笔记(二)关于camel-file的使用案例_第13张图片

Camel-学习笔记(二)关于camel-file的使用案例_第14张图片

Camel-学习笔记(二)关于camel-file的使用案例_第15张图片

这边在输入目录同时写入两份内容一样的文件1.log和2.log

Camel-学习笔记(二)关于camel-file的使用案例_第16张图片

调度时间到了之后,发现1.log 内容并没有刷新过来,因为默认的幂等是按照文件的绝对路径的

此外可以通过&idempotentKey= f i l e : n a m e − {file:name}- file:name{file:size}

来指定幂等的key

7.使用过滤器

路由中使用filter可以对传输的数据 进行过滤

 public FilterDefinition filter(@AsPredicate Predicate predicate) {
     
        FilterDefinition filter = new FilterDefinition(predicate);
        this.addOutput(filter);
        return filter;
    }
//new Predicate() 需要传入一个对象,则是一个抽象接口,需要重写matches方法,因为这边只调用一次,所以这边采用匿名内部类的方式
camelContext.addRoutes(new RouteBuilder() {
     
                public void configure() {
     
                    //读取指定目录的文件,写入到指定的输出目录中 
                    //通过filter进行message的过滤
                    from("file://D:\\Server\\Camel_Pro\\testData\\input\\").filter(
                            new Predicate() {
     
                                public boolean matches(Exchange exchange) {
     
                                    String body = exchange.getIn().getBody(String.class);
                                    System.out.println(body.length());
                                    if (body.contains("filter")) {
     
                                        System.out.println(body);
                                        return true;
                                    }
                                    return false;
                                }
                            }
                    )
                            .to("file://D:\\Server\\Camel_Pro\\testData\\output\\");
                }
            });

Camel-学习笔记(二)关于camel-file的使用案例_第17张图片

这边在新建两个测试文件,一个文件内容带有filter字样用于过滤

Camel-学习笔记(二)关于camel-file的使用案例_第18张图片

可以看到只有带有filter的文件进行了路由写入

控制条件可以根据自己的需求进行修改

废话:

个人觉得camel是一个特别适合企业集成使用的技术,提供的高级抽象有点类似SpringJPAData

目的就是将很多不同协议的数据通道,通过以相类似的路由形式表示出来使用

这里只总结了个人觉得比较常用的用法,更多的参数可以参考官网

更多内容参考官网:https://camel.apache.org/components

你可能感兴趣的:(camel,java,大数据)