ajax版聊天室

 

 ajax版聊天室大致思路

步骤1.

点击发送按钮发送消息(即ajax通过post方式,把消息insert到数据库的聊天表中)

xhr.open('post', url, true);

xhr.send(messageData);

步骤2.

通过ajax读取数据库中的聊天表的数据

xhr.open('get', url, true);
xhr.send(null);

步骤3.

通过setInterval()函数,每隔几秒钟就用ajax读取数据库中的聊天表的数据(即setInterval(步骤2, 2000))

数据库中chat表是聊天表,表设计的比较简略,表不是我们的重点,我们今天的重点是学习ajax

 

发送消息的js代码如下:

//发送消息
document.getElementById('send').onclick = function() {
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		if(this.readyState == 4 && this.status == 200){
			console.log(xhr.responseText);
			if(xhr.responseText == 1){
				document.getElementById('messageBox').value = '';
				document.getElementById('whetherSendSucceed').innerHTML = '发送成功';
				document.getElementById('whetherSendSucceed').style.display = 'inline';
				setTimeout(hideWhetherSendSucceedBox, 2000);
			}
		}
	}
	var url = '/ajax/ajaxChatServlet';
	xhr.open('post', url, true);
	xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded');
	var messageInfo = document.getElementById('messageBox').value;
	//userId和userName的值,我这里写死了,主要是为了测试,图个方便
	var messageData = 'flag=save&userId=88&userName=jack&message=' + messageInfo;
	console.log(messageData);
	xhr.send(messageData);
}

读取聊天消息的js代码如下:

/*
间隔时间别设置太长了,要不然最新的聊天记录会被延迟;
间隔时间也别设置太短了,要不然频繁的请求数据库,数据库压力会很大
*/
//刷新聊天记录,每隔3秒钟就去数据库中获取最新的聊天记录
setInterval(refreshMessage, 3000);

function refreshMessage() {
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
//见鬼了,火狐浏览器测试出来的结果,readyState打印出来是4,status打印出来是0,status一般是200或者404或者500之类的,为什么会是0
//大家可以去网上搜一下,为什么status会是0
		console.log(this.readyState, this.status);//4 0
		console.log(this.responseText, typeof this.responseText);//<empty string> string
		console.log(this.responseText == '', this.responseText === '');//true true
		console.log(this.responseText == null, this.responseText === null);//false false
		console.log(typeof '', typeof null, typeof undefined);//string object undefined
		console.log(typeof '{}', typeof '[]', typeof {}, typeof []);//string string object object
		
		//所以,最好还是加上this.status == 200这句话
		if(this.readyState == 4 && this.status == 200){
			console.log('服务端返回的内容:' + this.responseText);
			var json = this.responseText;
			console.log('json=' + json);
// 			var jsonObj = eval(json);
			var jsonObj = eval('(' + json + ')');
			console.log('***********************************');
			
			//以下代码都是测试代码
			var test = [{}, {}];
			console.log(json, json.length);
			console.log(jsonObj, jsonObj.length);
			console.log(test, test.length);
			console.log(typeof json, typeof jsonObj, typeof test);
			console.log(json instanceof Object, jsonObj instanceof Object, test instanceof Object);
			console.log(json instanceof Array, json instanceof Object);
			var test2 = '[{}, {}]';
			console.log(test2, test2.length, typeof test2);
			var jsonTest2 = eval('(' + test2 + ')');
			console.log(jsonTest2, jsonTest2.length, typeof jsonTest2);
			var json_Test2 = eval(test2);
			console.log(json_Test2, json_Test2.length, typeof json_Test2);
			//
			
			var showMessageDiv = document.getElementById("showMessageBox");
			var messageCount = jsonObj.length;
			var str = '';
			for (var index = 0; index < messageCount; index++) {
				var mesg = jsonObj[index];
				console.log(mesg.userId + '/' + mesg.userName + '/' + mesg.message + '/' + mesg.sendTime);
				str += '<font color="blue">用户id:' + mesg.userId + '&nbsp;&nbsp;&nbsp;' + '用户名:' + mesg.userName + '&nbsp;&nbsp;&nbsp;' + '发言时间:' + mesg.sendTime + '</font><br />';
				str += mesg.message + '<br /><br />';
			}
			showMessageDiv.innerHTML = str;
			//div的滚动条自动保持在底部,这样就可以直接看到最新的聊天记录,不用手动把滚动条拉到底部
			//参考https://www.jb51.net/article/93425.htm
			//参考https://blog.csdn.net/wybshyy/article/details/52064362
			//参考https://blog.csdn.net/sdfadfsdf/article/details/80281736
			showMessageDiv.scrollTop = showMessageDiv.scrollHeight;
		}
	}
	var url = '/ajax/ajaxChatServlet?randomNumber=' + Math.random();
	xhr.open('get', url, true);
	xhr.send(null);
}

