您的位置:首页 > 其它

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

2015-08-22 23:29 453 查看
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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: