ajax在线咨询

it2023-06-14  71

之前听说过别人使用ajax制作一个在线聊天室,对ajax也不熟悉,但是最近有一个需求,做一个在线咨询。也去网上查过n次资料,下过文档,但是一直找不到我想要的。花费了三天终于是做完了。也没写过博客,解决了问题,现在记录一下。 技术上用的是jsp+servlet+ajax。

数据库

数据库用到4张表,用户表,客服表,用户咨询表,聊天记录表。用户状态有3个状态,分别为1,2,3,分别代表在线,请求咨询,正在咨询。

1、用户user表,主要字段有username,pwd,status; 2、客服表contact主要字段有contactname,pwd; 3、用户咨询表record_user字段有recordid,username; 4、聊天记录表record_content字段有recordid,username,usercontent,contactname,contactcontent,tim。 每张表的主键为id,用户表和客服表中的pwd主要是用来登录用。

设计思路: 1、一个用户只有一个咨询号,用户第一次点击咨询的时候,添加咨询号,如果用户 有咨询号,那么无需添加咨询号。

2、客服端首页将用户处于2,3状态的用户展示出来,每10秒进行刷新一次界面,将2状态的前端展示位请求咨询,3状态的展示位正在咨询。正在咨询的颜色为黄色,请求咨询的颜色为红色,点击红色可进入聊天,点击黄色弹出弹窗显示已有客服正在服务。

3、用户进入咨询界面或每发一次信息状态都变为2,客服进入咨询界面或,每发一次信息状态都为3。

4、咨询界面,用户在左边,客服在右边,按照时间先后来排列。

sql="select * from record_content where recordid=? order by tim";

前端界面 前端css样式

