jetty部署websocket实现聊天器功能

    jetty是一个轻量级的可嵌入的web服务器,他对websocket的支持也是非常好的,下面就介绍如何通过jetty服务器的websocket实现聊天室功能:

一、后台实现

      后台使用的springMVC,具体的搭建可以看

http://dwj147258.iteye.com/blog/2328962,在这里web.xml文件中需要加入servlet

<servlet>
		<servlet-name>websocket</servlet-name>
		<servlet-class>main.java.test.websocket.WebSocketInitServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>websocket</servlet-name>
		<url-pattern>/websocket.ws</url-pattern>
	</servlet-mapping>
  	<servlet> 

 来拦截来自前端的websocket请求,这里的servlet类WebSocketInitServlet代码实现如下,

package main.java.test.websocket;

import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.websocket.WebSocketServlet;

public class WebSocketInitServlet extends WebSocketServlet {
	private static final long serialVersionUID = -7302427588920888589L;
	/**
	 * websocket建立连接
	 */
	@Override
	public WebSocket doWebSocketConnect(HttpServletRequest request, String arg1) {
		return new WebSocket();
	}
}

 覆盖了一个dowebsocketconnect方法,返回的webSocket对象则是具体的websocket业务处理了,代码实现如下

package main.java.test.websocket;

import java.util.List;

import net.sf.json.JSONObject;
import org.eclipse.jetty.websocket.WebSocket.OnTextMessage;

import com.sun.istack.internal.logging.Logger;

public class WebSocket implements OnTextMessage {

	private static final Logger log = Logger.getLogger(WebSocket.class);
	
	/**
	 * websocket连接
	 */
	private Connection conn = null;
	
	private String key ; 
	/**
	 * websocket关闭事件触发
	 */
	@Override
	public void onClose(int arg0, String arg1) {
		log.info("onClose begin.  arg0:"+arg0+" arg1:"+arg1+" conn:"+conn);
		WebSocketManager.getInstance().removeWebSocket(key);
		log.info("onClose end.  arg0:"+arg0+" arg1:"+arg1+" conn:"+conn);	
	}

	/**
	 * websocket连接建立触发
	 */
	@Override
	public void onOpen(Connection conn) {
		// 如果客户端在这个MaxIdleTime中都没有活动,则它会自动结束
		log.info("WebSocket onOpen. conn:"+conn.toString()+""+ conn.getMaxIdleTime()+" class:"+conn.getClass());
		conn.setMaxIdleTime(Integer.MAX_VALUE);
		String toStr = conn.toString();
		String name = toStr.substring(toStr.indexOf("(")+1, toStr.indexOf(")"));
		this.key = name ;
		this.conn = conn;
		WebSocketManager.getInstance().addWebSocket(this);
		System.out.println("服务端websocket连接建立"+conn.getProtocol()+"  "+conn.toString());
	}

	/**
	 * websocket收到消息触发
	 */
	@Override
	public void onMessage(String data) {
		
		/*log.info("onMessage. receive a Messag:" + data);
		JSONObject jsonObject = JSONObject.fromObject(data);
		System.out.println("name="+jsonObject.getString("name")+"  age="+jsonObject.getString("age"));
		WebSocketMessage webSocketMessage = (WebSocketMessage)JSONObject.toBean(jsonObject, WebSocketMessage.class);	
		OnMessageThread onMessageThread =new OnMessageThread(this,webSocketMessage);
		new Thread(onMessageThread).start();
		String jsonMsg = JSONObject.fromObject(jsonObject).toString();
		sendMessage(jsonMsg) ;*/
		WebSocketManager.getInstance().sendAllMessage(data);
	}
	
	/**
	 * websocket发送消息接口
	 * @param message
	 */
	public void sendMessage(String message){
		try{
			log.info("sendMessage. message:"+message);
			conn.sendMessage(message);
		}catch(Exception e){
			log.warning("sendMessage error,close the conn and clear the resource. msg:"+e.getMessage(),e);
			closeConnection();
		}
	}
	
