gpt4 book ai didi

java - 如何用Java处理来自客户端的Websocket消息?

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:51 25 4
gpt4 key购买 nike

我正在使用 Websocket 用 Ja​​va 开发客户端-服务器应用程序。目前,所有客户端消息均使用 switch-case 进行处理,如下所示。

@OnMessage
public String onMessage(String unscrambledWord, Session session) {
switch (unscrambledWord) {
case "start":
logger.info("Starting the game by sending first word");
String scrambledWord = WordRepository.getInstance().getRandomWord().getScrambledWord();
session.getUserProperties().put("scrambledWord", scrambledWord);
return scrambledWord;
case "quit":
logger.info("Quitting the game");
try {
session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, "Game finished"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
String scrambledWord = (String) session.getUserProperties().get("scrambledWord");
return checkLastWordAndSendANewWord(scrambledWord, unscrambledWord, session);
}

服务器必须处理来自客户端的 50 多个不同请求,从而产生 50 多个 case 语句。 future ,我预计它会增长。有没有更好的方法来处理来自客户端的Websocket消息?或者,这是通常的做法吗?

我在某处读到过有关使用哈希表通过映射到函数指针来避免长 switch-case 场景的内容。这在Java中可能吗?或者,有没有更好的解决方案?

谢谢。

最佳答案

经过一些测试和研究,我找到了两种替代方案来避免长 switch case 场景。

  1. 匿名类方法(策略模式)
  2. 带注释的反射(reflection)

使用匿名类

匿名类方法是常态,下面的代码展示了如何实现它。我在这个例子中使用了 Runnable。如果需要更多控制,请创建自定义界面。

public class ClientMessageHandler {

private final HashMap<String, Runnable> taskList = new HashMap<>();

ClientMessageHandler() {

this.populateTaskList();
}

private void populateTaskList() {

// Populate the map with client request as key
// and the task performing objects as value

taskList.put("action1", new Runnable() {
@Override
public void run() {
// define the action to perform.
}
});

//Populate map with all the tasks
}

public void onMessageReceived(JSONObject clientRequest) throws JSONException {

Runnable taskToExecute = taskList.get(clientRequest.getString("task"));

if (taskToExecute == null)
return;

taskToExecute.run();
}
}

此方法的主要缺点是对象创建。假设我们有 100 项不同的任务要执行。这种匿名类方法将导致为单个客户端创建 100 个对象。我的应用程序无法承受过多的对象创建,因为该应用程序将有超过 5,000 个 Activity 并发连接。看看这篇文章http://blogs.microsoft.co.il/gilf/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements/

带注释的反射(reflection)

我真的很喜欢这种方法。我创建了一个自定义注释来表示方法执行的任务。与策略模式方法一样,没有对象创建的开销,因为任务由单个类执行。

注释

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

public @interface TaskAnnotation {
public String value();
}

下面给出的代码将客户端请求键映射到处理任务的方法。在这里, map 仅被实例化和填充一次。

public static final HashMap<String, Method> taskList = new HashMap<>();

public static void main(String[] args) throws Exception {

// Retrieves declared methods from ClientMessageHandler class

Method[] classMethods = ClientMessageHandler.class.getDeclaredMethods();

for (Method method : classMethods) {
// We will iterate through the declared methods and look for
// the methods annotated with our TaskAnnotation

TaskAnnotation annot = method.getAnnotation(TaskAnnotation.class);

if (annot != null) {
// if a method with TaskAnnotation is found, its annotation
// value is mapped to that method.

taskList.put(annot.value(), method);
}
}

// Start server
}

最后,我们的 ClientMessageHandler 类如下所示

public class ClientMessageHandler {

public void onMessageReceived(JSONObject clientRequest) throws JSONException {

// Retrieve the Method corresponding to the task from map
Method method = taskList.get(clientRequest.getString("task"));

if (method == null)
return;

try {
// Invoke the Method for this object, if Method corresponding
// to client request is found

method.invoke(this);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
logger.error(e);
}
}

@TaskAnnotation("task1")
public void processTaskOne() {

}

@TaskAnnotation("task2")
public void processTaskTwo() {

}

// Methods for different tasks, annotated with the corresponding
// clientRequest code
}

这种方法的主要缺点是性能受到影响。与直接方法调用方法相比,此方法速度较慢。此外,许多文章建议远离反射,除非我们正在处理动态编程。

阅读这些答案以了解有关反射的更多信息 What is reflection and why is it useful?

反射性能相关文章

Faster alternatives to Java's reflection

https://dzone.com/articles/the-performance-cost-of-reflection

最终结果

我继续在应用程序中使用 switch 语句以避免任何性能影响。

关于java - 如何用Java处理来自客户端的Websocket消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44373406/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com