以下是完整的代码! 

ajaxChat.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ajax版聊天室</title>
<link rel="stylesheet" type="text/css" href="../css/body.css" />
<link rel="stylesheet" type="text/css" href="../css/mark.css" />
<link rel="stylesheet" type="text/css" href="../css/input2.css" />
<link rel="stylesheet" type="text/css" href="../css/console.css" />
</head>
<body>
<h1>ajax版聊天室</h1>
<div class="testDiv3" id="showMessageBox" style="width: 70%;height: 350px;">
</div>
<textarea rows="" cols="" id="messageBox" style="width: 70%;height: 60px;">
请在此输入聊天内容,点击发送即可!
</textarea>
<br />
<input type="button" id="send" style="width: 150px;height: 40px;" value="发送" />
<div id="whetherSendSucceed" style="border-width: 2px; display: none;" class="testDiv2">
</div>
<br /><br />
<h1>测试闭包</h1>
<input type="button" id="button1" value="测试闭包" />
<br /><br />
<input type="text" id="input1" value="江西省赣州市于都县" />
<br /><br />
<input type="text" id="input2" value="江西于都县" />
<br /><br />
</body>
<script type="text/javascript">
document.getElementById('messageBox').onfocus = function() {
	//replace(/\s+/g,""); //去除所有空格
	if (this.value.replace(/\s+/g, '') == '请在此输入聊天内容,点击发送即可!') {
		this.value = '';
	}
}

function hideWhetherSendSucceedBox() {
	document.getElementById('whetherSendSucceed').style.display = 'none';
}

//发送消息
document.getElementById('send').onclick = function() {
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		if(this.readyState == 4 && this.status == 200){
			console.log(xhr.responseText);
			if(xhr.responseText == 1){
				document.getElementById('messageBox').value = '';
				document.getElementById('whetherSendSucceed').innerHTML = '发送成功';
				document.getElementById('whetherSendSucceed').style.display = 'inline';
				setTimeout(hideWhetherSendSucceedBox, 2000);
			}
		}
	}
	var url = '/ajax/ajaxChatServlet';
	xhr.open('post', url, true);
	xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded');
	var messageInfo = document.getElementById('messageBox').value;
	//userId和userName的值,我这里写死了,主要是为了测试,图个方便
	var messageData = 'flag=save&userId=88&userName=jack&message=' + messageInfo;
	console.log(messageData);
	xhr.send(messageData);
}

/*
间隔时间别设置太长了,要不然最新的聊天记录会被延迟;
间隔时间也别设置太短了,要不然频繁的请求数据库,数据库压力会很大
*/
//刷新聊天记录,每隔3秒钟就去数据库中获取最新的聊天记录
setInterval(refreshMessage, 3000);

