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 + ' ' + '用户名:' + mesg.userName + ' ' + '发言时间:' + 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 + ' ' + '用户名:' + mesg.userName + ' ' + '发言时间:' + 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聊天室!
当然啦,如果想做的更完善的话,可以继续改进,比如,可以发送图片,发送表情等等,就像下图这样,总之,大家可以充分的发挥自己的想象力和创意!
完!