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);// 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 += '用户id:' + mesg.userId + ' ' + '用户名:' + mesg.userName + ' ' + '发言时间:' + mesg.sendTime + '
';
str += mesg.message + '
';
}
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
ajax版聊天室
ajax版聊天室
测试闭包
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 queryChat() {
List list = new ArrayList();
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聊天室!
当然啦,如果想做的更完善的话,可以继续改进,比如,可以发送图片,发送表情等等,就像下图这样,总之,大家可以充分的发挥自己的想象力和创意!
聊天室
完!