java - 使用 Spring 框架的 WebSocketClient 时如何修复 NoClassDefFoundError
问题描述
我正在编写一个桌面 Java 应用程序作为 Web 服务客户端。我想使用 WebSocket 来实现来自服务器的通知“回调”。
我正在使用 Spring 框架的 WebSocketStompClient。下面的片段显示了我如何初始化它:
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
...
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
stompClient = new WebSocketStompClient(new SockJsClient(transports));
...
如果我在 IntelliJ IDE 中运行它,它可以完美运行,但是,如果我通过命令行“java -cp my.jar MyPackage.MyMainClass”运行,它将失败并显示以下消息:
Error: Unable to initialize main class MyMainClass
Caused by: java.lang.NoClassDefFoundError: org/springframework/web/socket/client/WebSocketClient
以上是由 Java SE 12.0.2 生成的。如果我使用 Java SE 1.8 运行它,错误消息将是:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError:
org/springframework/web/socket/client/WebSocketClient
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
两者都java.lang.NoClassDefFoundError
建议getDeclaredMethods0(Native Method)
缺少本机模块(DLL)。
下面是我的 Gradle 脚本:
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
我不认为这是由于缺少一些 JAR。我试过:
- 添加
tyrus-standalone-client
到依赖列表,或 - 使用,
StandardWebSocketClient
而不是SockJsClient
但错误仍然存在。
我猜我的操作系统(Win10)中缺少一些本机库,但这无法解释为什么我可以在 IntelliJ 中运行它......
你能告诉我缺少什么吗?或者我该如何解决这个问题?谢谢!
解决方案
尝试创建一个包含所有依赖项和类的胖 jar。
build.gradle
将脚本更新为下面给出的:
apply plugin: 'java'
version = '...'
sourceCompatibility = 1.8
targetCompatibility = 1.8
// to create a fat jar.
jar {
manifest {
attributes "Main-Class": "MyPackage.MyMainClass"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
dependencies {
implementation project(':logman-common')
implementation 'org.springframework:spring-web:5.2.2.RELEASE'
implementation 'org.springframework:spring-websocket:5.2.2.RELEASE'
implementation 'org.springframework:spring-messaging:5.2.2.RELEASE'
... // other unrelated dependencies, such as GUI
}
它将在build/libs
您的根项目中生成一个可执行的 fat jar,其中将包含所有项目文件(这包括您的所有依赖项、资源文件、.class 文件等)。
注意:对于旧版本的 Gradle,请使用它configurations.compile.collect
而不是configurations.runtimeClasspath.collect
.
您只需要使用以下命令运行 jar: java -jar <project-version>.jar
这应该可以解决您的问题。
推荐阅读
- python - Tensorflow tf.data.Dataset 使用 map 函数时出错 | 键错误
- php - PHP中的PdfParser问题
- python - Django模型-如何通过相关模型使用过滤器
- html - Xpath在tbody内按位置4阶td查找文本并单击同一行中的编辑
- c++ - C++ 将原始 std::bytes 复制到 std::vector
- javascript - 如何在javascript中的一个选择下拉列表中显示所有父值和子值
- python - 带有rest框架的django在线用户
- oracle - Oracle Application Express 的问题
- google-cloud-platform - ESP32 到 GCP IOT Core 连接失败
- css - 输入滑块(v-slider)死区上的标签