header 中带有数据格式名称的骆驼自定义编组
camel custom marshalling with dataFormat name in header
我在两个独立的项目中有两条路线:
- 第一条路线是将 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");
}
};
}
}
}
- 第二条路由应该从 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 时请注意范围和并发性。
我的一个同事(感谢他)找到了确定的解决方案:
在交换属性中设置 bean 名称:
exchange.setProperty("myDataFormat", "myDataFormatAutowiredBean");
使用 RecipientList 模式检索 dataFormat bean 和(un)marshal :
routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:marshal"));
routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:unmarshal"));
非常简洁,效果很好。
我在两个独立的项目中有两条路线:
- 第一条路线是将 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");
}
};
}
}
}
- 第二条路由应该从 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 时请注意范围和并发性。
我的一个同事(感谢他)找到了确定的解决方案:
在交换属性中设置 bean 名称: exchange.setProperty("myDataFormat", "myDataFormatAutowiredBean");
使用 RecipientList 模式检索 dataFormat bean 和(un)marshal :
routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:marshal")); routedefinition.recipientList(简单("dataformat:${property.myDataFormat}:unmarshal"));
非常简洁,效果很好。