Tyrus服务器可以使用内部类端点吗?

时间:2015-03-09 00:05:35

标签: java websocket tyrus

我在使用非常简单的独立Tyrus websocket服务器时遇到问题。我已经让它在非常特殊的情况下工作,这对我来说没有意义。

正常工作的情况是我定义顶级(在其自己的文件中)服务器端点类并使用@ServerEndpoint注释它。这个类包括用@ OnOpen,@ OnMessage和@OnClose注释的方法,这些都是典型的东西。我将此类传递给Server构造函数。我的简单客户端可以连接到此服务器,并成功发送服务器收到的消息。

当我将顶级服务器端点类更改为初始化服务器的类的内部类时,会出现问题(这是我所做的唯一更改)。在这种情况下,我的客户端可以连接并调用客户端的@OnOpen方法。但是服务器没有实例化服务器端点,因此永远不会调用它的@OnOpen方法。显然,不会发生服务器消息接收。

Tyrus是否要求注释的服务器端点类不能成为内部类?如果没有,是否有对服务器端点类的特定权限(一切都已公开试图让它运行没有运气)?我在Mac,OSX 1.9.5上使用Tyrus 1.9和JDK 1.7。

简单服务器(包括并配置为使用失败的内部服务器端点):

package tyrus.example;

import java.util.concurrent.TimeUnit;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.glassfish.tyrus.server.Server;

public class SimpleServer
{
    private static final String HOST_ADDR = "localhost";
    private static final int HOST_PORT = 8025;

    public static void main(String[] args) {
        Server websocketServer = new Server(HOST_ADDR, HOST_PORT, "/ws", null, InnerSimpleServerEndpoint.class);

        try {
            websocketServer.start();
            Thread.sleep(TimeUnit.MINUTES.toMillis(5));
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        websocketServer.stop();

        System.out.println("Done.");
    }

    @ServerEndpoint("/myapp")
    public class InnerSimpleServerEndpoint {
        @OnOpen
        public void onOpen(Session session) {
            System.out.println("Connection received for "+session.getRequestURI());
        }

        @OnMessage
        public void onMessage(String message, Session session) {
            System.out.println("Message received: "+message);
        }

        @OnClose
        public void onClose(Session session, CloseReason closeReason) {
            System.out.println("Session closed, reason: "+closeReason);
        }
    }
}

简单的客户:

package tyrus.example;

import java.io.IOException;
import java.net.URI;

import javax.websocket.ClientEndpointConfig;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;

import org.glassfish.tyrus.client.ClientManager;

public class SimpleClient
{
    private static final String DEF_WS_URL = "ws://localhost:8025/ws/myapp";

    public static void main(String[] args) {
        ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
        ClientManager client = ClientManager.createClient();

        try {
            client.connectToServer(new ClientEndpoint(), cec, new URI(DEF_WS_URL));
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Done.");
    }

    private static class ClientEndpoint extends Endpoint {
        @Override
        public void onOpen(Session session, EndpointConfig config) {
            System.out.println("ClientEndpoint: server session opened: "+session);

            session.addMessageHandler(new MessageHandler.Whole<String>() {
                @Override
                public void onMessage(String message) {
                    System.out.println("ClientEndpoint: received message: "+message);
                }
            });

            try {
                session.getBasicRemote().sendText("Hello server!");
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

最后是服务器使用它时工作的非内部类服务器端点:

package tyrus.example;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/myapp")
public class SimpleServerEndpoint {
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connection received for "+session.getRequestURI());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Message received: "+message);
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        System.out.println("Session closed, reason: "+closeReason);
    }
}

3 个答案:

答案 0 :(得分:1)

在服务器上,端点可以是内部类,但它也必须是静态的。即使代码运行和服务,由于某种原因,如果服务器端点也是静态的,我只能使它工作。即:更改为在服务器代码中添加静态:

@ServerEndpoint("/myapp") public static class InnerSimpleServerEndpoint { }

您可能还想添加

@OnError public void onError(Session session, Throwable throwable) { //... }

答案 1 :(得分:0)

端点可以是内部类,但它必须是可实例化的 - 失败示例中的类ClientEndpointprivate,因此Tyrus无法创建它的实例。

将其更改为公开,并且应该按预期工作。

答案 2 :(得分:0)

内部类应该是静态的,否则没有外部类的实例就无法实例化。看这个: https://www.javatpoint.com/why-we-use-static-class-in-java 因此,如果用@ServerEndpoint 注释的类不是静态的,则无法实例化。