首页 > 代码库 > Camel路由构建过程

Camel路由构建过程

   个人认为Camel中最重要的两大块,一是路由的构建过程,二是路由构建完成后的执行过程。
下面就参数前面的Camel示例来说说路由的构建细节。
其实这里说的路由构建其实是构建路由定义,对应Camel中的RouteDefinition类,一个RouteDefinition对象规定了或者说指定了一个消息从哪里产生,中间要经过什么样的处理,最后路由到什么地方。RouteDefinition有点类似java中的Class类,包含的都是一个元信息,外界则是参照这些元信息进行工作。RouteDefinition由RouteBuilder进行构建,再具体点就是调用RouteBuilder的configure()方法,构建完成后再添加到CamelContext中,那么该路由定义就可以运行了。RouteBuilder的configure()方法是一个抽象方法,所以该方法
要由开发者进行实现,其实就是在进行路由定义的构建过程。下面是前面Camel示例中configure()中的代码:

camelContext.addRoutes(new RouteBuilder() {
	@Override
	public void configure() throws Exception {
		this.from("file:H:/temp/in").process(new Processor() {
			@Override
			public void process(Exchange exchange) throws Exception {
				GenericFile<File> gf = exchange.getIn().getBody(GenericFile.class);
				File file = gf.getFile();
				PrintStream ps = new PrintStream(System.out);
				BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
				String line = null;
				while((line=br.readLine())!=null) {
					ps.println(line);
				}
				
				ps.close();
				br.close();
			}
		}).to("file:H:/temp/out");
	}
});

路由定义的起始都是调用RouteBuilder的from方法,from方法有多个重载方法,一种是传入一个uri字符串,另一种是传入一个Endpoint对象,看到这种形式的重载就应该能想到,给定一个uri字符串最终肯定也是要获取一个Endpoint对象的,而在上一篇Camel查找组件方式中讲到Camel要根据uri解析出组件名称,再由组件名称查找出组件,在Camel中的重要概念中知道,组件其实是一个Endpoint工作,其作用就是创建出Endpoint对象的。到这里Camel根据uri字符串获取Endpoint对象这条线应该是通了的。

下面我们去看一个RouteBuilder的from(uri)方法,因为该方法用得最普遍:

public RouteDefinition from(String uri) {
	getRouteCollection().setCamelContext(getContext());
	RouteDefinition answer = getRouteCollection().from(uri);
	configureRoute(answer);
	return answer;
}

首先调用了getRouteCollection()方法,该方法返回一个RoutesDefinition对象,该对象代表的是多个路由定义的集合,因为Camel中可以运行多个路由定义。然后将CamelContext对象设置到RoutesDefinition中,然后调用RoutesDefinition的from(uri)方法:

public RouteDefinition from(String uri) {
	//创建RouteDefinition对象
	RouteDefinition route = createRoute();
	route.from(uri);
	return route(route);
}
protected RouteDefinition createRoute() {
	//创建RouteDefinition对象
    RouteDefinition route = new RouteDefinition();
    ErrorHandlerFactory handler = getErrorHandlerBuilder();
    if (handler != null) {//为RouteDefinition设置错误处理器
        route.setErrorHandlerBuilderIfNull(handler);
    }
    return route;
}

RouteDefinition创建出来后又调用了RouteDefinition的from(uri)方法:

public RouteDefinition from(String uri) {
	//创建一个FromDefinition对象,并将其添加到路由定义的输入当中
    getInputs().add(new FromDefinition(uri));
    //返回当前RouteDefinition对象
    return this;
}

在RouteDefinition的from(uri)方法调用完成后再调用RoutesDefinition的route方法:

public RouteDefinition route(RouteDefinition route) {
    //预处理RouteDefinition,设置一些异常处理器,拦截器等
    RouteDefinitionHelper.prepareRoute(getCamelContext(), route, getOnExceptions(), getIntercepts(), getInterceptFroms(),
            getInterceptSendTos(), getOnCompletions());
    //将预处理好的RouteDefinition添加到RouteDefinition集合当中,这样Camel就知道多了一个路由定义
    getRoutes().add(route);
    //标记该路由定义已处理好
    route.markPrepared();
    //返回当前的RouteDefinition对象
    return route;
}

RoutesDefinition的route方法调用完成后调用configureRoute方法,该方法只是为路由定义了设置了group属性值。
根据上面的分析,RouteBuilder的from方法就要是创建了一个RouteDefinition对象,并在该对象的输入中加入了一个FromDefinition对象,然后将该RouteDefinition对象添加进RoutesDefinition。

接下来调用了RouteDefinition的process方法,该定义定义在ProcessorDefinition类中,RouteDefinition从ProcessorDefinition继承到该方法,注意该方法的返回值为一泛型,该方法接收一个Processor类型参数:

public Type process(Processor processor) {
    ProcessDefinition answer = new ProcessDefinition(processor);
    addOutput(answer);
    //这时的this不是ProcessDefinition对象,而是RouteDefinition对象
    return (Type) this;
}

该方法很简单,创建出一个ProcessDefinition对象并添加进RouteDefinition的输出(outputs)中,最后返回RouteDefinition对象。
接下来调用RouteDefinition的to方法,该方法也是从从ProcessorDefinition继承而来,返回值也为一泛型:

public Type to(String uri) {
    addOutput(new ToDefinition(uri));
    return (Type) this;
}

该方法也很简单,创建一个ToDefinition对象并添加进RouteDefinition的输出(outputs)中。

至此,在这个简单示例中,整个路由定义就构建完成了,其实该路由定义最重要的就是输入与输出,输入与输出都可以有多个,默认情况下,在路由运行后,Camel会依赖调用这些输出处理器并最终将消息路由到指定目的地。

Camel路由构建过程