内部非静态类。正确的方法?的WebSocket

时间:2018-04-16 08:58:00

标签: java class websocket

提示此决定的正确性。

我在Java(服务器)上有一个Web套接字的连接点。它实现了onOpenonMessageonCloseonError方法。

关于onMessage方法。

我不想用一个对所有可能的消息来说都很大的开关来填充这个方法。

我做过这种事(我使用内部非静态类来处理消息)

@ServerEndpoint(value = "/endpoint", configurator = SocketConfigurator.class, encoders = WsEncoder.class, decoders = WsDecoder.class)
public class WsEndpoint {

    private static final CopyOnWriteArrayList<WsUser> wsWebUsers = new CopyOnWriteArrayList<WsUser>();

    public WsEndpoint() {
        LOGGER.info("ENDPOINT CREATED");
    }

    @OnOpen
    public void onOpen(Session session) {
        LOGGER.info("ENDPOINT ONOPEN");
    }

    @OnMessage
    public void onMessage(Session session, WsMessage wsMessage) {

        new WsOnMessage(session, wsMessage);

    }

    @OnClose
    public void onClose(Session session) {

    }

    @OnError
    public void onError(Session session, Throwable ex) {
        LOGGER.error("ENDPOINT ERROR", ex);
    }

    private class WsOnMessage {

        private Session session;
        private WsMessage wsMessage;

        WsOnMessage(Session session, WsMessage wsMessage) {
            this.session = session;
            this.wsMessage = wsMessage;
            execute();
        }

        private void execute() {
            switch (wsMessage.getType()) {
            default:
                LOGGER.info("ENDPOINT UNKNOWN MESSAGE");
                break;
            }
        }
    }
}

这样做是真的吗?可以有更优雅的方式处理消息吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

创建一个抽象类,其子类覆盖<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/img" android:text="Text Line" android:textColor="@color/black" /> <ImageView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:adjustViewBounds="true" android:src="@drawable/signuptop" /> </RelativeLayout> 方法:

execute

创建知道如何将public abstract class Command { protected final Session session; protected final WsMessage message; public Command(Session session, WsMessage message) { this.session = session; this.message = message; } public abstract void execute(); } 映射到相应的WsMessage类的命令工厂:

Command

import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class CommandFactory { private <T extends Command> Class<T> findCommandClass(WsMessage message) { // switch on message, or lookup in a Map<WsMessage,Class<? extends Command>>, or,... // throw exception if no registered class throw new RuntimeException(String.format("No known command for message %s", message)); } private <T extends Command> T createInstance(Class<T> clazz, Session session, WsMessage message) { try { Constructor<T> constructor = clazz.getConstructor(Session.class, WsMessage.class); return constructor.newInstance(session, message); } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException(String.format("Could not instantiate %s", clazz), e); } } public Command createCommand(Session session, WsMessage message) { Class<Command> commandClass = findCommandClass(message); return createInstance(commandClass, session, message); } } 中有对工厂的引用:

WsEndpoint

此模式允许您传递模拟的命令工厂以进行测试。

一些想法:

  • 使CommandFactory为abstract,并使用抛出异常的默认实现保护find方法
  • 可能仅将public class WsEndpoint { private CommandFactory factory; // if you are required to have a no-arg default constructor and can't use dependency injection: public WsEndpoint() { this(new MyStandardCommandFactory()); // create an instance of the standard command factory. } public WsEndpoint(CommandFactory factory) { this.factory = Objects.requireNonNull(factory); } @OnMessage public void onMessage(Session session, WsMessage wsMessage) { Command command = factory.createCommand(session, wsMessage); command.execute(); } 作为执行参数传递,而不是传递给工厂。