Ajax实现在线聊天室
来源:互联网 发布:买大班模型 淘宝店 编辑:程序博客网 时间:2024/04/29 12:39
功能实现及开发过程可能遇到的问题
- 发送聊天的消息和实时显示聊天的消息一定要分开处理!
- 发送聊天消息如何实现?
①在多行文本框上面绑定“按下键盘[keypress]”事件,在用户按回车键时发送Ajax请求
②接收到Ajax请求后,保存聊天记录信息 - 实时显示聊天记录如何实现?
①困难:
[1]服务器端不会主动的告诉浏览器有新的聊天记录了,而是只能被动的响应浏览器的请求
[2]浏览器不知道服务器端什么时候产生了新的聊天记录
②在浏览器端不间断的发送请求,询问服务器现在是否有新的聊天记录了
如何实现?setTimeout(回调函数的引用,毫秒值);
③服务器端接收到浏览器询问后,检查当前是否有新的聊天记录,如果有,返回true
④如果询问的结果是true,再发送请求,从服务器端获取新的聊天记录内容
⑤如何知道哪些记录是新的呢?- 在浏览器端维护一个全局变量,保存本地最新的记录的ID值
- 在询问服务器时,将本地ID值发送过去
- 服务器端根据ID值判断哪些记录是最新的
1. 新建AjaxChat,代码目录图如图所示
2.主界面index.jsp的代码如下,代码中已带有注释
<%@ 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><base href="http://${pageContext.request.serverName }:${pageContext.request.serverPort }${pageContext.request.contextPath }/" /><link rel="stylesheet" type="text/css" href="style/css.css" /><script type="text/javascript" src="script/jquery-1.7.2.js"></script><script type="text/javascript" src="script/dateFormate.js"></script><script type="text/javascript"> $(function(){ //用于保存当前本地最新的聊天记录ID值,初始值为0,目的是第一次加载时获取全部聊天记录 var finalMessageId = 0; askForNew(); //声明函数:询问服务器端是否存在新的聊天记录 function askForNew() { $.post("ServletAsk",{"finalMessageId":finalMessageId},function(hasNew){ //注意:这里hasNew是字符串,即使服务器返回的是"false",在if中判断也为true if(hasNew == "true") { //给服务器端发送请求,获取最新的聊天记录 getNew(); } },"text"); //注意:一定要使用函数的引用,不能加() setTimeout(askForNew, 1000); } //声明函数:获取新的聊天记录内容 function getNew() { var $showMessage = $("#showMessage"); $.post("ServletGetNew",{"finalMessageId":finalMessageId},function(newMessage){ /* private Integer messageId; private String message; private Date messageTime; */ for(var i = 0; i < newMessage.length; i++) { var messageId = newMessage[i].messageId; var message = newMessage[i].message; var messageTime = newMessage[i].messageTime; messageTime = new Date(messageTime).Format("yyyy年MM月dd日 hh:mm:ss"); var htmlStr = "<div>" + messageTime + " " + message + "</div>"; //console.log(htmlStr); $showMessage.append(htmlStr); finalMessageId = messageId; } //获取#showMessage对应的DOM对象,通过scrollTop属性设置滚动条的显示位置 $showMessage[0].scrollTop = 10000000; },"json"); } //给多行文本框绑定键盘按下事件 $("#sendMessage").keypress(function(event){ //在用户按下回车键时,发送聊天消息 //通过事件对象的keyCode属性获取当前按下的键对应的ASCII码 if(event.keyCode == 13) { //获取聊天消息的内容 var message = $.trim(this.value); //使用Ajax技术将聊天消息发送到服务器端 $.post("ServletSay",{"message":message}); //清空多行文本框 this.value = ""; } }); });</script></head><body> <img src="image/logo.gif" /> <div id="showMessage"></div> <textarea id="sendMessage"></textarea></body></html>
3.Message类的代码如下
package com.atguigu.liaotian.bean;import java.util.Date;public class Message { private Integer messageId; private String message; private Date messageTime; public Message() { } public Message(Integer messageId, String message, Date messageTime) { super(); this.messageId = messageId; this.message = message; this.messageTime = messageTime; } @Override public String toString() { return "Message [messageId=" + messageId + ", message=" + message + ", messageTime=" + messageTime + "]"; } public Date getMessageTime() { return messageTime; } public void setMessageTime(Date messageTime) { this.messageTime = messageTime; } public Integer getMessageId() { return messageId; } public void setMessageId(Integer messageId) { this.messageId = messageId; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}
4.Dao基类使用反射机制实现对象的增删改查
package com.atguigu.liaotian.dao;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import org.apache.commons.dbutils.handlers.ScalarHandler;import com.atguigu.liaotian.utils.JDBCUtils;/** * Dao基类 * 增删改查 * @author Administrator * */public class BaseDao<T> { private QueryRunner runner = new QueryRunner(); private Class<T> beanType = null; public BaseDao() { Class clazz = this.getClass(); Class superclass = clazz.getSuperclass(); Type type = clazz.getGenericSuperclass(); if(type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; Type[] typeArguments = pt.getActualTypeArguments(); Type realType = typeArguments[0]; if(realType instanceof Class) { beanType = (Class<T>) realType; } } } public Integer insertWithId(String sql, Object ... param) { Integer id = null; //1.获取数据库连接 Connection connection = JDBCUtils.getConnection(); //2.获取PreparedStatement对象 PreparedStatement ps = null; //3.获取ResultSet对象用来保存返回的自增ID的值 ResultSet rs = null; try { //在获取PreparedStatement对象时,通过附加另外一个参数的方式将PreparedStatement对象 //设置为返回自增主键的模式 ps = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); for (int i = 0; i < param.length; i++) { ps.setObject(i+1, param[i]); } ps.execute(); //自增的主键是以结果集形式返回的 rs = ps.getGeneratedKeys(); if(rs.next()) { id = rs.getInt(1); } } catch (SQLException e) { e.printStackTrace(); } finally { //4.释放资源 JDBCUtils.releaseConnection(connection); try { DbUtils.close(ps); } catch (SQLException e) { e.printStackTrace(); } try { DbUtils.close(rs); } catch (SQLException e) { e.printStackTrace(); } } return id; } /** * 执行批量更新操作 * @param sql * @param params 执行批量操作时的SQL语句的参数,是二维数组类型 * 在非批量处理的情况下,SQL语句的参数是一维数组,对应SQL语句的一次执行 * 在批量处理的情况下,SQL语句的参数是二维数组,对应SQL语句的多次执行 * 其中每一个一维数组和一条SQL语句是对应的 * 第二维数组的每一个元素分别对应SQL语句中的一个参数 */ public void batchUpdate(String sql, Object [] ... params ) { Connection connection = JDBCUtils.getConnection(); try { runner.batch(connection, sql, params); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.releaseConnection(connection); } /** * 获取单一值的方法,声明的泛型参数是根据接收返回值的变量的类型传入的 * 如果执行的是COUNT()函数需要注意它返回的是Long包装类型 * @param sql * @param params * @return */ public <E> E getSingleValue(String sql, Object ... params) { E e = null; Connection connection = JDBCUtils.getConnection(); try { e = (E) runner.query(connection, sql, new ScalarHandler(), params); } catch (SQLException e1) { e1.printStackTrace(); } JDBCUtils.releaseConnection(connection); return e; } /** * 查询数据库返回实体类对象的集合 * @param sql * @param params * @return实体类对象的集合 */ public List<T> getBeanList(String sql, Object ... params) { Connection connection = JDBCUtils.getConnection(); List<T> list = null; try { list = runner.query(connection, sql, new BeanListHandler<T>(beanType), params); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.releaseConnection(connection); return list; } /** * 返回单一对象的查询方法 * @param sql * @param params * @return 将数据库查询结果封装得到的对象 */ public T getBean(String sql, Object ... params) { T t = null; Connection connection = JDBCUtils.getConnection(); try { t = runner.query(connection, sql, new BeanHandler<T>(beanType), params); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.releaseConnection(connection); return t; } /** * 执行增删改的通用方法 * @param sql * @param params */ public void update(String sql, Object ... params) { Connection connection = JDBCUtils.getConnection(); try { runner.update(connection, sql, params); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.releaseConnection(connection); }}
5.BaseDao基类的实现类MessageDao类,实现Message对象的增删改查
package com.atguigu.liaotian.dao;import java.util.List;import com.atguigu.liaotian.bean.Message;public class MessageDao extends BaseDao<Message>{ //将聊天记录信息保存到数据库中 public void saveMessage(Message message) { String sql = "INSERT INTO MESSAGE (MESSAGE_CONTENT,MESSAGE_TIME) VALUES(?,?)"; this.update(sql, message.getMessage(), message.getMessageTime()); } //根据浏览器传入的本地最新消息ID查询比本地消息还要新的聊天记录 public List<Message> getNewMessage(String finalMessageId) { String sql = "SELECT `MESSAGE_ID` messageId,`MESSAGE_CONTENT` message,`MESSAGE_TIME` messageTime FROM `message` WHERE MESSAGE_ID>? ORDER BY MESSAGE_ID"; return this.getBeanList(sql, finalMessageId); } //根据浏览器传入的本地最新消息ID查询是否存在新的聊天记录 public boolean hasNew(String finalMessageId) { String sql = "SELECT COUNT(*) FROM `message` WHERE `MESSAGE_ID`>?"; long count = this.getSingleValue(sql, finalMessageId); return count > 0; }}
6.将聊天记录的值保存到数据库中
public class ServletSay extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取聊天记录消息的值 String msg = request.getParameter("message"); Message message = new Message(null, msg, new Date()); System.out.println(message); // 2. 将聊天记录的值保存到数据库中 MessageDao messageDao = new MessageDao(); messageDao.saveMessage(message); }}
7.询问是否有新消息的ServletAsk类代码如下
public class ServletAsk extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取请求参数:finalMessageId String finalMessageId = request.getParameter("finalMessageId"); //2.根据finalMessageId查询是否存在最新的聊天记录 MessageDao messageDao = new MessageDao(); boolean hasNew = messageDao.hasNew(finalMessageId); //3.将布尔类型的返回值以Ajax响应的形式返回给浏览器 response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.write(hasNew+""); }}
8.获取新聊天记录内容,并转换为json格式数据传递到前台
public class ServletGetNew extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取finalMessageId String finalMessageId = request.getParameter("finalMessageId"); //2.根据finalMessageId获取新聊天记录内容 MessageDao messageDao = new MessageDao(); List<Message> newMessage = messageDao.getNewMessage(finalMessageId); //3.转换为JSON字符串返回给浏览器 Gson gson = new Gson(); String json = gson.toJson(newMessage); System.out.println(json); response.setContentType("text/json;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.write(json); }}
运行界面效果图
项目源代码(点击下面链接)
AjaxChat源代码
0 0
- Ajax实现在线聊天室
- django+ajax实现在线聊天室
- ajax在线聊天室(一)
- ajax在线聊天室(二)
- ajax在线聊天室(三)
- ajax在线聊天室(四)
- 如何实现java,jsp,ajax编写的在线聊天室啊?
- Ajax PHP JavaScript MySQL实现简易无刷新在线聊天室
- Ajax+servlet实现聊天室
- WebSocket+HTML5实现在线聊天室
- socket.io 实现在线聊天室
- wokerman 在线聊天室本地实现
- Ajax PHP JavaScript MySQL实现简易的无刷新在线聊天室
- ajax实现的聊天室程序
- 一个用ajax实现聊天室
- wokerman 上在线聊天室本地实现
- php基于websocket实现的在线聊天室
- express简单实现登录及在线聊天室
- 让VC调试器正确显示UTF-8字符串
- Android中使用ListView实现漂亮的表格效果
- 链表反转
- 16进制颜色设定
- 改装LogitechK120为背光键盘
- Ajax实现在线聊天室
- 解决bringChildToFront/bringToFront不起作用的问题
- scp和sftp常用操作
- iOS多线程中performSelector: 和dispatch_time的不同
- 解决MySql Error Code: 2006 – MySQL 服务器已离线 错误
- 使用github中遇到的问题
- 更简单的非递归遍历二叉树
- 什么是EPEL 及 Centos上安装EPEL
- Scala学习笔记(actor)