TangCuYu 2013-06-26
早就厌倦了Ajax轮询,一直想试试Web Socket.这次终于体验了一把
这次用的浏览器是Chrome,IE不用提了,不支持,FireFox据说是支持的,但是实际试下来不支持.估计是有自己的API,下次再研究....(以上提到的浏览器都是最新稳定版Chrome15,IE9,Firefox8.0)
开发环境:Eclipse3.7,Jetty8.04
先要说下在Eclipse中配置Jetty,这个着实花了一些时间.
首先,要先安装Jetty插件,不能在Server里搜索,如果直接点下图里的,自动搜到的Jetty插件只支持到6.而要支持Web Socket,Jetty至少要7.
所以,只能通过下面这URL手动安装Jetty插件:
http://download.eclipse.org/jetty/updates/jetty-wtp/development
在Eclipse里安装完Jetty插件后,就要按照Jetty了,Jetty其实不需要安装,下载下来就是一个压缩包,解压了就可以使用,但是不能放在含空格的路径下,比如放在program files目录下就不行,Eclipse里起Jetty就起不来.
还没完...,看一下Jetty的lib目录,里面除了Jar包,还有很多文件夹,这些文件夹里面还是Jar包.本来呢这也没什么,但是在 Eclipse里就悲剧了,它认不出来,不知道是插件的问题还是Eclipse本身的问题.要解决这个问题就得把那些文件夹里的Jar包拷出来,直接放在 Jetty的lib目录下.这样经过改装的Jetty,终于可以在Eclipse里启动了.
要使用WebSocket,光能在Eclipse中启动Jetty是不够的,还需要导入一个Jar包,把Jetty中lib下的jetty-websocket-8.0.4.v20111024.jar拷贝到项目的lib下.
这样子就有了2个Jetty,一个是直接解压出来的原版Jetty,如果要部署war包,就用这个.另一个是经过改装的,专用于Eclipse里调试.
真够麻烦的,Jetty终于搞定了.还是Tomcat方便,可惜Tomcat到7为止没有支持Web Socket.
搞定了Web服务器,现在可以开始写一些代码了.
顺着上面的,先来看服务器端的代码:
服务器端要提供Websocket就需要实现OnTextMessage,实现其中的三个方法:onOpen(),onMessage()和onClose().
onOpen在一个客户端连上来的时候调用
onClose在客户端断开时调用
onMessage在客户端发送消息时调用
除了这个Socket类之外,还需要一个Servlet来接收客户端请求,这个Servlet也不是传统的Servlet(要是传统的Servlet就可以用Tomcat咯),这个Servlet需要继承WebSocketServlet.
服务器端需要做的基本就这么多,接下来是前端HTML
与服务器端类似
首先需要实例化一个WebSocket对象,然后定义它的onOpen,onClose方法.需要发送消息时调用send方法.
下面,贴一下聊天室的代码:
首先有一个普通的Servlet执行初始化,主要是定义一个List,用户存放WebSocket对象:
public class InitServlet extends HttpServlet { private static final long serialVersionUID = -1936532122758235837L; private static List<MyWebSocket> socketList; public void init(ServletConfig config) throws ServletException { InitServlet.socketList = new ArrayList<MyWebSocket>(); super.init(config); System.out.println("Server start============"); } public static synchronized List<MyWebSocket> getSocketList() { return InitServlet.socketList; } }
然后写一个Servlet处理请求,这个Servlet就返回一个WebSocket对象:
public class MyWebSocketServlet extends WebSocketServlet { private static final long serialVersionUID = -7302427588920888589L; @Override public WebSocket doWebSocketConnect(HttpServletRequest request, String arg1) { return new MyWebSocket(); } }
最后实现WebSocket,循环InitServlet中的List,给所有客户端发送消息:
public class MyWebSocket implements OnTextMessage { private Connection conn; /* (non-Javadoc) * @see org.eclipse.jetty.websocket.WebSocket#onClose(int, java.lang.String) * 一个客户端断开时,从List中移除 */ @Override public void onClose(int arg0, String arg1) { InitServlet.getSocketList().remove(this); System.out.println("onClose=========================="); } /* (non-Javadoc) * @see org.eclipse.jetty.websocket.WebSocket#onOpen(org.eclipse.jetty.websocket.WebSocket.Connection) * 一个客户端连上来时,将它加入List */ @Override public void onOpen(Connection conn) { // 如果客户端在这个MaxIdleTime中都没有活动,则它会自动结束 System.out.println("onOpen=========================="+conn.getMaxIdleTime()); this.conn = conn; InitServlet.getSocketList().add(this); } /* (non-Javadoc) * @see org.eclipse.jetty.websocket.WebSocket.OnTextMessage#onMessage(java.lang.String) * 一个客户端发送数据后,触发它自己的onMessage方法,在这个方法里给所有在线的客户端发送这条消息 */ @Override public void onMessage(String data) { System.out.println("~~~~~~~~~~" + data); List<MyWebSocket> socketList = InitServlet.getSocketList(); for (MyWebSocket socket : socketList) { try { socket.getConn().sendMessage(data); } catch (IOException e) { e.printStackTrace(); } } } public Connection getConn() { return conn; } public void setConn(Connection conn) { this.conn = conn; } }
好,服务器端代码展示完毕,接下来是前端HTML:
最后附上web.xml
至此,一个具有基础功能的基于HTML5 Web Socket的简陋聊天室就做完了.