【Openfire】网页版单对单聊天实例

来源:互联网 发布:js判断chrome版本 编辑:程序博客网 时间:2024/06/08 02:47

网上部分关于Openfire的代码,只实现了,从单一应用与Openfire已经封装好的Spark客户端交互的功能,并没有实现一个应用内,多个用户交互的功能。


下面编写一个Openfire网页版单对单聊天的实例,用Smack的api与Struts2实现。仅包含两在线用户聊天部分。


如下图,开两个浏览器,模拟两个用户,实现网页版的Openfire聊天。


具体文件结构如下:






除了补充了一个fastjson-1.1.24.jar实现Java的容器类到Json字符串的转换,详见《【Java】读取网页中的内容》(点击打开链接),其余关于Openfire的用户处理部分在《【Openfire】网页版的用户注册、登录、修改密码》(点击打开链接)一文中已经详细介绍,这次工程是在其上面开发的。在struts.xml新增了部分关于聊天的Ajax Action,更新之后如下:

  /index.jsp/chat.jsp/index.jsp/index.jsp/index.jsp   

具体改动如下:


基本上已经可以通过Struts2的Ajax Action略窥一二,网页聊天主要实现三个事情,一个是初始化init,一个是让前台JavaScript的定时器setInterval定时执行的,载入信息的Action,还有一个是用户点击按钮的发送信息的Action。

这些Action全写在chat.java这个文件里面,具体代码如下,详情请留意注释:

package test;import java.io.IOException;import java.io.PrintWriter;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.struts2.ServletActionContext;import org.jivesoftware.smack.Chat;import org.jivesoftware.smack.ChatManager;import org.jivesoftware.smack.ChatManagerListener;import org.jivesoftware.smack.Connection;import org.jivesoftware.smack.MessageListener;import org.jivesoftware.smack.XMPPException;import org.jivesoftware.smack.packet.Message;import tool.DB;import com.alibaba.fastjson.JSON;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;@SuppressWarnings({ "unchecked", "rawtypes", "serial" })public class chat extends ActionSupport {private String msg;//用户要发送的信息private String to_user;//用户选择的收信人private Map session = ActionContext.getContext().getSession();//Session//将1970年到现在的long时间记法,转换成真实时间,人看的时间。private String get_realTime(long systime) {return new SimpleDateFormat("hh:mm:ss").format(new Date(systime)).toString();}//聊天系统的初始化public void init() throws IOException {PrintWriter printWriter = ServletActionContext.getResponse().getWriter();//用于打印Ajax//新建一个名为message_list存信息的ArrayList放入sessionArrayList message_list = new ArrayList();session.put("message_list", message_list);//Openfire的关键步骤,为当前的连接,新建聊天信息接受的接听器。Connection connection = (Connection) session.get("connection");ChatManager chatmanager = connection.getChatManager();chatmanager.addChatListener(new ChatManagerListener() {@Overridepublic void chatCreated(Chat chat, boolean arg1) {//对Openfire的消息处理进行重写chat.addMessageListener(new MessageListener() {//要求这个监听器,收到信息,通通放入session中的message_listpublic void processMessage(Chat arg0,Message message_receive) {if (message_receive.getBody() != null) {ArrayList message_list = (ArrayList) session.get("message_list");//由于Smack的api是没有对Openfire中Time属性的处理//因此必须自己再处理一下message_receive.setProperty("time",System.currentTimeMillis());message_list.add(message_receive);session.put("message_list", message_list);}}});}});//这样重写了监听器之后,就可以避免原来Openfire必须指定接听哪个用户发来的信息的情况//任意用户给当前登录用户发来信息,都会放入session中,一会儿载入信息的load_msg()仅仅需要对session进行处理//载入Openfire中所有用户列表,剔除当前用户,和在初始化Openfire服务器时设定系统总管理用户adminDB db = DB.getInstance();List userlist = db.getBySql("select username from ofuser where username !='"+ session.get("username") + "' and username!='admin'");String json = JSON.toJSONString(userlist);//将用户列表打印给前台printWriter.print(json);printWriter.flush();printWriter.close();}//载入用户信息public void load_msg() throws IOException, XMPPException {ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");//由于用户发送的信息可能有中文,所以必须要先设置编码PrintWriter printWriter = ServletActionContext.getResponse().getWriter();//对session中的message_list进行处理构造JSONArrayList message_list = (ArrayList) session.get("message_list");ArrayList> message_json = new ArrayList>();//这个message_json会被fastjson-1.1.24.jar转化成json字符串for (int i = 0; i < message_list.size(); i++) {Message message = message_list.get(i);HashMap one_message = new HashMap();String from = message.getFrom().split("@")[0];//由于Openfire会自动在发信人后面带上一堆服务器、设备参数,因此,做此划分String time = get_realTime((long) message.getProperty("time"));//将long时间转现实时间输出到前台one_message.put("from", from);one_message.put("time", time);one_message.put("body", message.getBody());message_json.add(one_message);//每一条消息都这样处理}//打印到前台String json = JSON.toJSONString(message_json);printWriter.print(json);printWriter.flush();printWriter.close();}// 信息发送public void submit_msg() throws IOException, XMPPException {PrintWriter printWriter = ServletActionContext.getResponse().getWriter();Connection connection = (Connection) session.get("connection");//取连接//按Openfire要求的格式构造发信、收信人String from = (String) session.get("username") + "@"+ connection.getServiceName();String to = to_user + "@" + connection.getServiceName();//发信息核心代码ChatManager chatmanager = connection.getChatManager();Chat chat = chatmanager.createChat(to, null);//新建一个会话,指定收信人,不对收信人所回复的信息进行监听//因为在初始化的时候,已经对此连接收到信息都进行了监听,无须重复监听chat.sendMessage(msg);//对此会话进行发送//但同样要将发送的信息记录在session中的message_list里面,用户打印,这才符合现时主流的聊天工具一问一答的方式ArrayList message_list = (ArrayList) session.get("message_list");Message message_send = new Message();message_send.setFrom(from);message_send.setTo(to);message_send.setBody(msg);message_send.setProperty("time", System.currentTimeMillis());message_list.add(message_send);session.put("message_list", message_list);//其实,消息发送,是没有任何东西交互给前台的,但必须打印一个空信息,才能保证ajax过程不出错。printWriter.print("");printWriter.flush();printWriter.close();}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getTo_user() {return to_user;}public void setTo_user(String to_user) {this.to_user = to_user;}}

最后,配合前台的chat.jsp一切就大功告成,HTML布局部分不重要就表格里面的几行和一个按钮。关键是javascript部分:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ page isELIgnored="false"%>聊天欢迎,${sessionScope.username},登出

要求进入这个页面就马上执行init()的代码,载入用户列表的同时,同时触发读取信息的定时器,每2秒一次执行load_msg()里面的所有内容。

将发送信息的按钮的点击事件,绑定于submit_msg()事件与后台进行交互。


作者:yongh701

原文地址:http://blog.csdn.net/yongh701/article/details/52032869#comments

0 0
原创粉丝点击