function refreshMessage() {
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
//见鬼了,火狐浏览器测试出来的结果,readyState打印出来是4,status打印出来是0,status一般是200或者404或者500之类的,为什么会是0
//大家可以去网上搜一下,为什么status会是0
		console.log(this.readyState, this.status);//4 0
		console.log(this.responseText, typeof this.responseText);//<empty string> string
		console.log(this.responseText == '', this.responseText === '');//true true
		console.log(this.responseText == null, this.responseText === null);//false false
		console.log(typeof '', typeof null, typeof undefined);//string object undefined
		console.log(typeof '{}', typeof '[]', typeof {}, typeof []);//string string object object
		
		//所以,最好还是加上this.status == 200这句话
		if(this.readyState == 4 && this.status == 200){
			console.log('服务端返回的内容:' + this.responseText);
			var json = this.responseText;
			console.log('json=' + json);
// 			var jsonObj = eval(json);
			var jsonObj = eval('(' + json + ')');
			console.log('***********************************');
			
			//以下代码都是测试代码
			var test = [{}, {}];
			console.log(json, json.length);
			console.log(jsonObj, jsonObj.length);
			console.log(test, test.length);
			console.log(typeof json, typeof jsonObj, typeof test);
			console.log(json instanceof Object, jsonObj instanceof Object, test instanceof Object);
			console.log(json instanceof Array, json instanceof Object);
			var test2 = '[{}, {}]';
			console.log(test2, test2.length, typeof test2);
			var jsonTest2 = eval('(' + test2 + ')');
			console.log(jsonTest2, jsonTest2.length, typeof jsonTest2);
			var json_Test2 = eval(test2);
			console.log(json_Test2, json_Test2.length, typeof json_Test2);
			//
			
			var showMessageDiv = document.getElementById("showMessageBox");
			var messageCount = jsonObj.length;
			var str = '';
			for (var index = 0; index < messageCount; index++) {
				var mesg = jsonObj[index];
				console.log(mesg.userId + '/' + mesg.userName + '/' + mesg.message + '/' + mesg.sendTime);
				str += '<font color="blue">用户id:' + mesg.userId + '&nbsp;&nbsp;&nbsp;' + '用户名:' + mesg.userName + '&nbsp;&nbsp;&nbsp;' + '发言时间:' + mesg.sendTime + '</font><br />';
				str += mesg.message + '<br /><br />';
			}
			showMessageDiv.innerHTML = str;
			//div的滚动条自动保持在底部,这样就可以直接看到最新的聊天记录,不用手动把滚动条拉到底部
			//参考https://www.jb51.net/article/93425.htm
			//参考https://blog.csdn.net/wybshyy/article/details/52064362
			//参考https://blog.csdn.net/sdfadfsdf/article/details/80281736
			showMessageDiv.scrollTop = showMessageDiv.scrollHeight;
		}
	}
	var url = '/ajax/ajaxChatServlet?randomNumber=' + Math.random();
	xhr.open('get', url, true);
	xhr.send(null);
}

function fn1(){
	
	console.log(eval("{}")); //undefined
	console.log(eval('{}')); //undefined
	console.log(eval("({})")); //Object {  }
	console.log(eval('({})')); //Object {  }
	console.log(eval("(" + "{}" + ")")); //Object {  }
	console.log(eval('(' + '{}' + ')')); //Object {  }
// 	console.log(eval("(" + "{[]}" + ")")); //报错SyntaxError: expected expression, got ']'
// 	console.log(eval('(' + '{[]}' + ')')); //报错SyntaxError: expected expression, got ']'
	console.log(eval({})); //Object {  }
	console.log(eval({name:"jack"})); //Object { name: "jack" }
	console.log(eval('{name:"tom"}')); //tom
	console.log(eval("{name:'jerry'}")); //jerry
	var test = '{[], [], []}';
	console.log(eval(test)); //Array []
// 	console.log(eval('(' + test + ')')); //报错SyntaxError: expected expression, got ']'
// 	console.log(eval("(" + test + ")")); //报错SyntaxError: expected expression, got ']'

	var test2 = '{}';
	console.log(eval(test2)); //undefined
	console.log(eval('(' + test2 + ')')); //Object {  }
	console.log(eval("(" + test2 + ")")); //Object {  }
	
	var test6 = {};
	console.log(eval(test6)); //Object {  }
// 	console.log(eval('(' + test6 + ')')); //报错SyntaxError: missing ] after element list
// 	console.log(eval("(" + test6 + ")")); //报错SyntaxError: missing ] after element list
	
	var test3 = '[{}, {}]';
	console.log(eval(test3)); //Array [ {}, {} ]
	console.log(eval('(' + test3 + ')')); //Array [ {}, {} ]
	console.log(eval("(" + test3 + ")")); //Array [ {}, {} ]
	
	var test8 = {};
	//true false
	console.log(test8 instanceof Object, test8 instanceof Array);
	console.log(typeof test8); //object
	
	var test9 = [];
	//true true
	console.log(test9 instanceof Object, test9 instanceof Array);
	console.log(typeof test9); //object
	
}

fn1();

function fn2(){
	return 'hello';
}

var a = fn2();
console.log(a); //hello

function fn3(){
	return fn2();
}

var b = fn3();
console.log(b); //hello

function fn4(){
	var v = function fn5(){
		return '江西省赣州市于都县';
	}
	return v;
}

