AJAX+js实现实时聊天

chatClient.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>聊天案例</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">

<!-- js部分,本应在一个js文件里,这里为了演示方便,放在一起 -->
<script type="text/javascript">

	/* ajax生成后台访问的http对象 */
	function getXmlHttpObject() {
		var xmlHttp = null;
		try {
			// Firefox, Opera 8.0+, Safari
			xmlHttp = new XMLHttpRequest();
		} catch (e) {
			// Internet Explorer
			try {
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		return xmlHttp;
	}
	
	/* ajax执行方法,访问servlet, */
	function getServerInfo() {
		http = getXmlHttpObject();
		var url = "getmsg?time=" + Math.random();
		http.onreadystatechange = getInfoBack;
		http.open("GET", url, true);
		http.send(null);
	}
	
	/* 消息返回执行方法, */
	function getInfoBack() {
		if (http.readyState == 4) {
			if (http.status == 200) {
				//获取返回的消息字符串
				var response = http.responseText;
				//通过id找到聊天显示框把消息显示出来
				document.getElementById("chatbox").innerHTML += response
						+ "\r\n";
				//再次执行getServerInfo方法访问servlet
				getServerInfo();
			}
		}
	}
	
	/* 点击发送按钮执行,提交表单,把输入框清空,消息显示框显示到最底部
	@param o输入框的id */
	function sendok(o) {
		//提交表单(直接使用form表单的名字)
		myform.submit();
		//通过传来的输入框的id参数o把输入框的内容清空
		document.getElementById(o).value = "";
		//用txt保存聊天显示框的对象
		var txt = document.getElementById("chatbox");
		//设置显示框显示在最底部
		txt.scrollTop = txt.scrollHeight;
	}
</script>
</head>

<!-- 加载时就执行getServerInfo方法,监听是否有数据输入 -->
<body οnlοad="getServerInfo()">
	聊天内容:
	<br>
	
	<!-- textarae显示聊天内容,设置id方便访问该标签,设置disabled让文本框不可以输入数据,设置style背景色为白色(这些在css里设置,这里为了演示方便) -->
	<textarea id="chatbox" rows="10" cols="50" disabled="disabled"
		style="background-color: white;"></textarea>
	<br>
	
	<!-- 用表单来提交数据,设置name方便访问,action为servlet地址,target为跳转下面设置的页面“sform”,相当于不跳转 -->
	<form name="myform" method="post" action="sendmsg" target="sform">
	
		<!-- 输入框完成消息输入 -->
		<input id="msginput" type="text" name="chatmsg" />
		
		<!-- 发送按钮,点击执行sendok()方法 -->
		<input type="button" value="发送" οnclick="sendok('msginput')" />
	</form>
	
	<!-- 设置一个空iframe,让表单提交后不跳转, -->
	<iframe width="0" height="0" style="display: none" name="sform"></iframe>
</body>
</html>


chatdemo_message.java
package chat.classinfo;
/* 封装消息对象的类,这里为了演示就只设置了message一个属性 ,提供相应的set、get方法*/
public class Message {
	private String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

}

chatdemo_getmsg.jsva
package chat.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import chat.classinfo.Message;

/* 监听是否有消息输入,当页面加载时就会用AJAX访问该servlet, */
public class GetMsgServlet extends HttpServlet {
	// 用一个Hashtable保存正在监听消息的客户端,键为每个客户端的session,值为消息对象
	public static Hashtable<String, Message> waitList = new Hashtable<String, Message>();

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

	/* 消息监听,如果没有消息就会等待,当发送消息的servlet执行后会释放该同步锁 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 保存Message对象
		Message msg = new Message();
		// 把该对象与相应的session放到Hashtable中,
		waitList.put(request.getSession(true).getId(), msg);
		// 消息同步,消息刚刚创建是没有任何内容的,所以一定会先进入等待状态,等到消息值放进去之后再执行后面的操作
		synchronized (msg) {
			try {
				// 同步等待
				msg.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		// 当执行到这一步时,就说明消息同步已被唤醒,就说明msg里面已经把消息内容放进去了。
		// 设置返回编码
		response.setCharacterEncoding("utf-8");
		// 用pw保存返回输出对象
		PrintWriter pw = response.getWriter();
		// 把消息内容通过输出对象输出
		pw.print(msg.getMessage());

		// 把输出对象清空关闭
		pw.flush();
		pw.close();
	}

}

chatdemosendmsg.jsva
package chat.servlet;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import chat.classinfo.Message;

/* 当点击发送按钮提交表单执行该servlet,对消息进行处理 */
public class SendMsgSrevlet 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 {
		// 设置传过来的数据编码
		request.setCharacterEncoding("utf-8");
		// 得到由输入的消息内容
		String chatmsg = request.getParameter("chatmsg");
		// 通过Set(Hashtable键)获取所有正在等待的session列表,方便使用迭代器
		Set<String> sessions = GetMsgServlet.waitList.keySet();
		// 使用迭代器Iterator方便遍历到所有的等待session
		Iterator<String> sessionsIt = sessions.iterator();
		// 遍历所有等待的session对象
		while (sessionsIt.hasNext()) {
			// 获取每一个等待的sessionid
			String sessionId = sessionsIt.next();
			// 通过sessionid获取该等待session的消息对象
			Message msg = GetMsgServlet.waitList.get(sessionId);
			// 在把输入框传过来的消息内容放进消息对象中时,可以用迭代器方便的把该等待session从等待列表中移除
			sessionsIt.remove();
			// 把消息内容放进消息对象,把同步消息唤醒
			msg.setMessage(chatmsg);
			// 同步唤醒所有正在等待的消息对象
			synchronized (msg) {
				msg.notifyAll();
			}
		}
	}
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值