websocket(二)--简单实现网页版群聊

websocket可以实现服务端的消息推送,而不必在客户端轮询,大大的节省的资源,对于实时通讯来说简直是个大喜讯。

在上一篇文章中介绍了协议握手,这篇文章将通过实现简单的群聊来帮助进一步了解websocket。

注意:1.JavaEE版本为7.0

             2.tomcat版本为8.0 

             3.不需要额外导入其他的jar包 

             由于websocket不支持低版本的javaEE和tomcat,所以必须符合上述条件,我是在Myeclipse2014 的IDE中进行编码的。

             为了尽可能的使代码简洁以便更好的理解,所以代码中有些地方可能不全面,但不影响学习websocket。 

             首先是WebSocketServer类:

              

package socket;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/socket",configurator=GetHttpSessionConfigurator.class)  
public class WebSocketServer {
	
	private static final Set<WebSocketServer> onlineUsers =
            new CopyOnWriteArraySet<WebSocketServer>();  //静态变量 存储在线用户
	private HttpSession httpSession;
	private Session session;
	private String name;
	
	@OnMessage  
    public void onMessage(String message, Session session)   
        throws IOException, InterruptedException { 
	
		//将客户端传来的消息发送给所有在线用户
		sendMessageToAllOnline(session,this.name+" : "+message);
		
		//在控制台打印当前在线用户
		for(WebSocketServer webSocketServer:onlineUsers){
        	System.out.print(webSocketServer.name+"  ");
        }
        System.out.println();
    }  
      
    @OnOpen  
    public void onOpen (Session session, EndpointConfig config) throws IOException {  
        System.out.println("Client connected");  
        
        this.session = session;
        this.httpSession = (HttpSession) config.getUserProperties()
                .get(HttpSession.class.getName());
        this.name=(String) httpSession.getAttribute("name");
        onlineUsers.add(this);   //将用户信息添加到在线用户序列中
        
        //将上线消息发送给所有在线用户
        sendMessageToAllOnline(session,this.name+" 上线了");
        
    }  
  
    @OnClose  
    public void onClose(Session session) throws IOException{  
    	onlineUsers.remove(this);
        System.out.println("Connection closed"); 
        //将下线消息发送给所有在线用户
        sendMessageToAllOnline(session,this.name+" 下线了");
        
    }  
   /**
    * 发送信息给所有在线用户.
    * @param session
    * @param message
    */
   public void sendMessageToAllOnline(Session session,String message) throws IOException{
	   for (Session sess : session.getOpenSessions()){
	  		  if (sess.isOpen()){
	  			  sess.getBasicRemote().sendText(message);			  
	  		  }
	   }
   }
}
由于这里边的session和平时使用的httpsession不是同一个,所以为了可以获取httpsession以便获取当前用户的信息,所以需要下面的类:

package socket;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
/**
 * 为获取httpSession提供支持
 * @author nagsh
 *
 */
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator{
	@Override
    public void modifyHandshake(ServerEndpointConfig config,
                                HandshakeRequest request,
                                HandshakeResponse response){
        HttpSession httpSession = (HttpSession)request.getHttpSession();
        config.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

该类在websocket的@ServerEndpoint注解中引用。

为了可以获取登陆用户的信息以便实现群聊,简单的写了一个登陆,会将用户信息存到session中

客户端:

login.html

<!DOCTYPE html>
<html>
  <head>
    <title>login.html</title>
  </head>
  
  <body>
    <form action="servlet/LoginServlet" method="post">
               姓名:<input type="text" name="name"/>
       <input type="submit">
    </form>
  </body>
</html>

服务端:

package socket;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 处理用户的登陆.
 * @author nagsh
 *
 */
public class LoginServlet extends HttpServlet {

	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		
		String name = request.getParameter("name");
		//将当前用户的信息存入session中
		request.getSession().setAttribute("name",name);
		//重定向到聊天界面
		response.sendRedirect("/websockettest/socketClient.jsp");
	}

}

然后下面是简单的聊天界面(勿吐槽哈) 该页面是在上篇文章实现握手的页面基础上简单修改的:

socketClient.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
 <script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<script type="text/javascript">
	    /*   申请一个WebSocket对象,参数是需要连接的服务器端的地址 */
		var webSocket =  new WebSocket('ws://localhost:8080/websockettest/socket');

        /* 如果出现连接、处理、接收、发送数据失败的时候就会触发onerror事件 */
		webSocket.onerror = function(event) {
			onError(event)
		};
		
       /* 当websocket创建成功时,即会触发onopen事件 */
		webSocket.onopen = function(event) {
			onOpen(event)
		};
		
        /* 当客户端收到服务端发来的消息时,会触发onmessage事件,参数evt.data中包含server传输过来的数据 */
		webSocket.onmessage = function(event) {
			onMessage(event)
		};
		
        /* 当客户端收到服务端发送的关闭连接的请求时,触发onclose事件 */
        webSocket.onclose = function(event) {
			onMessage(event)
		};

		function onMessage(event) {
		   $("#messages").append(event.data+"<br/>");
		}

		function onOpen(event) {
		    $("#messages").append("成功建立连接...<br/>");
		    $("#messages").append(event.data);
			
		}

        function onClose(event) {
			$("#messages").append(event.data);
		}

		function onError(event) {
			alert("error");
		}
		
        //发送信息
        function send(){
            var content = $("#content").val();
            webSocket.send(content);      
        }
	</script>
<body>
	
	<div id="messages"></div>
	<input type="text" id="content">
	<input type="button" value="发送" onclick="send()">
	
</body>
</html>





版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-08-22 23:29  dingxiaoyue  阅读(838)  评论(1编辑  收藏  举报