当前位置: 首页 > 后端技术 > Java

Netty系列:websocket处理器分离

时间:2023-04-02 01:37:45 Java

简介在上一篇文章中,我们使用netty搭建了一个可以处理websocket协议的服务器。在这个服务器中,我们构建了一个特殊的处理程序来处理HTTP或websocket请求。一些代码整洁的人可能无法容忍在一个处理程序中处理两个不同的请求。那么,是否可以对普通的HTTP请求和websocket请求使用不同的handler呢?答案是肯定的。Netty的消息处理我们知道netty中所有的消息处理都是通过handlers来实现的。为了方便,netty提供了一个简单的消息处理类SimpleChannelInboundHandler。可以通过继承重写channelRead0方法:protectedabstractvoidchannelRead0(ChannelHandlerContextctx,Imsg)throwsException;我们再看一下SimpleChannelInboundHandler的定义:publicabstractclassSimpleChannelInboundHandlerextendsChannelInboundHandlerAdapter可以看到SimpleChannelInboundHandler本身有一个泛型I,这个I就是我们要探索的方向。如果我们想使用这个处理程序来处理所有消息,那么我可以设置为对象。如果我们只需要处理String消息,那么我们可以这样做:}}同样,如果你想同时处理HTTP和WebSocket消息,只需要将I设置为不同的类型即可。对于WebSocketFrame,我们有:publicclassServer2FrameHandlerextendsSimpleChannelInboundHandler对于FullHttpRequest,我们有:publicclassServer2HttpHandlerextendsSimpleChannelInboundHandler处理WebSocketFrame对于WebSocketFrame消息,从上一节我们知道它有6种类型,分别是:BinaryWebSocketFrameCloseWebSocketFrameContinuationWebSocketFramePingWebSocketFramePongWebSocketFrameTextWebSocketFrameTheonesthatactuallycontainthecontentareTextWebSocketFrameandBinaryWebSocketFrame.HerewespeciallyhandleTextWebSocketFrame:protectedvoidchannelRead0(ChannelHandlerContextctx,WebSocketFrameframe)throwsException{if(frameinstanceofTextWebSocketFrame){//ConvertthereceivedmessagetoanuppercaseStringrequest=((TextWebSocketFrame)frame).text();ctx.channel().writeAndFlush(newTextWebSocketFrame(request.toUpperCase(Locale.CHINA)));}else{Stringmessage="UnsupportedFrametype:"+frame.getClass().getName();thrownewUnsupportedOperationException(信息);}}处理HTTP对于HTTP请求中的FullHttpRequest,我们只是安装普通的HTTP服务请求处理流程,这里不做细说。编码器和解码器等等,我们是不是忘记了什么?是的,就是编码器和解码器。在上一节中,我们使用WebSocketServerHandshaker对websocket消息进行编码和解码。但是,它实际上是放在我们自定义的hadler代码中,使用起来略显不雅。没关系,netty为我们提供了一个WebSocketServerProtocolHandler类,它负责websocket的编解码。除了处理正常的websocket握手,WebSocketServerProtocolHandler类还为我们处理了Close、Ping、Pong等常见的消息类型。而我们只需要关注真正的业务逻辑消息,非常方便。对于剩下的Text或者Binary帧数据,会交给pipeline中的下一个handler去处理。其中,Handshake有两种状态,分别是:HANDSHAKE_COMPLETE和HANDSHAKE_TIMEOUT。而HandshakeComplete包含了requestUri、requestHeaders和selectedSubprotocol的信息。最后在管道中添加WebSocketServerProtocolHandler,最后得到:publicvoidinitChannel(SocketChannelch)throwsException{ChannelPipelinepipeline=ch.pipeline();pipeline.addLast(newHttpServerCodec());pipeline.addLast(新的HttpObject3Aggregator)(655);pipeline.addLast(newWebSocketServerCompressionHandler());pipeline.addLast(newWebSocketServerProtocolHandler(WEBSOCKET_PATH,null,true));pipeline.addLast(newServer2HttpHandler());pipeline.addLast(newServer2FrameHandler());分离HTTP请求和webSocket请求的服务器就完成了。简单直观是程序员追求的世界!本文示例可参考:learn-netty4本文已收录于http://www.flydean.com/24-netty-websocket-server2/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!