header 中带有数据格式名称的骆驼自定义编组

camel custom marshalling with dataFormat name in header

我在两个独立的项目中有两条路线:

  1. 第一条路线是将 header 的数据格式 bean 名称设置为常量:

setHeader("dataFormatBeanName", constant("myFirstList"))

第一条路线:

public class MyTest {
    @Configuration
    public static class MyTestConfig extends CamelConfiguration {

        @Bean(name = "myFirstList")
        public DataFormat getMyFirstListDataFormat() {
            return new MyFirstListDataFormat();
        }

        @Bean(name = "mySecondList")
        public DataFormat getMySecondListDataFormat() {
            return new MySecondListDataFormat();
        }

        @Bean
        public RouteBuilder route() {
            return new RouteBuilder() {

                @Override
                public void configure() throws Exception {
                    from("direct:testFirstDataFormat").setHeader("dataFormatBeanName", constant("myFirstList")).to("direct:myRoute");
                    from("direct:testSecondDataFormat").setHeader("dataFormatBeanName", constant("mySecondList")).to("direct:myRoute");
                }
            };
        }
    }
}
  1. 第二条路由应该从 header 中检索 bean 名称并将其用作自定义编组器。像 :

custom(header("dataFormatBeanName"))

(不编译)

任何人都知道我应该如何从 header 中获取我的 bean 名称以在自定义方法中使用它?

@Component
public class MyRouteBuilder extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        final RouteDefinition routedefinition = this.from("direct:myRoute");
        routedefinition.marshal().custom(??????????).to("netty4:tcp://{{route.address}}:{{port}}?textline=true&sync=true");
    }

经过几个小时的搜索,找到了以下解决方案:

第一个class没有变化。

第二个 class 使用匿名数据格式,在其中我从 header 检索 bean 名称并在调用其 marshal 方法之前从 camel 上下文获取 spring bean。 AbstractXxxDataFormat class 属于 project2,被 Project1 DataFormat 继承。

    @Override
    public void configure() throws Exception {
        final RouteDefinition routedefinition = this.from("direct:myRoute");
        routedefinition.marshal(new DataFormat() {
            @Override
            public void marshal(final Exchange exchange, final Object graph, final OutputStream stream) throws Exception {
                AbstractXxxDataFormat myDataFormat = (AbstractGoalDataFormat) getContext().getRegistry().lookupByName(exchange.getIn().getHeader("dataFormatBeanName", String.class));
                myDataFormat.marshal(exchange, graph, stream);
            }

            @Override
            public Object unmarshal(final Exchange exchange, final InputStream stream) throws Exception {
                return null;
            }
        });
        routedefinition.to("netty4:tcp://{{route.address}}:{{port}}?textline=true&sync=true");
    }

如果有更好的解决方案,我会很感兴趣。

您是否尝试过 simple("${header.dataFormatBeanName}") 访问 header?

此外,与其首先在 header 中传递格式 bean 名称,不如将每个 .marshal() 调用分解为两个子路径(一个用于 formatBeanA,一个用于 formatBeanB),然后调用适当的子路径而不是首先设置 header?我相信这可能是一种更清洁的方法。

如果你真的需要在路由中将它作为变量获取(而不是在构建器中使用谓词 api),你可以使用内联处理器来提取它:

public class MyRouteBuilder extends RouteBuilder {
    public void configure() throws Exception {
        from("someEndpoint")
        .process(new Processor() {
        public void process(Exchange exchange) throws Exception {
            String beanName = exchange.getHeader("beanNameHeader");
        }
    });
    }
}

但是,在存储提取的 beanName 时请注意范围和并发性。

我的一个同事(感谢他)找到了确定的解决方案:

  1. 在交换属性中设置 bean 名称: exchange.setProperty("myDataFormat", "myDataFormatAutowiredBean");

  2. 使用 RecipientList 模式检索 dataFormat bean 和(un)marshal :

routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:marshal")); routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:unmarshal"));

非常简洁,效果很好。