var result = fn4();
console.log(result); //function fn5()
console.log(result()); //江西省赣州市于都县

/*
打印出
******我是fn7(),我执行了******
江西于都县666
*/
console.log((function fn6(){
	var f = function fn7(){
		console.log('******我是fn7(),我执行了******');
		return '江西于都县666';
	}
	return f;
})()());


//测试闭包
document.getElementById('button1').onclick = function() {
	var inputNodes = document.getElementsByTagName('input');
	var count = inputNodes.length;
	for (var index = 0; index < count; index++) {
		var inputNode = inputNodes[index];
		console.log(inputNode, inputNode.type);
		console.log('*******************');
		if (inputNode.type == 'text') {
			inputNode.onclick = (function(parameter) {
// 				alert('--' + index);
// 				alert('==' + parameter);
				return fn9(parameter);
			})(index);
		}
	}
};

//测试闭包
function fn9(param){
	var f = function fn10() {
		alert(param);
	}
	return f;
}

function fn8() {
console.log('(' + null + ')'); //(null)
console.log(typeof ('(' + null + ')')); //string
console.log('(' + 666 + ')'); //(666)
// console.log('(' + abc + ')'); //ReferenceError: abc is not defined
console.log('(' + 'null' + ')'); //(null)
console.log(typeof ('(' + 'null' + ')')); //string
console.log(eval('(' + null + ')')); //null
console.log(eval('(null)')); //null
// console.log(eval('(' + '' + ')')); //SyntaxError: expected expression, got ')'
console.log(eval('(' + undefined + ')')); //undefined
// console.log(eval('(' + ')')); //SyntaxError: expected expression, got ')'
// console.log(eval('()')); //SyntaxError: expected expression, got ')'
}

fn8();
</script>
</html>

AjaxChat类

package com.jiongmeng.ajax;

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

import javax.servlet.ServletConfig;
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.jiongmeng.dao.ChatDAO;
import com.jiongmeng.entity.Chat;

import net.sf.json.JsonConfig;

/**
 * ajax版聊天室
 */
@WebServlet("/ajaxChatServlet")
public class AjaxChat extends HttpServlet {
	private static final long serialVersionUID = 1L;
	public static final String AJAX_POST_ENCODE = "UTF-8";

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding(AJAX_POST_ENCODE);
		PrintWriter pw = response.getWriter();
		String flag = request.getParameter("flag");
		String userId = request.getParameter("userId");
		String userName = request.getParameter("userName");
		String message = request.getParameter("message");
		System.out.println("userId=" + userId + " userName=" + userName + " message=" + message);
		ChatDAO chatDAO = new ChatDAO();
		if ("save".equals(flag)) {
			Chat chat = new Chat(0, Integer.parseInt(userId), userName, message, null);
			int effectRows = chatDAO.saveChat(chat);
			pw.print(effectRows);
		}else{
		//获得所有聊天内容
		String json = chatDAO.queryChatToJson();
		try {
			// 模拟网络慢的情况
			Thread.sleep(3000);
		} catch (InterruptedException e) { 
			e.printStackTrace();
		}
		pw.print(json);
	 }
		pw.flush();
		pw.close();
	}

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

	@Override
	public void init(ServletConfig config) throws ServletException {

	}

}

ChatDAO类

package com.jiongmeng.dao;

import java.sql.Connection;
import java.util.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jiongmeng.entity.Chat;
import com.jiongmeng.tool.DateTool;
import com.jiongmeng.tool.JsonDateValueProcessor;

import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;

//从mysql数据库中读取出数据并封装成json
public class ChatDAO {
	//
	public List<Chat> queryChat() {
		List<Chat> list = new ArrayList<Chat>();
		DBManger dbManger = new DBManger();
		String sql = "select id, userId, userName, message, sendTime from chat";
		ResultSet rs = dbManger.query(sql);
		try {
			while (rs.next()) {
				int id = rs.getInt("id");
				int userId = rs.getInt("userId");
				String userName = rs.getString("userName");
				String message = rs.getString("message");
				Date sendTime = rs.getTimestamp("sendTime");
				Chat chat = new Chat(id, userId, userName, message, sendTime);
				list.add(chat);
				}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			dbManger.closeDB();
		}
		return list;
	}
	
