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>
版权声明:本文为博主原创文章,未经博主允许不得转载。