架构

路由配置

师成师成· 更新于 2026-09-28· 阅读 24 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

用户手册

路由配置

Camel 3.12 引入了路由配置,用于将配置与路由分离。这可用于为一组路由配置不同错误处理等场景。在之前的 Camel 版本中,这样做比较繁琐,因为你要么必须把相同的配置复制到一组路由上,要么只能依赖全局错误处理配置。

现在你可以配置多个路由配置,然后在每条路由上指定使用哪一种配置(可以按 id、通配符和正则表达式进行匹配)。

所有 DSL 都支持路由配置,因此可用于:Java、XML、Groovy 等。

在路由配置中,你可以为以下内容设置通用策略:

Java DSL 中的路由配置构建器

在 Java DSL 中,你可以使用 RouteConfigurationBuilder 来指定配置,如下所示。该构建器与 RouteBuilder 类似,因此其用法也相似。

public class MyJavaErrorHandler extends RouteConfigurationBuilder {

    @Override
    public void configuration() throws Exception {
        routeConfiguration("javaError")
            .onException(Exception.class).handled(true)
            .log("Java WARN: ${exception.message}");
    }
}
RouteConfigurationBuilder 使用 configuration 方法来编写配置代码。这是有意为之,为了避免与常规 Java DSL 中 RouteBuilder 用来编写 Camel 路由的 configure 方法相混淆。

在上面的示例中,只有一个被赋予了 ID javaError 的路由配置。通过这个 ID,我们可以在之后指定哪些路由使用该配置时引用它。

这是一个基础配置,只负责捕获并处理所有异常,然后记录一条 WARN 级别的日志消息。

将路由配置分配给路由

要在路由中使用该配置,可以通过 routeConfigurationId 进行分配,如下所示:

仅限 Java:使用 routeConfigurationId 的 RouteBuilder

public class MyJavaRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer:java?period=2s")
            // refer to the route configuration by the id to use for this route
            .routeConfigurationId("javaError")
            .setBody(method(MyJavaRouteBuilder.class, "randomNumber"))
            .log("Random number ${body}")
            .filter(simple("${body} < 30"))
                .throwException(new IllegalArgumentException("The number is too low"));
    }

    public static int randomNumber() {
        return new Random().nextInt(100);
    }
}

在 routeConfigurationId 中,要使用的配置通过 ID 指定,例如 javaError。

可以指定多个配置(以逗号分隔),例如:

.routeConfigurationId("javaError,myAudit")

路由配置支持以下匹配方式:

  • 精确 ID 名称。这就是我们在上面看到的示例。
  • 通配符
  • 正则表达式。

通配符是以 * 结尾的文本。当配置 ID 以该指定文本开头、其后跟任意字符时,即视为匹配。例如,你可以这样写:

.routeConfigurationId("java*,myAudit")

这里我们在 java* 中使用了通配符,这意味着任何以 java 开头的 ID 所对应的配置都会匹配。

按正则表达式匹配与按通配符匹配的方式类似,只是将通配符替换为正则表达式。

.routeConfigurationId(".*error.*")

此处我们要匹配 ID 中包含 error 的所有配置。

向 CamelContext 添加路由配置

由于 RouteConfigurationBuilder 本身也是一个 RouteBuilder,因此添加路由配置的方式与 RouteBuilder 相同,例如使用 CamelContext 上的 API

CamelContext context = ...
// add the route configuration
context.addRoutes(new MyJavaErrorHandler());
// add the regular route
context.addRoutes(new MyJavaRouteBuilder());

如果你使用 Spring Boot,那么你的 Camel 路由和路由配置可以通过 Spring Boot 的包扫描自动发现。这需要在类上添加 @Component 注解。

更多内容请参阅这个 Spring Boot 示例:路由配置示例。

使用 Endpoint DSL 的路由配置

Endpoint DSL 也可用于路由配置。这需要将 camel-endpointdsl JAR 添加到类路径中,然后使用 org.apache.camel.builder.endpoint.EndpointRouteConfigurationBuilder,它为 Camel 端点提供了类型安全的 DSL。