	//
	public String queryChatToJson() {
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.registerJsonValueProcessor(Date.class, new JsonDateValueProcessor());
		JSONArray jsonArray = JSONArray.fromObject(queryChat(), jsonConfig);
		System.out.println(jsonArray.isEmpty());
		String json = jsonArray.toString();
		System.out.println(json);
		return json;
	}
	
	public int saveChat(Chat chat) {
//		int id = chat.getId();
		int userId = chat.getUserId();
		String userName = chat.getUserName();
		String message = chat.getMessage();
//		String sendTime = DateTool.getDateStr(chat.getSendTime());
		String sql = "insert into chat values(null, " + userId + ", '" + userName + "', '" + message + "', now())";
		DBManger dbManger = new DBManger();
		return dbManger.update(sql);
	}

}

Chat类(实体类)

package com.jiongmeng.entity;

//聊天表实体类
public class Chat {
	
	private int id;
	private int userId;
	private String userName;
	private String message;
	private java.util.Date sendTime;
	
	public Chat() {
		super();
	}

	public Chat(int id, int userId, String userName, String message, java.util.Date sendTime) {
		super();
		this.id = id;
		this.userId = userId;
		this.userName = userName;
		this.message = message;
		this.sendTime = sendTime;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getUserId() {
		return userId;
	}

	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getMessage() {
		return message;
	}

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

	public java.util.Date getSendTime() {
		return sendTime;
	}

	public void setSendTime(java.util.Date sendTime) {
		this.sendTime = sendTime;
	}

}

DBManger类

package com.jiongmeng.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBManger {
	
	private static final String DB_NAME = "aaa";
	private static final String URL = "jdbc:mysql://localhost:3306/" + DB_NAME;
	private static final String Driver = "com.mysql.jdbc.Driver";
	private static final String USER = "root";
	private static final String PASSWORD = "root";
	private Connection connection = null;
	private PreparedStatement prepareStatement = null;
	private ResultSet rs = null;
	
	//
	public ResultSet query(String sql) {
		try {
			Class.forName(Driver);
			connection = DriverManager.getConnection(URL, USER, PASSWORD);
			prepareStatement = connection.prepareStatement(sql);
			rs = prepareStatement.executeQuery();
		} catch (ClassNotFoundException  | SQLException e) {
			e.printStackTrace();
		}
		return rs;
	}
	
	//
	public int update(String sql) {
		int effectRows = 0;
		try {
			Class.forName(Driver);
			connection = DriverManager.getConnection(URL, USER, PASSWORD);
			prepareStatement = connection.prepareStatement(sql);
			effectRows = prepareStatement.executeUpdate(sql);
		} catch (ClassNotFoundException  | SQLException e) {
			e.printStackTrace();
		}finally {
			closeDB();
		}
		return effectRows;
	}
	
	//
	public void closeDB() {
		try {
			if (rs != null) {
				rs.close();
			}
			if (prepareStatement != null) {
				prepareStatement.close();
			}
			if (connection != null) {
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

JsonDateValueProcessor类(java中的日期类型转换成json报错,所以需要JsonDateValueProcessor类)

package com.jiongmeng.tool;

import java.text.SimpleDateFormat;
import java.util.Date;

import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;

public class JsonDateValueProcessor implements JsonValueProcessor {
	//默认样式,可以在构造方法中修改
	private  String datePattern = "yyyy-MM-dd HH:mm:ss";
	
	public JsonDateValueProcessor() {
		super();
	}
	
	public String getDatePattern() {
		return datePattern;
	}
	public void setDatePattern(String datePattern) {
		this.datePattern = datePattern;
	}
	
	public JsonDateValueProcessor(String datePattern) {
		super();
		this.datePattern = datePattern;
	}

	@Override
	public Object processArrayValue(Object object, JsonConfig jsonConfig) {
		try {
			if(object instanceof Date){
				SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
				Date date = (Date)object;
				return sdf.format(date);
			}
			return object == null ? null : object.toString();
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public Object processObjectValue(String string, Object object, JsonConfig jsonConfig) {
		return processArrayValue(object, jsonConfig);
	}

}

这是一个粗略版的ajax聊天室

当然啦,如果想做的更完善的话,可以继续改进,比如,可以发送图片,发送表情等等,就像下图这样,总之,大家可以充分的发挥自己的想象力和创意!

聊天室

完!

猜你喜欢

转载自blog.csdn.net/czh500/article/details/108112888
今日推荐