聊天室演示地址
使用jsp做一个聊天室,一开始想到做一个聊天室时本想使用udp或是tcp发送数据包实现,使用线程来接收,但是做到最后,在获取到数据怎么实时的显示到浏览器呢,这种在客户端程序或许比较使用,但在web并不好交互,怎么想都不好实现,于是查看别人例子,发现通过websocket可以很好的实现,websocket逆向思维,一般都是由客户端发送请求到服务器,再有服务器发送响应到客户端,而客户端和服务器端建立了websocket连接后,允许服务器直接发送消息给客户端,以此实现web端实时接收来自服务器的数据, WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议
那么聊天室的大致实现思路是这样的,,客户端和服务器端建立了websocket连接后,只要服务器接收到来自客户端的消息,就把收到的消息转发给所有的客户端,当然可以筛选下,不要发给自己本身,总的来说就是使用服务器做中转。
运行结果图
前端代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<%
String userName = request.getParameter("name");
if (userName != null) {
session.setAttribute("userName", userName);
response.sendRedirect("Chat-room.jsp");
}
%>
<form id="myform" action="index.jsp" method="post">
姓名:<input id="name" name="name" type="text" /><input type="submit" value="开始聊天" />
</form>
<script>
document.getElementById('myform').onsubmit=function()
{
return fun();
}
function fun()
{
if(document.getElementById('name').value=="")
return false;
return true;
}
</script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
<link type="text/css" rel="stylesheet" href="css/style.css" />
<script src="scripts/jquery-3.3.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
function setReceiver(obj) {
document.getElementById("reply-to").innerHTML = "接收人:" + obj.innerHTML;
}
</script>
</head>
<body>
<div id="chat-room">
<div class="lefter">
<h2>在线用户列表</h2>
<ul id="userlist">
</ul>
</div>
<div class="righter">
<div id="history">
</div>
<div class="spacer"></div>
<div id="reply-to">接收人:所有 <span id="message"></span></div>
<div class="reply">
<input id="username" hidden="hidden" value=<%=new String(session.getAttribute("userName").toString().getBytes("iso-8859-1"),"utf-8")%> type="text"/>
<input type="text" class="text" id="sendmessage" name="content" /><label
class="ui-blue"><input type="button" id="sendbtn" value="发送" /></label>
</div>
</div>
</div>
<script type="text/javascript">
setInterval("getuser()", 50)
function getuser() {
$.ajax({
type:'get',
url:'RoomUser',
async:false,
error:function(data){
alert('发生错误');
},
success:function(data){
$('#userlist').html(data);
}
});
}
var websocket = null;
var userName =document.getElementById('username').value;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/Chat/websocket?username="+userName);
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
setMessageInnerHTML("连接成功,可以开始聊天了");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
document.getElementById('history').innerHTML+= "<p style='float:left'>"+event.data+"</p></br>";
}
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML= innerHTML + '<br/>';
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
document.getElementById("sendbtn").onclick=function(){
var message = document.getElementById('sendmessage').value;
document.getElementById('sendmessage').value="";
websocket.send(message);
document.getElementById('history').innerHTML+= "<p style='float:right'>我说:"+message+"</p></br>";
};
</script>
</body>
</html>
后台代码
package com.websocket;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Set;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
/**
* @ServerEndpoint 注解标识该类是websocket类
*/
@ServerEndpoint("/websocket")
public class WebSocketTest {
//将用户的名字和每个websocket连接存在map集合中,static修饰,其他类可以直接调用
private static HashMap<String, WebSocketTest> webSocketMap = new HashMap<String, WebSocketTest>();
//session保存用户请求过来的信息
private Session session;
private String userName;
/**
*
*
* @param session
* 当有客户端与服务器建立连接时调用
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
try {
this.userName = URLDecoder.decode(session.getQueryString().substring(session.getQueryString().indexOf("=") + 1),"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
webSocketMap.put(this.userName, this); //加入用户姓名和此连接
}
/**
*与服务器连接关闭时调用
*/
@OnClose
public void onClose() {
webSocketMap.remove(this.userName);
}
/**
*
*
* @param message
* @param session
* 收到来自客户端的消息时调用,session保存发送消息的客户端信息
*/
@OnMessage
public void onMessage(String message, Session session) {
String messageUser=null;
try {
messageUser = URLDecoder.decode(session.getQueryString().substring(session.getQueryString().indexOf("=") + 1), "UTF-8");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Ⱥ����Ϣ
Set<String> keys = webSocketMap.keySet();
for (String key : keys) {
if (!key.equals(messageUser)) {
try {
webSocketMap.get(key).sendMessage(messageUser+"说:"+message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
continue;
}
}
}
}
/**
*发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
// this.session.getAsyncRemote().sendText(message);
}
public static synchronized Set<String> getUser() {
return webSocketMap.keySet();
}
}
package com.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.websocket.WebSocketTest;
@WebServlet("/RoomUser")
public class RoomUser extends HttpServlet {
private static final long serialVersionUID = 1L;
//前台调用此方法获取在线用户列表
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
Set<String> users = WebSocketTest.getUser();
StringBuffer str = new StringBuffer();
for (String username : users) {
str.append("<li><a href=# onclick=setReceiver(this)>" + username + "</a></li>");
}
PrintWriter out=response.getWriter();
out.println(str);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
评论区