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

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

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

使用案例

基于文件的camel的使用案例

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>it.luke</groupId>
    <artifactId>Camel_Pro</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>

         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-core</artifactId>
             <version>2.25.1</version>
         </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();
        }
    }
}

在这里插入图片描述

在这里插入图片描述

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\\");
                }
            });

在这里插入图片描述

在这里插入图片描述

补充: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");

在这里插入图片描述

便可以得到平铺后的文件

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();
        }
    }
}

在这里插入图片描述

在这里插入图片描述

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

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/");
                }
            });

在这里插入图片描述

在这里插入图片描述

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.camel</groupId>
            <artifactId>camel-quartz2</artifactId>
            <version>2.16.2</version>
        </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目录里面添加重复名字的文件是会重复读取写入的

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

故添加幂等

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\\");
                }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

调度时间到了之后,发现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\\");
                }
            });

在这里插入图片描述

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

在这里插入图片描述

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

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

废话:

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

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

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

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

Camel-iec60870 是一个Java库,它实现了IEC 60870-5-101/104协议,这个协议主要用于电力系统的自动化控制和监控。IEC 60870-5是国际电工委员会(IEC)制定的关于远程控制和监视电力系统设备的标准之一。Camel-iec60870库使得开发者可以更容易地在Java应用程序中实现这个协议,用于创建连接、发送和接收数据,以及处理各种事件。 使用这个库的示例可以按照以下步骤进行: 1. 添加依赖:首先需要在你的Java项目中添加Camel-iec60870的依赖。如果你使用Maven作为构建工具,可以添加相应的maven依赖到你的`pom.xml`文件中。 2. 创建连接:使用库提供的API创建到远程设备的连接。通常需要指定连接的参数,如IP地址、端口、站地址等。 3. 发送和接收数据:一旦连接建立,就可以使用库提供的方法来发送控制命令到远程设备,以及接收来自远程设备的状态和数据。 4. 处理事件:在连接过程中,可能需要处理各种事件,如断线重连、数据接收事件等,这需要编写相应的事件处理代码。 下面是一个简单的示例代码框架,展示了如何使用Camel-iec60870库: ```java import org.apache.camel.component.iec60870.Iec60870Component; import org.apache.camel.component.iec60870.Iec60870Endpoint; import org.apache.camel.CamelContext; public class Iec60870Example { public static void main(String[] args) throws Exception { // 创建CamelContext CamelContext camelContext = new DefaultCamelContext(); // 创建IEC 60870组件 Iec60870Component iec60870Component = new Iec60870Component(); iec60870Component.setHost("127.0.0.1"); // 设置连接的IP地址 iec60870Component.setPort(2404); // 设置端口号 // ... 其他配置 // 将组件添加到CamelContext camelContext.addComponent("iec60870", iec60870Component); // 创建路由 String fromEndpointUri = "iec60870://127.0.0.1:2404?..."; // 构建输入端点URI String toEndpointUri = "..."; // 输出端点URI // 构建并启动路由 RouteBuilder builder = new RouteBuilder() { @Override public void configure() { from(fromEndpointUri) .to(toEndpointUri); } }; camelContext.addRoutes(builder); camelContext.start(); // ... 进行连接、发送和接收数据的操作 // 关闭CamelContext,结束程序 camelContext.stop(); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值