Jetty websocket class 加载问题
Jetty websocket class loading issue
我已经在 Jetty 中实现了一个基本的 websocket 服务器(独立模式)。
MyWebSocketServlet.java
public class MyWebSocketServlet extends WebSocketServlet {
@Override
public void configure(WebSocketServletFactory webSocketServletFactory){
webSocketServletFactory.getPolicy().setIdleTimeout(1000 * 10 * 60);
webSocketServletFactory.setCreator(new MyWebSocketFactory());
}
}
MyWebSocketFactory.java
public class MyWebSocketFactory implements WebSocketCreator {
public Object createWebSocket(
ServletUpgradeRequest servletUpgradeRequest
, ServletUpgradeResponse servletUpgradeResponse) {
return new MyWebSocketListener();
}
}
MyWebSocketListener.java
public class MyWebSocketListener implements WebSocketListener {
private Session sessionInstance;
public void onWebSocketBinary(byte[] bytes, int i, int i1) {
ByteBuffer data = ByteBuffer.wrap(bytes, i, i1);
try {
sessionInstance.getRemote().sendBytes(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public void onWebSocketClose(int i, String s) {
}
public void onWebSocketConnect(Session session) {
sessionInstance = session;
}
public void onWebSocketError(Throwable throwable) {
throwable.printStackTrace(System.err);
}
public void onWebSocketText(String s) {
try {
sessionInstance.getRemote().sendString(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<servlet>
<servlet-name>WsEcho</servlet-name>
<servlet-class>org.test.sanket.MyWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WsEcho</servlet-name>
<url-pattern>/echo/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HttpEcho</servlet-name>
<servlet-class>org.test.sanket.MyHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HttpEcho</servlet-name>
<url-pattern>/httpecho/*</url-pattern>
</servlet-mapping>
</web-app>
如果我使用嵌入式码头并以编程方式配置服务器并添加 Servlet,则此示例运行良好,而不是使用独立码头。
但是,如果我将与 war 相同的内容打包,然后将其部署在独立的码头实例中,我将得到以下观察结果:
- 我能够访问 HttpServlet ,即 MyHttpServlet 并收到响应
- 但是当我尝试访问 websocket servlet,即 MyWebSocketServlet 时,我看到了以下错误:
异常
java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:175)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:148)
at org.eclipse.jetty.websocket.servlet.WebSocketServlet.service(WebSocketServlet.java:151)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
我确实遇到了以下 link:
Jetty - stand alone WebSocket server
从上面的 link 来看,这似乎是一个 class 加载问题,因为 jetty websocket 包被视为系统 class 包并且不应该被 WebApp 加载,如果已被系统加载。
因此,如上 link 所述,我查看了建议的详细信息:
http://www.eclipse.org/jetty/documentation/9.2.10.v20150310/jetty-classloading.html
从这个 link 开始,解决此问题的方法之一是调用 org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array) 或 org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String) 以允许精细控制classes 被认为是系统 classes.
因此,为了能够做到这一点,我应该能够在 Jetty 初始化并添加 WebSocket classes 作为系统 classes 时获取 WebAppContext 的实例。
我试过搜索如何才能达到同样的效果,但到目前为止还没有成功?任何人都可以为我指出一个关于如何实现这一点的参考实现吗?
Java版本:OpenJDK 7(最新)
码头:9.2.10.v20150310
操作系统:Ubuntu14.04
提前致谢!
不要在您的 war 的 WEB-INF/lib
或 WEB-INF/classes
目录中包含 org.eclipse.jetty.*
类。
如果您已按照此 link 设置 Jetty 独立实例,那么您可能 运行 以下命令:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging
如果是这样,那么当您尝试访问 websocket servlet 时,您将看到您注意到的异常。
您需要做的就是,除了该命令,您还需要初始化 websocket 模块,如下所示:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging,websocket
希望对您有所帮助!
我已经在 Jetty 中实现了一个基本的 websocket 服务器(独立模式)。
MyWebSocketServlet.java
public class MyWebSocketServlet extends WebSocketServlet {
@Override
public void configure(WebSocketServletFactory webSocketServletFactory){
webSocketServletFactory.getPolicy().setIdleTimeout(1000 * 10 * 60);
webSocketServletFactory.setCreator(new MyWebSocketFactory());
}
}
MyWebSocketFactory.java
public class MyWebSocketFactory implements WebSocketCreator {
public Object createWebSocket(
ServletUpgradeRequest servletUpgradeRequest
, ServletUpgradeResponse servletUpgradeResponse) {
return new MyWebSocketListener();
}
}
MyWebSocketListener.java
public class MyWebSocketListener implements WebSocketListener {
private Session sessionInstance;
public void onWebSocketBinary(byte[] bytes, int i, int i1) {
ByteBuffer data = ByteBuffer.wrap(bytes, i, i1);
try {
sessionInstance.getRemote().sendBytes(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public void onWebSocketClose(int i, String s) {
}
public void onWebSocketConnect(Session session) {
sessionInstance = session;
}
public void onWebSocketError(Throwable throwable) {
throwable.printStackTrace(System.err);
}
public void onWebSocketText(String s) {
try {
sessionInstance.getRemote().sendString(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<servlet>
<servlet-name>WsEcho</servlet-name>
<servlet-class>org.test.sanket.MyWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WsEcho</servlet-name>
<url-pattern>/echo/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HttpEcho</servlet-name>
<servlet-class>org.test.sanket.MyHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HttpEcho</servlet-name>
<url-pattern>/httpecho/*</url-pattern>
</servlet-mapping>
</web-app>
如果我使用嵌入式码头并以编程方式配置服务器并添加 Servlet,则此示例运行良好,而不是使用独立码头。
但是,如果我将与 war 相同的内容打包,然后将其部署在独立的码头实例中,我将得到以下观察结果:
- 我能够访问 HttpServlet ,即 MyHttpServlet 并收到响应
- 但是当我尝试访问 websocket servlet,即 MyWebSocketServlet 时,我看到了以下错误:
异常
java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:175)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:148)
at org.eclipse.jetty.websocket.servlet.WebSocketServlet.service(WebSocketServlet.java:151)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
我确实遇到了以下 link: Jetty - stand alone WebSocket server
从上面的 link 来看,这似乎是一个 class 加载问题,因为 jetty websocket 包被视为系统 class 包并且不应该被 WebApp 加载,如果已被系统加载。
因此,如上 link 所述,我查看了建议的详细信息: http://www.eclipse.org/jetty/documentation/9.2.10.v20150310/jetty-classloading.html
从这个 link 开始,解决此问题的方法之一是调用 org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array) 或 org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String) 以允许精细控制classes 被认为是系统 classes.
因此,为了能够做到这一点,我应该能够在 Jetty 初始化并添加 WebSocket classes 作为系统 classes 时获取 WebAppContext 的实例。
我试过搜索如何才能达到同样的效果,但到目前为止还没有成功?任何人都可以为我指出一个关于如何实现这一点的参考实现吗?
Java版本:OpenJDK 7(最新)
码头:9.2.10.v20150310
操作系统:Ubuntu14.04
提前致谢!
不要在您的 war 的 WEB-INF/lib
或 WEB-INF/classes
目录中包含 org.eclipse.jetty.*
类。
如果您已按照此 link 设置 Jetty 独立实例,那么您可能 运行 以下命令:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging
如果是这样,那么当您尝试访问 websocket servlet 时,您将看到您注意到的异常。
您需要做的就是,除了该命令,您还需要初始化 websocket 模块,如下所示:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging,websocket
希望对您有所帮助!