【问题标题】:Netty websocket and Rest in same Java applicationNetty websocket 和 Rest 在同一个 Java 应用程序中
【发布时间】:2018-10-12 16:41:28
【问题描述】:

我有一个公开 REST 服务的现有 Java 应用程序。我想在同一个应用程序中添加一个新功能来处理 Web 套接字请求(使用 netty)以及现有的 REST 服务。如何在不更改 REST 服务的情况下做到这一点?

【问题讨论】:

    标签: rest websocket netty javax.ws.rs


    【解决方案1】:

    您可以在接收 http 请求的处理程序之前使用处理程序。此处理程序的基本任务是查看 http 请求是否包含 WebSocket 升级标头。如果是这种情况,它将完成握手并继续处理 websocket 帧,否则它将把 http 请求传递给下一个处理程序,如下所示:

    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    import io.netty.handler.codec.http.HttpHeaderNames;
    import io.netty.handler.codec.http.HttpHeaderValues;
    import io.netty.handler.codec.http.HttpHeaders;
    import io.netty.handler.codec.http.HttpMethod;
    import io.netty.handler.codec.http.HttpRequest;
    import io.netty.handler.codec.http.websocketx.WebSocketFrame;
    import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
    import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
    
    public class WebSocketServerHandler extends ChannelInboundHandlerAdapter {
        private WebSocketServerHandshaker handshaker;
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            if (msg instanceof HttpRequest) {
                HttpRequest httpRequest = (HttpRequest) msg;
                HttpMethod requestMethod = httpRequest.method();
    
                if (containsUpgradeHeaders(httpRequest)) {
                    if (HttpMethod.GET == requestMethod) {
                        // Handshake
                        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                                getWebSocketLocation(httpRequest), null, false, Integer.MAX_VALUE);
                        handshaker = wsFactory.newHandshaker(httpRequest);
                        if (handshaker == null) {
                            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
                        } else {
                            handshaker.handshake(ctx.channel(), httpRequest);
                        }
    
                    }
                } else {
                    //Let the http handler handle the request
                    ctx.fireChannelRead(msg);
                }
    
            } else if (msg instanceof WebSocketFrame) {
                handleWebSocketFrame(ctx, (WebSocketFrame) msg);
            } else {
                throw new IllegalStateException("unknown message: " + msg);
            }
        }
    
        private boolean containsUpgradeHeaders(HttpRequest httpRequest) {
            HttpHeaders headers = httpRequest.headers();
            return headers.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true) && headers
                    .containsValue(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET, true);
        }
    
        private static String getWebSocketLocation(HttpRequest req) {
            return "ws://" + req.headers().get(HttpHeaderNames.HOST);
        }
    
        private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
            //handle the websocket frame
        }
    }
    

    或者您可以使用不同的处理程序来处理 websocket 帧,方法是在握手完成后将 http 请求处理程序替换为 WebSocket 帧处理程序。

    【讨论】:

      【解决方案2】:

      有两种方法可以在不更改 REST 服务的情况下做到这一点:

      1. 我建议您设置一个普通的 netty websocket 服务器并在另一个端口上并行运行它(这可能发生在同一个应用程序中)。

      2. 一个更复杂的低效解决方案是编写一个运行在默认端口 (80/443) 上的 netty http/websocket 服务器,并将所有 REST 请求发送到您的 REST 服务。所以基本上你会编写一种 HTTP 代理,它也托管 websocket 服务器(也可能发生在同一个应用程序中)。

      Here是一个如何编写netty websocket服务器的例子。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-25
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        • 2015-07-19
        • 2016-06-05
        • 2012-10-06
        • 2018-12-14
        相关资源
        最近更新 更多