默认路由配置

路由配置要么被赋予一个显式的唯一 ID,要么是无名的。无名配置将作为默认/回退配置,用于那些未被显式分配路由配置的路由。

假设你有一个无名配置和另一个名为 retryError 的配置:

纯 Java:RouteConfigurationBuilder 类定义

public class MyJavaErrorHandler extends RouteConfigurationBuilder {

    @Override
    public void configuration() throws Exception {
        routeConfiguration()
            .onException(Exception.class).handled(true)
            .log("WARN: ${exception.message}");

        routeConfiguration("retryError")
            .onException(Exception.class).maximumRedeliveries(5);
    }
}

以及以下两条路由:

  • Java
  • XML
  • YAML
   from("file:cheese").routeId("cheese")
        .to("kafka:cheese");

   from("file:beer").routeId("beer")
        .routeConfigurationId("retryError")
        .to("jms:beer");
<route id="cheese">
    <from uri="file:cheese"/>
    <to uri="kafka:cheese"/>
</route>

<route id="beer" routeConfigurationId="retryError">
    <from uri="file:beer"/>
    <to uri="jms:beer"/>
</route>
- route:
    id: cheese
    from:
      uri: file:cheese
      steps:
        - to:
            uri: kafka:cheese

- route:
    id: beer
    routeConfigurationId: retryError
    from:
      uri: file:beer
      steps:
        - to:
            uri: jms:beer

在上面的示例中,cheese 路由没有分配任何路由配置,因此该路由将使用默认配置,在发生异常时会记录一条警告日志。

而 beer 路由分配了名为 retryError 的路由配置,该配置在发生异常时最多会重试五次,如果仍然出错,则会失败并回滚。

如果添加更多路由,并且这些路由也需要在出错时进行重试,那么也可以为它们分配 retryError 配置。

带有错误处理器的路由配置

每个路由配置还可以配置特定的错误处理器,如下所示:

public class MyJavaErrorHandler extends RouteConfigurationBuilder {

    @Override
    public void configuration() throws Exception {
        routeConfiguration()
            .errorHandler(deadLetterChannel("mock:dead"));

        routeConfiguration("retryError")
            .onException(Exception.class).maximumRedeliveries(5);
    }
}

在上面的示例中,nameless 配置带有一个包含死信队列的错误处理器。而 id 为 retryError 的路由配置没有错误处理器,它将尝试对失败的消息重试最多五次,然后放弃(耗尽)。由于该路由配置没有分配任何错误处理器,Camel 将使用默认的错误处理器。

定义了本地错误处理器的路由,将始终使用该错误处理器,而不是使用路由配置中的错误处理器。一个路由只能有一个错误处理器。

XML 中的路由配置

使用 XML DSL 时,你可以在 XML 文件中编写路由配置,如下所示:

<routeConfiguration id="xmlError">
    <onException>
        <exception>java.lang.Exception</exception>
        <handled><constant>true</constant></handled>
        <log message="XML WARN: ${exception.message}"/>
    </onException>
</routeConfiguration>

而在 XML 路由中,你可以指定要使用哪些配置:

<route routeConfigurationId="xmlError">
    <from uri="timer:xml?period=5s"/>
    <log message="I am XML"/>
    <throwException exceptionType="java.lang.Exception" message="Some kind of XML error"/>
</route>

在此示例中,该路由通过精确 ID 被指派了 xmlError 路由配置。

YAML 中的路由配置

使用 YAML DSL 时,你可以按如下所示在 YAML 文件中编写路由配置:

- routeConfiguration:
    id: "yamlError"
    onException:
    - onException:
        handled:
          constant: "true"
        exception:
          - "java.lang.Exception"
        steps:
          - log:
              message: "YAML WARN ${exception.message}"

在 YAML 路由中,你可以指定要使用哪些配置:

- route:
    # refer to the route configuration by the id to use for this route
    routeConfigurationId: "yamlError"
    from:
      uri: timer:yaml
      parameters:
        period: 3s
      steps:
        - setBody:
            expression:
              simple:
                expression: "Timer fired ${header.CamelTimerCounter} times"
        - to:
            uri: "log:yaml"
            parameters:
              showBodyType: false
              showExchangePattern: false
        - throwException:
            exceptionType: "java.lang.IllegalArgumentException"
            message: "Error from yaml"

在此示例中,该路由通过精确 ID 被分配了 yamlError 路由配置。

混合使用 DSL

路由和路由配置不必使用同一种语言。例如,你可以用 Java 编写路由配置,然后使用 YAML DSL 编写路由,它们可以协同工作。

经典 Spring XML 中的路由配置

当配合 camel-spring-xml 使用 XML DSL 时,你可以在单独的 XML 文件中,通过 <routeConfigurationContext> 片段编写路由配置,如下所示:

<routeConfigurationContext id="myConf" xmlns="http://camel.apache.org/schema/spring">
    <routeConfiguration id="xmlError">
        <onException>
            <exception>java.lang.Exception</exception>
            <handled><constant>true</constant></handled>
            <log message="XML WARN: ${exception.message}"/>
        </onException>
    </routeConfiguration>
</routeConfigurationContext>

然后在 <camelContext> 中,你可以通过这些 XML 片段的 id 来引用它们:

<camelContext id="myCamel" xmlns="http://camel.apache.org/schema/spring">

    <!-- refer to the ID on the context that has the route configurations (see above) -->
    <routeConfigurationContextRef ref="myConf"/>

    <!-- routes can then assign which configuration to use -->
    <route routeConfigurationId="xmlError">
        <from uri="timer:xml?period=5s"/>
        <log message="I am XML"/>
        <throwException exceptionType="java.lang.Exception" message="Some kind of XML error"/>
    </route>
</camelContext>

在此示例中,路由通过确切的 ID 被分配了 xmlError 路由配置。

将路由配置打包为可复用的 JAR

你可以将通用的路由配置打包到 JAR 中,然后通过将这些 JAR 作为依赖添加到类路径(例如 Maven 的 pom.xml 文件中)来与你的 Camel 应用程序一起使用。

例如,这使得在你的多个 Camel 应用程序之间采用通用做法成为可能。

日志摘要

如果你设置 startup-summary-level=verbose,Camel 将为每条路由记录它们被分配了哪些路由配置。

该选项可以通过 Java API 配置,也可以在 application.properties 中配置,适用于运行在 Spring Boot、Quarkus 上的 Camel,以及通过 camel-main 运行的独立 Camel。

  • Java
  • Application Properties
camelContext.setStartupSummaryLevel(StartupSummaryLevel.Verbose);

例如使用 Spring Boot、Quarkus 或 Camel Standalone。

camel.main.startup-summary-level = verbose

路由前置条件

路由配置可以根据用 Simple 语言表达的测试结果来决定是否包含,该测试只在初始化阶段求值一次。

在下面的示例中,只有当参数 activate 被设置为 true 时,才会包含该路由配置。

  • Java
  • XML
  • YAML
routeConfiguration().precondition("{{activate}}")
    .onException(IllegalArgumentException.class)
    .handled(true)
    .log("WARN: ${exception.message}");
<routeConfiguration precondition="{{activate}}">
    <onException>
        <exception>java.lang.IllegalArgumentException</exception>
        <handled>
            <constant>true</constant>
        </handled>
        <log message="XML WARN: ${exception.message}"/>
    </onException>
</routeConfiguration>
- routeConfiguration:
    precondition: "{{activate}}"
    onException:
    - onException:
        exception:
          - "java.lang.IllegalArgumentException"
        handled:
          constant: "true"
        steps:
          - log:
              message: "YAML WARN ${exception.message}"

更多信息

参见以下示例:

评论

登录后参与评论

正在加载评论…