您的位置:首页 > Web前端 > HTML5

HTML5 WebSocket做聊天室(服务器端基于Jetty8)

2012-07-29 13:47 246 查看

HTML5 WebSocket做聊天室(服务器端基于Jetty8)

博客分类:
Web前端
Java
WebSocketHTML5JettyEclipse 

早就厌倦了Ajax轮询,一直想试试Web Socket.这次终于体验了一把

 

这次用的浏览器是Chrome,IE不用提了,不支持,FireFox据说是支持的,但是实际试下来不支持.估计是有自己的API,下次再研究....(以上提到的浏览器都是最新稳定版Chrome15,IE9,Firefox8.0)

 

开发环境:Eclipse3.7,Jetty8.04

 

[2012/4/6日更新:Tomcat从7.0.27开始已经支持WebSocket了,http://www.iteye.com/news/24773]

 

先要说下在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对象:

Java代码


 




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;   
    }   
  
}  

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对象:

Java代码


 




public class MyWebSocketServlet extends WebSocketServlet {
  
  
    private static final long serialVersionUID = -7302427588920888589L;
  
  
    @Override  
    public WebSocket doWebSocketConnect(HttpServletRequest request, String arg1) {   
        return new MyWebSocket();   
    }   
  
}  

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,给所有客户端发送消息:

Java代码


 




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;   
    }   
  
}  

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:

Html代码


 




<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=GBK">  
<title>Chart</title>  
<script type="text/javascript" src="../../js/jquery-1.7.1.min.js"></script>  
<script type="text/javascript">  
var ws = null;   
function startWebSocket() {   
    if (!window.WebSocket) alert("WebSocket not supported by this browser!");   
    // 创建WebSocket   
    ws = new WebSocket("ws://localhost:8080/html5chart/mywebsocket.do");   
    // 收到消息时在消息框内显示   
    ws.onmessage = function(evt) {      
        $('#msgBox').append(evt.data);   
        $('#msgBox').append('</br>');   
    };   
    // 断开时会走这个方法   
    ws.onclose = function() {    
        alert('close~~~~~~~');   
    };   
    // 连接上时走这个方法   
    ws.onopen = function() {      
        alert('open~~~~~~~~');    
    };   
}   
     
// 发送消息   
function sendMsg() {   
    var data = document.getElementById('msgSendBox').value;   
    ws.send(data);   
    document.getElementById('msgSendBox').value = '';   
       
}   
</script>  
</head>  
<body onload="startWebSocket();">  
<div id="msgBox" style="width:400px;height:300px;border:1px solid #000000">  
</div>  
<textarea id="msgSendBox" rows="5" cols="32"></textarea>  
<input type="button" value="send" onclick="sendMsg()"></input>  
</body>  
</html>  

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title>Chart</title>
<script type="text/javascript" src="../../js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
var ws = null;
function startWebSocket() {
if (!window.WebSocket) alert("WebSocket not supported by this browser!");
// 创建WebSocket
ws = new WebSocket("ws://localhost:8080/html5chart/mywebsocket.do");
// 收到消息时在消息框内显示
ws.onmessage = function(evt) {
$('#msgBox').append(evt.data);
$('#msgBox').append('</br>');
};
// 断开时会走这个方法
ws.onclose = function() {
alert('close~~~~~~~');
};
// 连接上时走这个方法
ws.onopen = function() {
alert('open~~~~~~~~');
};
}

// 发送消息
function sendMsg() {
var data = document.getElementById('msgSendBox').value;
ws.send(data);
document.getElementById('msgSendBox').value = '';

}
</script>
</head>
<body onload="startWebSocket();">
<div id="msgBox" style="width:400px;height:300px;border:1px solid #000000">
</div>
<textarea id="msgSendBox" rows="5" cols="32"></textarea>
<input type="button" value="send" onclick="sendMsg()"></input>
</body>
</html>

 

最后附上web.xml

Xml代码


 




<?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_2_5.xsd" id="WebApp_ID" version="2.5">  
  <display-name>html5test</display-name>  
  <welcome-file-list>  
    <welcome-file>index.html</welcome-file>  
  </welcome-file-list>  
    
  <servlet>  
    <servlet-name>initServlet</servlet-name>  
    <servlet-class>lhc.init.InitServlet</servlet-class>  
    <load-on-startup>1</load-on-startup>  
  </servlet>  
  <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>  
</web-app>  

<?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_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>html5test</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>initServlet</servlet-name>
<servlet-class>lhc.init.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<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>
</web-app>

 

至此,一个具有基础功能的基于HTML5 Web Socket的简陋聊天室就做完了.

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