如何动态创建路由配置本身

时间:2019-05-16 16:41:12

标签: spring-boot apache-camel spring-camel camel-http

在我的一个用例中,我将所有路由信息都保存在一个json文件中,我想读取该文件并相应地创建路由。

例如,

如果我在json配置文件中声明了这样的路由

{
  "config": [
    {
      "routeSrcSystem": "System1",
      "routes": [
        {
          "fromRoute": {
            "type": "default",
            "typeValue": "direct:CMStart"
            },  
          "toRoute": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System1/inboundMessage"
            }
        }
      ]
    }
  ]
}

然后,我可以动态创建以下路由。但是,尽管路由定义是动态的,但路由定义不是动态的,因为我使用了一个“从”和“到”定义,但是我动态地传递了该定义的参数。

public class GenerateRouter extends RouteBuilder {

        private RoutesMetadata routesMetadata;

        public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
            super(context);
            this.routesMetadata=routesMetadata;
        }

        @Override
        public void configure() throws Exception {
            from(routesMetadata.getFromRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue());
        }
    }

但是我想动态地进行路由定义。例如,我有这样的路由配置,

{
  "config": [
    {
      "routeSrcSystem": "System1",
      "routes": [
        {
          "fromRoute": {
            "type": "default",
            "typeValue": "direct:CMStart"
            },  
          "toRoute1": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System1/inboundMessage"
            }
         "toRoute2": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System2/inboundMessage"
            }
        }
      ]
    }
  ]
}

然后在我的路线定义中,我需要动态添加一个“至”定义。它只是一个例子。它可能会更加动态。例如,可以更改配置以引入“流程”或“ bean”或“类”定义。因此,根据配置,我们需要确定要创建多少个“ to”以及要创建多少个“ process”等。我可能需要在进行一些验证等之后调用下一个剩余端点,有时我需要调用kafka将消息放入队列。我确实看到了在列表中列出所有路由并执行它的选项,但是我认为在调用下一个端点之前,我们需要具有灵活性来添加过程或/或类定义,并且这必须基于配置。

public class GenerateRouter extends RouteBuilder {

        private RoutesMetadata routesMetadata;

        public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
            super(context);
            this.routesMetadata=routesMetadata;
        }

        @Override
        public void configure() throws Exception {
            from(routesMetadata.getFromRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue());
        }
    }

我看到了一些信息,可以动态定义路由定义本身,并且我正在对此进行研究。但与此同时,我想在此发布此内容以获得专家意见。另外,请建议我是否以正确的方式使用骆驼?因为在我的用例中,我正在考虑在配置文件的基础上动态添加类名称的“ to”定义,以便应用程序开发人员可以在传递给目标之前动态地对其类进行逻辑转换,丰富或操作系统。如果有更好的方法,请告诉我。另外,让我知道XML的工作方式是好方法还是以json格式定义自己的配置文件是创建动态路由的好方法。

我打算读取json文件并动态地将路由器定义创建为字符串。但是我似乎需要在上下文中将此字符串作为定义加载。我想我缺少这部分。

  

.to(“ class:com.xxx.camel.layoutTransform?method = layout()”)

如果我们在xml文件中提供所有这些配置,并且如果骆驼支持使用此文件自动创建路由定义,那么我们也可以考虑使用此选项。

下面是从另一个来源使用XML文件创建路由器定义的一种方法。在XML中,我们定义了路由器信息,并且将此xml视为字符串,并将此字符串转换为路由器定义对象,最后将其添加到上下文中。

<routes
  xmlns=\"http://camel.apache.org/schema/spring\">
  <route>
      <from uri='direct:c'/>
      <to uri='mock:d'/>
  </route>
</routes>
CamelContext context = new DefaultCamelContext(); 
context.setTracing(true); 
String xmlString = "<routes  xmlns=\"http://camel.apache.org/schema/spring\"><route><from uri='direct:c'/><to uri='mock:d'/></route></routes>"; 

InputStream is = new ByteArrayInputStream(xmlString.getBytes()); 
RoutesDefinition routes = context.loadRoutesDefinition(is); 
context.addRouteDefinitions(routes.getRoutes()); 

context.start(); 

ProducerTemplate template = null; 
template = context.createProducerTemplate(); 
template.start(); 
template.sendBody("direct:c", "HelloC"); 
Thread.sleep(10000); 
context.stop();

我想使用java dsl定义作为字符串来做类似的概念。

例如,如果我有以下字符串,那么可以将其转换为路由器定义吗?

  

String dslString =“ from(” direct:starting“)。to(” seda:end“)”;

这是我的用例。有时,我们要调用以下2个http服务

  

from(“ direct:start”)。to(http://localhost:8080/service1).to(“ http://localhost:8080/service2”)

有时我们可能需要调用以下3种服务

  

from(“ direct:start”)。to(http://localhost:8080/service1).to(“ http://localhost:8080/service2”)。to(“ http://localhost:8080/service3”)

有时候,我们需要像下面这样调用service2之前进行转换。

  

from(“ direct:start”)。to(http://localhost:8080/service1).to(“ class:com.xxx.yyy”)。to(“ http://localhost:8080/service2”)。to(“ http://localhost:8080/service3 “)

在偶数驱动的体系结构中,我们将必须为每种事件类型定义一组路由。因此,想法是,如果我们在每种事件类型的表中定义这些路由,则在服务启动时,所有路由都将在上下文中加载并启动。我能够以XML DSL方式执行相同操作,但尝试在Java DSL中执行相同操作。

谢谢!

1 个答案:

答案 0 :(得分:2)

Camel支持以基于XML的特定格式定义有关路由的所有详细信息。 This page具有到该(和其他)DSL的链接。

您肯定可以提出自己的DSL并动态构建路由,但是如果要支持完整的Camel DSL支持的所有功能,则需要进行很多工作。我会怀疑这不是适用于您的任何用例的解决方案。

如果您的路由具有某些模式,则可以创建由某些配置驱动的相当动态的Camel路由构建器。为了具体化,假设您有许多用例都遵循非常相似的模式...例如,来自文件夹中文件的使用者数据,从(例如)10-15个转换菜单中进行一些转换,然后发送输出到许多队列之一。

由于您有各种可能的组合,因此有可能在文件等中配置这些详细信息,然后从中构建一些路由。权衡取舍与其他任何地方都没有什么不同,在其他地方,您必须决定是否只需编写所需的10件事,或者使某些事情变得更复杂但更通用即可。

从本质上讲,您仍将在创建DSL或排序,但更接近您的用例。