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

网上部分关于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放入session
		ArrayList
   
   
    
     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() {
			@Override
			public void chatCreated(Chat chat, boolean arg1) {
				//对Openfire的消息处理进行重写
				chat.addMessageListener(new MessageListener() {
					//要求这个监听器,收到信息,通通放入session中的message_list
					public 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服务器时设定系统总管理用户admin
		DB 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进行处理构造JSON ArrayList 
        
          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"%>




   
   
<script src="jquery-1.8.3.js" type="text/javascript"></script>
聊天


	
   
   
欢迎,${sessionScope.username},登出
<script type="text/javascript"> function init(){ $.ajax({ type : "post", url : "init", dataType : "json", success : function(data) { for(var i=0;i "+data[i]+""); } }, error : function() { alert("出错了"); } }); setInterval("load_msg()",2000); } function load_msg(){ var msg=""; $.ajax({ type : "post", url : "load_msg", dataType : "json", success : function(data) { for(var i=0;i "+data[i].time+"

"+ "

"+data[i].from+":"+data[i].body+"

"; $("#msg_list").html(msg); } }, error : function() { alert("出错了"); } }); } function submit_msg() { var msg = $("#msg").val(); var to_user = $("#user_list").val(); $("#msg").val(""); $.ajax({ type : "post", url : "submit_msg", dataType : "text", data : { msg : msg, to_user : to_user }, success : function(data) { }, error : function() { alert("出错了"); } }); } init(); </script>

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

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


作者:yongh701

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值