Camel 为使用许多不同的通信技术实现的端点提供开箱即用的支持。下面是 Camel 支持的端点技术的一些示例。
基于文件的camel的使用案例
<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>
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();
}
}
}
路由: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");
便可以得到平铺后的文件
提取目录下的文件的内容,经过处理后,写入到另一个文件中
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();
}
}
}
可以看到写入内容已经被我们修改了
写入临时目录,然后通过原子操作,将数据直接移动到目的目录,主要是为了防止正在写入时被其它程序异常读取,这样可以保证数据的完整性
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/");
}
});
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常用来指定文件在哪个时间段完成读取,读取的内容是什么,是问题回溯的一大利器
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目录里面添加重复名字的文件是会重复读取写入的
故添加幂等
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
路由中使用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