46.7. 例子
46.7.1. 使用 Request-Reply 和序列化对象有效负载的 UDP Netty 端点 复制链接链接已复制到粘贴板!
请注意,默认不允许对象序列化,因此必须配置解码器。
@BindToRegistry("decoder")
public ChannelHandler getDecoder() throws Exception {
return new DefaultChannelHandlerFactory() {
@Override
public ChannelHandler newChannelHandler() {
return new DatagramPacketObjectDecoder(ClassResolvers.weakCachingResolver(null));
}
};
}
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("netty:udp://0.0.0.0:5155?sync=true&decoders=#decoder")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Poetry poetry = (Poetry) exchange.getIn().getBody();
// Process poetry in some way
exchange.getOut().setBody("Message received);
}
}
}
};
46.7.2. 使用单向通信基于 TCP 的 Netty 使用者端点 复制链接链接已复制到粘贴板!
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("netty:tcp://0.0.0.0:5150")
.to("mock:result");
}
};
46.7.3. 使用 Request-Reply 通信的基于 SSL/TCP 的 Netty 使用者端点 复制链接链接已复制到粘贴板!
使用 JSSE 配置工具
Netty 组件通过 Camel JSSE 配置实用程序支持 SSL/TLS 配置。这个工具可显著减少您需要编写的组件特定代码数量,并在端点和组件级别进行配置。以下示例演示了如何将 实用程序与 Netty 组件一起使用。
组件的编程配置
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("/users/home/server/keystore.jks");
ksp.setPassword("keystorePassword");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("keyPassword");
SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);
NettyComponent nettyComponent = getContext().getComponent("netty", NettyComponent.class);
nettyComponent.setSslContextParameters(scp);
基于 Spring DSL 的端点配置
...
<camel:sslContextParameters
id="sslContextParameters">
<camel:keyManagers
keyPassword="keyPassword">
<camel:keyStore
resource="/users/home/server/keystore.jks"
password="keystorePassword"/>
</camel:keyManagers>
</camel:sslContextParameters>...
...
<to uri="netty:tcp://0.0.0.0:5150?sync=true&ssl=true&sslContextParameters=#sslContextParameters"/>
...
在 Jetty 组件中使用基本 SSL/TLS 配置
Registry registry = context.getRegistry();
registry.bind("password", "changeit");
registry.bind("ksf", new File("src/test/resources/keystore.jks"));
registry.bind("tsf", new File("src/test/resources/keystore.jks"));
context.addRoutes(new RouteBuilder() {
public void configure() {
String netty_ssl_endpoint =
"netty:tcp://0.0.0.0:5150?sync=true&ssl=true&passphrase=#password"
+ "&keyStoreFile=#ksf&trustStoreFile=#tsf";
String return_string =
"When You Go Home, Tell Them Of Us And Say,"
+ "For Your Tomorrow, We Gave Our Today.";
from(netty_ssl_endpoint)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(return_string);
}
}
}
});
获取 SSLSession 和客户端证书的访问权限
如果您需要获取客户端证书的详细信息,您可以访问 javax.net.ssl.SSLSession。当 ssl=true 时,Netty 组件会将 SSLSession 存储为 Camel Message 上的标头,如下所示:
SSLSession session = exchange.getIn().getHeader(NettyConstants.NETTY_SSL_SESSION, SSLSession.class);
// get the first certificate which is client certificate
javax.security.cert.X509Certificate cert = session.getPeerCertificateChain()[0];
Principal principal = cert.getSubjectDN();
请记住,设置 needClientAuth=true 以验证客户端,否则 SSLSession 无法访问客户端证书的信息,您可以得到 javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated。如果客户端证书过期或无效等,您可能还会获得此异常。
选项 sslClientCertHeaders 可以设置为 true,然后使用具有客户端证书详情的标头增强 Camel 消息。例如,主题名称在标头 CamelNettySSLClientCertSubjectName 中可用。
46.7.4. 使用多个代码 复制链接链接已复制到粘贴板!
在某些情况下,可能需要将编码器和解码器链添加到 netty 管道。要将 multpile codecs 添加到 camel netty 端点中,应使用 'encoders' 和 'decoders' uri 参数。与 'encoder' 和 'decoder' 参数一样,它们用来提供应添加到管道中的 ChannelUpstreamHandlers 和 ChannelDownstreamHandlers 的引用(list)。请注意,如果指定了 encodingrs,则编码器参数将被忽略,类似于解码器和解码器参数。
更多有关使用不可共享编码器/解码器的信息。
codecs 列表需要添加到 Camel 的 registry 中,以便在创建端点时解析它们。
ChannelHandlerFactory lengthDecoder = ChannelHandlerFactories.newLengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4);
StringDecoder stringDecoder = new StringDecoder();
registry.bind("length-decoder", lengthDecoder);
registry.bind("string-decoder", stringDecoder);
LengthFieldPrepender lengthEncoder = new LengthFieldPrepender(4);
StringEncoder stringEncoder = new StringEncoder();
registry.bind("length-encoder", lengthEncoder);
registry.bind("string-encoder", stringEncoder);
List<ChannelHandler> decoders = new ArrayList<ChannelHandler>();
decoders.add(lengthDecoder);
decoders.add(stringDecoder);
List<ChannelHandler> encoders = new ArrayList<ChannelHandler>();
encoders.add(lengthEncoder);
encoders.add(stringEncoder);
registry.bind("encoders", encoders);
registry.bind("decoders", decoders);
Spring 的原生集合支持可用于在应用程序上下文中指定 codec 列表
<util:list id="decoders" list-class="java.util.LinkedList">
<bean class="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newLengthFieldBasedFrameDecoder">
<constructor-arg value="1048576"/>
<constructor-arg value="0"/>
<constructor-arg value="4"/>
<constructor-arg value="0"/>
<constructor-arg value="4"/>
</bean>
<bean class="io.netty.handler.codec.string.StringDecoder"/>
</util:list>
<util:list id="encoders" list-class="java.util.LinkedList">
<bean class="io.netty.handler.codec.LengthFieldPrepender">
<constructor-arg value="4"/>
</bean>
<bean class="io.netty.handler.codec.string.StringEncoder"/>
</util:list>
<bean id="length-encoder" class="io.netty.handler.codec.LengthFieldPrepender">
<constructor-arg value="4"/>
</bean>
<bean id="string-encoder" class="io.netty.handler.codec.string.StringEncoder"/>
<bean id="length-decoder" class="org.apache.camel.component.netty.ChannelHandlerFactories" factory-method="newLengthFieldBasedFrameDecoder">
<constructor-arg value="1048576"/>
<constructor-arg value="0"/>
<constructor-arg value="4"/>
<constructor-arg value="0"/>
<constructor-arg value="4"/>
</bean>
<bean id="string-decoder" class="io.netty.handler.codec.string.StringDecoder"/>
然后,在 netty 端点定义中使用 bean 名称作为逗号分隔的列表,也可以包含在 List 等中。
from("direct:multiple-codec").to("netty:tcp://0.0.0.0:{{port}}?encoders=#encoders&sync=false");
from("netty:tcp://0.0.0.0:{{port}}?decoders=#length-decoder,#string-decoder&sync=false").to("mock:multiple-codec");
或者通过 XML。
<camelContext id="multiple-netty-codecs-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:multiple-codec"/>
<to uri="netty:tcp://0.0.0.0:5150?encoders=#encoders&sync=false"/>
</route>
<route>
<from uri="netty:tcp://0.0.0.0:5150?decoders=#length-decoder,#string-decoder&sync=false"/>
<to uri="mock:multiple-codec"/>
</route>
</camelContext>