之前大概的看过WebSocket,当时Tomcat还不支持WebSocket,所以当时写了一篇基于Jetty的WebSocket实现,地址如下:
http://redstarofsleep.iteye.com/blog/1307608
?
现在Tomcat7.0.27发布了,从这个版本开始Tomcat就支持WebSocket了。
Tomcat的WebSocket和Jetty的大致上差不多,大同小异,这里就简单的贴两个类吧:
?
第一个类,这个和Jetty一样,需要一个Servlet来处理WebSocket请求:
package lhc.websocket; import org.apache.catalina.websocket.StreamInbound; import org.apache.catalina.websocket.WebSocketServlet; public class MyWebSocketServlet extends WebSocketServlet { private static final long serialVersionUID = -7178893327801338294L; @Override protected StreamInbound createWebSocketInbound(String arg0) { System.out.println("##########"); return new MyMessageInbound(); } }
这个Servlet继承自WebSocketServlet,实现createWebSocketInbound方法。该方法返回第二个类的实例。
?
第二个类,处理每一次具体的WebSocket任务:
package lhc.websocket; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import lhc.init.InitServlet; import org.apache.catalina.websocket.MessageInbound; import org.apache.catalina.websocket.WsOutbound; public class MyMessageInbound extends MessageInbound { @Override protected void onBinaryMessage(ByteBuffer arg0) throws IOException { // TODO Auto-generated method stub } @Override protected void onTextMessage(CharBuffer msg) throws IOException { for (MessageInbound messageInbound : InitServlet.getSocketList()) { CharBuffer buffer = CharBuffer.wrap(msg); WsOutbound outbound = messageInbound.getWsOutbound(); outbound.writeTextMessage(buffer); outbound.flush(); } } @Override protected void onClose(int status) { InitServlet.getSocketList().remove(this); super.onClose(status); } @Override protected void onOpen(WsOutbound outbound) { super.onOpen(outbound); InitServlet.getSocketList().add(this); } }?
?这个类继承自MessageInbound类,必须实现onBinaryMessage和onTextMessage方法。Jetty中只有一个onMessage方法,而Tomcat细化成了2个方法。
?
还要一个初始化的Servlet
package lhc.init; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import org.apache.catalina.websocket.MessageInbound; public class InitServlet extends HttpServlet { private static final long serialVersionUID = -3163557381361759907L; private static List<MessageInbound> socketList; public void init(ServletConfig config) throws ServletException { InitServlet.socketList = new ArrayList<MessageInbound>(); super.init(config); System.out.println("Server start============"); } public static synchronized List<MessageInbound> getSocketList() { return InitServlet.socketList; } }?
?
最后,web.xml中进行一下Servlet的配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>wsoc</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>mywebsocket</servlet-name> <servlet-class>lhc.websocket.MyWebSocketServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>mywebsocket</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet> <servlet-name>initServlet</servlet-name> <servlet-class>lhc.init.InitServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> </web-app>?
?
页面的话,就是标准的HTML5的websocket,这个和服务器是否是Tomcat或者Jetty是无关的:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Index</title> <script type="text/javascript"> var ws = null; function startWebSocket() { if ('WebSocket' in window) ws = new WebSocket("ws://localhost:8080/wsoc/mywebsocket.do"); else if ('MozWebSocket' in window) ws = new MozWebSocket("ws://localhost:8080/wsoc/mywebsocket.do"); else alert("not support"); ws.onmessage = function(evt) { alert(evt.data); }; ws.onclose = function(evt) { alert("close"); }; ws.onopen = function(evt) { alert("open"); }; } function sendMsg() { ws.send(document.getElementById('writeMsg').value); } </script> </head> <body onload="startWebSocket();"> <input type="text" id="writeMsg"></input> <input type="button" value="send" onclick="sendMsg()"></input> </body> </html>?
?
2 楼
redstarofsleep
2012-04-22
junes_yu 写道
找了很久,实在万分感谢~!!
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
public class MyMessageInbound extends MessageInbound
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
是导入的这个包么?
import org.apache.catalina.websocket.MessageInbound;
3 楼
junes_yu
2012-04-22
redstarofsleep 写道
junes_yu 写道
找了很久,实在万分感谢~!!
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
public class MyMessageInbound extends MessageInbound
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
是导入的这个包么?
import org.apache.catalina.websocket.MessageInbound;
嗯,是的..有导入
package util; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import org.apache.catalina.websocket.MessageInbound; public class MyMessageInbound extends MessageInbound { @Override protected void onBinaryMessage(ByteBuffer arg0) throws IOException { // TODO Auto-generated method stub } @Override protected void onTextMessage(CharBuffer msg) throws IOException { System.out.println("***" + msg); } }
而且我把catalina.jar包放在WEB-INF的lib目录下了.请问还需要配置些什么吗?
4 楼
redstarofsleep
2012-04-23
junes_yu 写道
redstarofsleep 写道
junes_yu 写道
找了很久,实在万分感谢~!!
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
但我在编写MyMessageInbound类的时候报如下错误,请问如何解决呢?
public class MyMessageInbound extends MessageInbound
The type org.apache.coyote.http11.upgrade.UpgradeInbound cannot be resolved. It is indirectly referenced from required .class files
是导入的这个包么?
import org.apache.catalina.websocket.MessageInbound;
嗯,是的..有导入
package util; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import org.apache.catalina.websocket.MessageInbound; public class MyMessageInbound extends MessageInbound { @Override protected void onBinaryMessage(ByteBuffer arg0) throws IOException { // TODO Auto-generated method stub } @Override protected void onTextMessage(CharBuffer msg) throws IOException { System.out.println("***" + msg); } }
而且我把catalina.jar包放在WEB-INF的lib目录下了.请问还需要配置些什么吗?
首先确认你的Tomcat是7.0.27,并且在Eclipse的Server中已经导入了,然后在工程上又击,选择Build Path--Config Build Path--Libraries选项卡下--Add Library--Server Runtime--选择Tomcat7即可.不需要把包考到lib下
5 楼
junes_yu
2012-04-23
redstarofsleep 写道
首先确认你的Tomcat是7.0.27,并且在Eclipse的Server中已经导入了,然后在工程上又击,选择Build Path--Config Build Path--Libraries选项卡下--Add Library--Server Runtime--选择Tomcat7即可.不需要把包考到lib下
是的,我都是按您说的那样配置.但如果lib下不导入catalina.jar的话,那么工程不就不能访问import org.apache.catalina.websocket.MessageInbound;这个类了吗?
http://dl.iteye.com/upload/picture/pic/111775/e180baee-9426-3030-8e9d-73b3dea76067.jpg
6 楼
junes_yu
2012-04-23
junes_yu 写道
redstarofsleep 写道
首先确认你的Tomcat是7.0.27,并且在Eclipse的Server中已经导入了,然后在工程上又击,选择Build Path--Config Build Path--Libraries选项卡下--Add Library--Server Runtime--选择Tomcat7即可.不需要把包考到lib下
是的,我都是按您说的那样配置.但如果lib下不导入catalina.jar的话,那么工程不就不能访问import org.apache.catalina.websocket.MessageInbound;这个类了吗?
7 楼
redstarofsleep
2012-04-23
junes_yu 写道
junes_yu 写道
redstarofsleep 写道
首先确认你的Tomcat是7.0.27,并且在Eclipse的Server中已经导入了,然后在工程上又击,选择Build Path--Config Build Path--Libraries选项卡下--Add Library--Server Runtime--选择Tomcat7即可.不需要把包考到lib下
是的,我都是按您说的那样配置.但如果lib下不导入catalina.jar的话,那么工程不就不能访问import org.apache.catalina.websocket.MessageInbound;这个类了吗?
你的Tomcat导入的好像不太对。我的可以看到很多Jar包的。你去相册里看下我的那个截图。
怎么在回复里插入图片啊。。。
8 楼
junes_yu
2012-04-23
redstarofsleep 写道
你的Tomcat导入的好像不太对。我的可以看到很多Jar包的。你去相册里看下我的那个截图。
怎么在回复里插入图片啊。。。
嗯..我用另外一种方法把tomcat里的包导入了..那个插入图片可是有技巧的~你上传图片到相册里,然后点击一张查看高清图,在它加载的时候右键点击,然后选复制图片地址,(一定要在下面的CLOSE图标出来之前),接着就可以引用图片的路径了..
9 楼
redstarofsleep
2012-04-23
junes_yu 写道
redstarofsleep 写道
你的Tomcat导入的好像不太对。我的可以看到很多Jar包的。你去相册里看下我的那个截图。
怎么在回复里插入图片啊。。。
嗯..我用另外一种方法把tomcat里的包导入了..那个插入图片可是有技巧的~你上传图片到相册里,然后点击一张查看高清图,在它加载的时候右键点击,然后选复制图片地址,(一定要在下面的CLOSE图标出来之前),接着就可以引用图片的路径了..
果然需要技巧...
10 楼
junes_yu
2012-04-23
redstarofsleep 写道
果然需要技巧...
嘿嘿,手慢点也发现不了~
对了,请问怎么样实现把消息发给多个用户?我在onTextMessage方法里调用MessageInbound集合里子对象的getWsOutbound().writeTextMessage(msg)方法,但那个msg对象是Charbuffer类型,好像不能通过循环来发送给每个客户端(只能发给第一个客户端),然后msg就什么也没有了..
11 楼
redstarofsleep
2012-04-24
junes_yu 写道
redstarofsleep 写道
果然需要技巧...
嘿嘿,手慢点也发现不了~
对了,请问怎么样实现把消息发给多个用户?我在onTextMessage方法里调用MessageInbound集合里子对象的getWsOutbound().writeTextMessage(msg)方法,但那个msg对象是Charbuffer类型,好像不能通过循环来发送给每个客户端(只能发给第一个客户端),然后msg就什么也没有了..
这个你看上一篇基于Jetty的.那个时候写的是多客户端的.只要定义一个全局的List就可以了:
private static List<MyWebSocket> socketList;换成Tomcat应该是一样的.
http://redstarofsleep.iteye.com/blog/1307608
12 楼
junes_yu
2012-04-29
redstarofsleep 写道
这个你看上一篇基于Jetty的.那个时候写的是多客户端的.只要定义一个全局的List就可以了:
private static List<MyWebSocket> socketList;换成Tomcat应该是一样的.
http://redstarofsleep.iteye.com/blog/1307608
我已经有一个全局的List用来存放客户端了,但好像还是不行耶~请问如果有时间的话能做个简单的实例分享一下吗?谢谢...
13 楼
redstarofsleep
2012-05-08
junes_yu 写道
redstarofsleep 写道
这个你看上一篇基于Jetty的.那个时候写的是多客户端的.只要定义一个全局的List就可以了:
private static List<MyWebSocket> socketList;换成Tomcat应该是一样的.
http://redstarofsleep.iteye.com/blog/1307608
我已经有一个全局的List用来存放客户端了,但好像还是不行耶~请问如果有时间的话能做个简单的实例分享一下吗?谢谢...
我已经更新过了,你在看看!
14 楼
wlyfls
2012-05-10
请问lz,连接在空闲一断时间后自动终止怎么办?
15 楼
pch272215690
2012-05-17
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
16 楼
ffyy_0106
2012-06-10
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
heartbeat
17 楼
pch272215690
2012-06-13
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
heartbeat
请问你验证过吗,在js处发心跳?
18 楼
jxfsuda
2012-06-14
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
heartbeat
请问你验证过吗,在js处发心跳?
我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?
19 楼
yaolifei
2012-06-14
jxfsuda 写道
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
heartbeat
请问你验证过吗,在js处发心跳?
我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?
看了tomcat的bug list,
https://issues.apache.org/bugzilla/show_bug.cgi?id=53074
上面说trunk版本中已经解决了,所以就下了源代码进行编译,经测试已解决。不知道怎么贴附件,贴上网盘地址,我编译出的版本,暂且为7.0.28版本吧:http://115.com/file/an34jocc#apache-tomcat-7.0.28.rar
20 楼
jxfsuda
2012-06-15
yaolifei 写道
jxfsuda 写道
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?
我也遇到这种问题,不知何解。。。。
heartbeat
请问你验证过吗,在js处发心跳?
我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?
看了tomcat的bug list,
https://issues.apache.org/bugzilla/show_bug.cgi?id=53074
上面说trunk版本中已经解决了,所以就下了源代码进行编译,经测试已解决。不知道怎么贴附件,贴上网盘地址,我编译出的版本,暂且为7.0.28版本吧:http://115.com/file/an34jocc#apache-tomcat-7.0.28.rar
谢过兄台!~~
21 楼
jxfsuda
2012-06-15
做了浏览器兼容性的示例代码发在这里了
http://www.cnblogs.com/jifsu/archive/2012/06/15/2550603.html
用到的是flash.还需要另外开socket,有点麻烦.
http://www.cnblogs.com/jifsu/archive/2012/06/15/2550603.html
用到的是flash.还需要另外开socket,有点麻烦.