<style type="text/css"> *{ margin:0; padding:0; } .one{ background:#fff; margin-left:30%; width:510px; height:380px; overflow-y:auto; overflow-x:none; } .title{ margin-top:5px; text-align:center; margin-bottom:0px } .line{ margin-top:5px; margin-bottom:5px; } .userContent{ background:#00BFFF; margin-left:10px; max-width:335px; min-height:40px; max-height:180px; color:#fff; line-height:40px; border-radius:5px; } .contactInfo{ text-align:right; margin-bottom:0px; } .contactContent{ background: #00FA9A; margin-left:157px; width:335px; min-height:40px; color:#fff; line-height:40px; max-height:180px; border-radius:5px; } .chat{ margin-bottom:-1px; margin-top:40px; overflow-y:auto; margin-left:30%; margin-top:5px; background:#fff; width:500px; } .input{ width:380px; height:30px; margin-left:15px; border-radius:5px; border:1px blue solid; } .send{ margin-left:15px; height:29px; width:75px; color:#fff; border-radius:5px; } .recordid{ display:none; } .header{ width:510px; height:20px; background:#fff; margin-left:30%; } </style>

前端body样式

<div class="header"> <h5 class="title">客服咨询</h5><span class="recordid" id="recordid">${recordid }</span> <hr class="line"> </div> <div class="one" id="one"> <!-- <div class="user"> <span class="userInfo"><span id="username">张三</span> 2020-10-14 09:29:33</span> <div class="userContent">你好</div> </div> <div class="contact"> <p class="contactInfo">李四 2020-10-14 09:30:33</p> <div class="contactContent">你好</div> </div> --> </div> <div class="chat"> <input type="text" class="input" id="input"> <button class="send" id="send" onclick="send()">发送</button> </div>

这里先将主体样式注释掉,后面内容用ajax添加。 前端js

<script type="text/javascript"> window.onload=function(){ var jsonString = '${beans}'; var jsonObject = JSON.parse(jsonString); for(var i=0;i<jsonObject.length;i++){ if(jsonObject[i].usernam!=null){ $(".one").append( "<div class='user'><span class='userInfo'><span>" +jsonObject[i].usernam+ "&nbsp;</span>" +jsonObject[i].tim+ "</span><div class='userContent'>" +jsonObject[i].userContent+ "</div></div>"); }else{ $(".one").append( "<div class='contact'><p class='contactInfo'>" +jsonObject[i].contactnam+"&nbsp;"+jsonObject[i].tim+ "</p><div class='contactContent'>" +jsonObject[i].contactContent+ "</div></div>"); } } document.getElementById("one").scrollTop=document.getElementById("one").scrollHeight; } </script> <script type="text/javascript"> window.setInterval("refresh()",2000);//2秒执行一次,刷新功能 function refresh(){//用于追加新发的消息 $.ajax({ type:"post", url:"lianXiKeFuHistoryServlet", contentType: "application/json;charset=utf-8", success:function(data){ /* alert(data); */ console.log(data); var jsonString = data; var jsonObject = JSON.parse(jsonString); for(var i=0;i<jsonObject.length;i++){ if(jsonObject[i].usernam!=null){ $(".one").append( "<div class='user'><span class='userInfo'><span>" +jsonObject[i].usernam+ "&nbsp;</span>" +jsonObject[i].tim+ "</span><div class='userContent'>" +jsonObject[i].userContent+ "</div></div>"); }else{ $(".one").append( "<div class='contact'><p class='contactInfo'>" +jsonObject[i].contactnam+"&nbsp;"+jsonObject[i].tim+ "</p><div class='contactContent'>" +jsonObject[i].contactContent+ "</div></div>"); } } }, error:function(e){ console.log("失败"); } }) document.getElementById("one").scrollTop=document.getElementById("one").scrollHeight; } </script> <script type="text/javascript"> window.setInterval("run()",500);//0.5秒执行一次 function run(){ var input=document.getElementById("input").value; var send=document.getElementById("send"); if(input==""){ send.style.backgroundColor="#ddd"; send.disabled=true;//设置不可点击 }else{ send.style.backgroundColor="blue"; send.disabled=false;//设置可点击 } } </script> <script type="text/javascript"> function send(){//发信息,使用ajax,异步处理 var input=document.getElementById("input").value; var input1=document.getElementById("input"); var recordid=document.getElementById("recordid").innerText; $.ajax({ type:"post", url:"addLianXiKeFuServlet?userContent="+input+"&recordid="+recordid, contentType: "application/json;charset=utf-8", success:function(data){ input1.value="";//发送成功之后,input的值变为空 /* refresh(); */ }, error:function(e){ alert("发送失败"); } }) } </script>

当聊天窗内的消息过多时,聊天框会溢出界面,所以聊天窗css样式添加:

overflow-y:auto; overflow-x:none;

每次进入聊天界面滚动条都在最上面,用户体验不好。于是设计每次进入,聊天窗滚动条在最下面。

document.getElementById("one").scrollTop=document.getElementById("one").scrollHeight;

输入框为空时,消息不能发送,按钮为灰色,每0.5秒检测一次,输入框不为空,则按钮变为蓝色。界面每2秒刷新一次,时间刷新的太短,可能会一下子刷出几条数据出来。 ajax使用Jquery的相对要简单方便一些,可以使用json传也可以使用拼接字符串。但是使用json传注意一定要加上:

contentType: "application/json;charset=utf-8"

防止后端接收到的是乱码。

后端实体类 用户实体类userBean。在这里只要注意username,pwd,status。

package Bean; public class userBean { private int id; private String usernam; private String telephone; private String sex; private String pwd; private String age; private String description; private String status; public userBean(int id, String usernam, String telephone, String sex, String pwd, String age,String description) { this.id = id; this.usernam = usernam; this.telephone = telephone; this.sex = sex; this.pwd = pwd; this.age = age; } public userBean(int id, String usernam, String telephone, String sex,String age,String description) { this.id = id; this.usernam = usernam; this.telephone = telephone; this.sex = sex; this.age = age; this.description=description; } public userBean(int id, String telephone, String sex,String age,String description) { this.id = id; this.telephone = telephone; this.sex = sex; this.age = age; this.description=description; } public userBean(String usernam, String telephone, String sex, String age,String description) { this.usernam = usernam; this.telephone = telephone; this.sex = sex; this.description=description; this.age = age; } public userBean(String usernam, String pwd) { this.usernam=usernam; this.pwd=pwd; } public userBean(String usernam) { this.usernam=usernam; } public userBean(int id) { // TODO Auto-generated constructor stub this.id=id; } public userBean(int id, String telephone, String sex, String age) { // TODO Auto-generated constructor stub this.id = id; this.telephone = telephone; this.sex = sex; this.age = age; } public userBean(int id, String usernam, String status) { // TODO Auto-generated constructor stub this.id=id; this.usernam=usernam; this.status=status; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsernam() { return usernam; } public void setUsernam(String usernam) { this.usernam = usernam; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }

客服实体类contactBean。这里只要注意contactname,pwd。

package Bean; public class contactBean { private int id; private String contactnam; private String telephone; private String sex; private String pwd; private String age; private String description; public contactBean(String contactnam, String telephone, String sex, String pwd, String age) { this.contactnam = contactnam; this.telephone = telephone; this.sex = sex; this.pwd = pwd; this.age = age; } public contactBean(String contactnam, String pwd) { // TODO Auto-generated constructor stub this.contactnam = contactnam; this.pwd = pwd; } public contactBean(int id, String contactnam, String telephone) { // TODO Auto-generated constructor stub this.id=id; this.contactnam = contactnam; this.telephone = telephone; } public contactBean(String contactnam) { // TODO Auto-generated constructor stub this.contactnam=contactnam; } public contactBean(int id, String contactnam, String telephone, String sex, String age, String description) { // TODO Auto-generated constructor stub this.id=id; this.contactnam = contactnam; this.telephone = telephone; this.sex = sex; this.age = age; this.description=description; } public contactBean(int id2, String telephone2, String sex2, String age2, String description2) { // TODO Auto-generated constructor stub this.id=id2; this.telephone=telephone2; this.sex=sex2; this.age=age2; this.description=description2; } public contactBean(int id, String contactnam, String telephone, String sex, String pwd, String age, String description) { // TODO Auto-generated constructor stub this.id=id; this.contactnam = contactnam; this.telephone = telephone; this.sex = sex; this.pwd=pwd; this.age = age; this.description=description; } public contactBean(String contactnam2, String telephone2, String sex2, String age2) { // TODO Auto-generated constructor stub this.contactnam = contactnam2; this.telephone = telephone2; this.sex = sex2; this.age = age2; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getContactnam() { return contactnam; } public void setContactnam(String contactnam) { this.contactnam = contactnam; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }

用户咨询实体类recordUserBean。

package Bean; public class recordUserBean { private int id; private String recordid; private String usernam; public recordUserBean(int id, String recordid, String usernam) { // TODO Auto-generated constructor stub this.id=id; this.recordid=recordid; this.usernam=usernam; } public recordUserBean() { // TODO Auto-generated constructor stub } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getRecordid() { return recordid; } public void setRecordid(String recordid) { this.recordid = recordid; } public String getUsernam() { return usernam; } public void setUsernam(String usernam) { this.usernam = usernam; } }

聊天记录实体类recordContentBean。

package Bean; public class recordContentBean { private int id; private String recordid; private String usernam; private String contactnam; private String userContent; private String contactContent; private String tim; public recordContentBean(int id, String recordid, String usernam, String contactnam, String userContent, String contactContent,String tim) { this.id = id; this.recordid = recordid; this.usernam = usernam; this.contactnam = contactnam; this.userContent = userContent; this.contactContent = contactContent; this.tim=tim; } public String getTim() { return tim; } public void setTim(String tim) { this.tim = tim; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getRecordid() { return recordid; } public void setRecordid(String recordid) { this.recordid = recordid; } public String getUsernam() { return usernam; } public void setUsernam(String usernam) { this.usernam = usernam; } public String getContactnam() { return contactnam; } public void setContactnam(String contactnam) { this.contactnam = contactnam; } public String getUserContent() { return userContent; } public void setUserContent(String userContent) { this.userContent = userContent; } public String getContactContent() { return contactContent; } public void setContactContent(String contactContent) { this.contactContent = contactContent; } }

控制器servlet 用户端,需要四个servlet。分别是登录servlet;进入聊天界面,将用户的聊天记录加载到前端界面的servlet,添加聊天记录的servlet,每两秒刷新一次界面的servlet。这里就不说登录的了,说一下聊天的servlet。

1、将用户的聊天记录加载到前端界面的控制器:headLianXiKeFuServlet。上代码!

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=UTF-8"); String usernam=(String)request.getSession().getAttribute("userSession"); Date d=new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");//以时间作为咨询id String recordid=null; //一个用户只有一个咨询窗口,也就是说只有一个咨询号,创建一个之后,以后重新打开就不会重新创建 //先查询数据库中record是否有用户,如果有则无需创建,如果没有,则创建咨询号 lianXiDao dao=new lianXiDao(); if (dao.queryUser(usernam)) {//如果表中没有数据,那么添加一个咨询号 System.out.print("已有咨询号"); }else { recordid=df.format(d); if (dao.addRecord(recordid, usernam)) {//添加成功 System.out.print("咨询号添加成功!"); }else { System.out.print("咨询号添加失败!"); } } recordUserBean bean=dao.queryRecordid(usernam); recordid=bean.getRecordid(); List<recordContentBean> beans=new ArrayList<>(); beans=dao.queryRecordHistroy(recordid);//界面刷新 Gson gson = new Gson(); String beans1 = gson.toJson(beans); //将List转化为Json数据 //当用户进入界面后,状态变为2 dao.updateStatus("2", usernam); request.setAttribute("beans", beans1); response.getWriter().write(beans1); request.setAttribute("recordid", recordid); request.getRequestDispatcher("lianXiKeFu.jsp").forward(request, response); }

2、添加聊天记录的控制器:addLianXiKeFuServlet。上代码!

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=UTF-8"); String usernam=(String)request.getSession().getAttribute("userSession"); String recordid=request.getParameter("recordid"); String userContent=request.getParameter("userContent"); String msg=null; Date d=new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//时间 String tim=df.format(d); lianXiDao dao=new lianXiDao(); //防止客服离开聊天界面之后,状态变为其他状态,故每次发送消息,状态都为2 dao.updateStatus("2", usernam); if (dao.addRecordContent(recordid, usernam,userContent, tim)) { msg="ok"; }else { System.out.print("咨询失败"); msg="no"; } }

3、前端每两秒刷新一次界面的控制器:lianXiUpdateServlet。上代码!

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=UTF-8"); String usernam=(String)request.getSession().getAttribute("userSession"); lianXiDao dao=new lianXiDao(); recordUserBean bean=dao.queryRecordid(usernam); String recordid=bean.getRecordid(); List<recordContentBean> beans=new ArrayList<>(); beans=dao.queryRecord_5(recordid);//刷新界面 Gson gson = new Gson(); String beans1 = gson.toJson(beans); //将List转化为Json数据 response.getWriter().write(beans1); }

ajax请求servlet返回前端json数据用的是:

response.getWriter().write();

前端解析json是:

var jsonObject = JSON.parse(data);

ajax请求之后,控制器访问dao层,dao层访问底层until,底层访问数据库。

注意事项: 1、访问数据库之后一定要关闭连接,因为每两秒刷新一次界面,不关闭连接会对数据库造成巨大负荷,没一会就会给你报错。

2、控制器返回json数据。dao层返回的List是Object类型的,前端js不能解析,所以要在后端进行解析。解析需要用到jar包,我用的jar包为gson.jar。

3、java在线时间的模板:yyyy-MM-dd HH:mm:ss。当小时为H时,为24小时制,当为h时为12小时制。我在设计的时候,早上还可以正常运行的,到了下午却运行不出来了,找了半天问题,最后看到数据库的时间记录,下午15点结果变为3点,这样就导致发的信息刷不出来。

Dao层 lianxiDao

package Dao; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.mysql.jdbc.Statement; import Bean.recordContentBean; import Bean.recordUserBean; import Bean.userBean; import Until.DBUtil; public class lianXiDao { DBUtil dbUtil=new DBUtil(); ResultSet rs=null; String sql=null; public boolean queryUser(String usernam) {//查询record_user表中是否有用户的咨询号 sql="select * from record_user where usernam=?"; Object[] params= {usernam}; return dbUtil.isExcut(sql, params); } public boolean updateStatus(String status,String usernam) {//改变用户状态 sql="update user set status=? where usernam=?"; Object[] params= {status,usernam}; return dbUtil.queryExecuteUpdate(sql, params); } public boolean addRecord(String recordid,String usernam) {//在record_user表中添加咨询号 sql="insert into record_user(recordid,usernam) values(?,?)"; Object[] params= {recordid,usernam}; return dbUtil.queryExecuteUpdate(sql, params); } public recordUserBean queryRecordid(String usernam) {//查询表中的数据 sql="select * from record_user where usernam=?"; Object[] params= {usernam}; recordUserBean bean = null; rs=dbUtil.queryExecutQuery(sql, params); try { while(rs.first()) { bean=new recordUserBean(rs.getInt("id"),rs.getString("recordid"),rs.getString("usernam")); break; } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { dbUtil.closeAll(rs, (Statement)dbUtil.pstmt, dbUtil.connection); } return bean; } public boolean addRecordContent(String recordid,String usernam,String userContent,String tim) {//在record_user表中添加咨询号--用户 sql="insert into record_content(recordid,usernam,userContent,tim) values(?,?,?,?)"; Object[] params= {recordid,usernam,userContent,tim}; return dbUtil.queryExecuteUpdate(sql, params); } public boolean addRecordContentByContact(String recordid,String conatctnam,String conatctContent,String tim) {//在record_user表中添加咨询号--客服 sql="insert into record_content(recordid,contactnam,contactcontent,tim) values(?,?,?,?)"; Object[] params= {recordid,conatctnam,conatctContent,tim}; return dbUtil.queryExecuteUpdate(sql, params); } public List<recordContentBean>queryRecord_5(String recordid) {//每秒刷新数据 sql="select * from record_content where recordid=? and tim >= now()-interval 2.3 second;"; Object[] params= {recordid}; recordContentBean bean = null; List<recordContentBean> beans=new ArrayList<>(); rs=dbUtil.queryExecutQuery(sql, params); try { while(rs.next()) { bean=new recordContentBean(rs.getInt("id"),rs.getString("recordid"),rs.getString("usernam"),rs.getString("contactnam"), rs.getString("usercontent"),rs.getString("contactcontent"),rs.getString("tim")); beans.add(bean); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { dbUtil.closeAll(rs, (Statement)dbUtil.pstmt, dbUtil.connection); } return beans; } public List<recordContentBean>queryRecordHistroy(String recordid) {//查询历史聊天记录 sql="select * from record_content where recordid=? order by tim"; Object[] params= {recordid}; recordContentBean bean = null; List<recordContentBean> beans=new ArrayList<>(); rs=dbUtil.queryExecutQuery(sql, params); try { while(rs.next()) { bean=new recordContentBean(rs.getInt("id"),rs.getString("recordid"),rs.getString("usernam"),rs.getString("contactnam"), rs.getString("usercontent"),rs.getString("contactcontent"),rs.getString("tim")); beans.add(bean); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { dbUtil.closeAll(rs, (Statement)dbUtil.pstmt, dbUtil.connection); } return beans; } public List<userBean>queryUserByContact() {//查询处于2,3状态的用户 sql="select * from user where status=2"; Object[] params= {}; userBean bean = null; List<userBean> beans=new ArrayList<>(); rs=dbUtil.queryExecutQuery(sql, params); try { while(rs.next()) { bean=new userBean(rs.getInt("id"),rs.getString("usernam"),rs.getString("status")); beans.add(bean); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { dbUtil.closeAll(rs, (Statement)dbUtil.pstmt, dbUtil.connection); } return beans; } public List<recordContentBean>queryRecordHistroy1(String recordid,String contactnam) {//客服进入聊天界面,查询历史聊天记录 sql="select * from record_content where recordid=? or contactnam=? order by tim"; Object[] params= {recordid,contactnam}; recordContentBean bean = null; List<recordContentBean> beans=new ArrayList<>(); rs=dbUtil.queryExecutQuery(sql, params); try { while(rs.next()) { bean=new recordContentBean(rs.getInt("id"),rs.getString("recordid"),rs.getString("usernam"),rs.getString("contactnam"), rs.getString("usercontent"),rs.getString("contactcontent"),rs.getString("tim")); beans.add(bean); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { dbUtil.closeAll(rs, (Statement)dbUtil.pstmt, dbUtil.connection); } return beans; } }

查询两秒内数据库增加的数据:

select * from 表 where 时间字段> now()-interval 2 second;

客服聊天界面 基本上和用户的一样,加一个每10秒刷新界面的:

<meta http-equiv="refresh" content="10"><!-- 界面每30秒刷新一次 -->

用户状态:

<script type="text/javascript"> var statu=document.getElementsByClassName("statu"); var a=document.getElementsByClassName("a"); for(var i=0;i<statu.length;i++){ if(statu[i].innerText=="2"){//状态为2 statu[i].style.backgroundColor="red"; statu[i].innerText="请求咨询"; statu[i].style.color="#fff"; }else{//状态为3 statu[i].style.backgroundColor="yellow"; statu[i].innerText="正在咨询"; a.href="#"; } } </script>

客服端基本上和用户端差不多,只不过对数据库操作有一些不同,如果想了解更多,可以评论,或者咨询我。

最新回复(0)