Ajax实现在线聊天室
2015-04-09 20:23
369 查看
功能实现及开发过程可能遇到的问题
发送聊天的消息和实时显示聊天的消息一定要分开处理!发送聊天消息如何实现?
①在多行文本框上面绑定“按下键盘[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源代码相关文章推荐
- django+ajax实现在线聊天室
- 基于javascript、ajax、memcache和PHP实现的简易在线聊天室
- 聊天室用ajax实现在线人员列表
- Ajax PHP JavaScript MySQL实现简易的无刷新在线聊天室
- Ajax PHP JavaScript MySQL实现简易的无刷新在线聊天室
- Ajax PHP JavaScript MySQL实现简易无刷新在线聊天室
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
- 如何实现java,jsp,ajax编写的在线聊天室啊?
- 用ASP实现聊天室中的在线答题游戏
- 实现聊天室在线人员无刷新所需要的JavaScript技术
- 实现一个无刷新的基于ajax的简易聊天室
- 实现一个无刷新的基于ajax的简易聊天室
- 实现聊天室在线人员无刷新所需要的JavaScript技术 - 2
- 利用AJAX和ASP.NET实现简单聊天室
- 一个用ajax实现聊天室
- ajax实现的聊天室程序
- 实现一个无刷新的基于ajax的简易聊天室
- ajax如何根据座位实现在线订票
- 实现一个无刷新的基于ajax的简易聊天室
- Struts+Ajax实现定时刷新Table内容,实现在线人员显示