103.8. 例子
103.8.1. 使用 Request-Reply 和 serialized 对象有效负载的 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); } } } };
103.8.2. 使用单向通信基于 TCP 的 Netty consumer 端点
RouteBuilder builder = new RouteBuilder() { public void configure() { from("netty:tcp://0.0.0.0:5150") .to("mock:result"); } };
103.8.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
中可随时提供主题名称。
103.8.4. 使用多个代码cs
在某些情况下,可能需要将编码器和解码器链添加到 netty 管道。要将 multpile codecs 添加到 camel netty 端点中,应使用 'encoders' 和 'decoders' uri 参数。与 'encoder' 和 'decoder' 参数类似,它们用来提供应该添加到管道中的引用( ChannelUpstreamHandlers 和 ChannelDownstreamHandlers 列表)。请注意,如果指定了编码器,则忽略 encoder 参数,类似于解码器和解码器参数。
请参阅上面有关使用不可共享的编码器/解码器的进一步的信息。
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>