	/**
	 * 关闭连接
	 */
	private void closeConnection(){
		conn.close();
	}
	
	public String getKey(){
		return key ;
	}
	
}

 在这里,还需用到一个管理websocket的类,WebSocketManager,代码如下

package main.java.test.websocket;

import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketManager {
	private ConcurrentHashMap<String , WebSocket> websockts = new ConcurrentHashMap<String , WebSocket>();
	
	private static WebSocketManager instance ; 
	
	public static WebSocketManager getInstance(){
		if(instance == null ){
			instance = new WebSocketManager();
		}
		return instance ;
	}
	
	private WebSocketManager(){}
	
	public void addWebSocket(WebSocket ws){
		websockts.put(ws.getKey(), ws);
	}
	
	public void removeWebSocket(String key ){
		websockts.remove(key);
	}
	
	public void sendAllMessage(String message){
		for(Entry<String, WebSocket> entry : websockts.entrySet()){
			entry.getValue().sendMessage(message);
		}
	}
}

 到这里,来自前端的消息都会进入websocket的onmessage方法中,然后websocket会全部转发出去

二、前端实现

     首先前端页面需要一个页面来显示接收的消息,并需要一个文本域来输入发送的消息,页面代码如下

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Home</title>
<meta charset="utf-8">
    <title>WebSocket简单实例</title>
    <style>body{text-align:center}</style>
</head>
<body>
	<textarea id="receive" cols="80" rows="20" readonly="true"></textarea><br>
	<textarea id="send" cols="80" rows="8"></textarea><br>
	<input style="height:36px;width:80px" type="button" id="loginng" value="发送" onclick="send()"><br>
</body>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/common.js"></script>
<script type="text/javascript" src="/js/webchannel.js"></script>
</html>
在这里,用到了webchannel.js,这个就是连接服务器websocket的js实现,如下,
var Webchannel = {
    wso: "",
    wsUrl: "ws://" + window.location.host + "/websocket.ws",
    busiTypes: {},
    initWebsocket: function () {
        if ("WebSocket" in window) {
            wso = new WebSocket(Webchannel.wsUrl);
        } else if ("MozWebSocket" in window) {
            wso = new MozWebSocket(Webchannel.wsUrl);
        } else {
            console.log("The browser don't support the WebSocket");
        }
        wso.onopen = function () {
            console.log("connect success");
        };
        wso.onclose = function () {
        	try{ 
                wso = new WebSocket(Webchannel.wsUrl); 
            }catch(e){ 
                console.log("disconnect error"+e); 
            } 
            console.log("disconnect success");
        };
        wso.onerror = function () {
            console.log("sorry,it get error");
        };
        wso.onmessage = function (receiveMsg) {
        	var str = $("#receive").val();
        	var reMsg = receiveMsg.data.substring(1 ,receiveMsg.data.length-1);
        	$("#receive").val(str+"\n"+reMsg);
        }
    },
    sendMsg:function(data){
    	var jsonData= JSON.stringify(data);
    	wso.send(jsonData);
    },

    closeWebSocket: function () {
        if (1 == wso.readyState) {
            wso.close();
            wso = "";
        }
    },
    regBusitype: function (busiType, backFunction) {
        Webchannel.busiTypes[busiType] = backFunction;
    }
};
Webchannel.initWebsocket();
function send(){
	var data = $("#send").val();
	$("#send").val("");
	Webchannel.sendMsg(data);
	
}
 

 在这个js中,打开页面就会进行一个websocket初始化,连接服务器,点击页面上的发送按钮就会调用js中的send方法,send方法获取页面中需要发送的内容,然后调用wensocket方法发送消息给服务器,

这样就实现了网页版的群聊功能

猜你喜欢

转载自dwj147258.iteye.com/blog/2329438