package server; import java.awt.datatransfer.StringSelection; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Hashtable; import java.util.Iterator; import java.util.Observable; import java.util.Observer; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.LinkedBlockingQueue; import org.apache.log4j.Logger; import org.apache.mina.core.session.IoSession; import org.hibernate.Session; import observer.ObserverMessage; import observer.ObserverMessage_Login; import protocol.ProtoHead; import protocol.Data.ChatData.ChatItem; import protocol.Data.ChatData.ChatItem.ChatType; import protocol.Msg.ReceiveChatMsg.ReceiveChatSync; import protocol.Msg.SendChatMsg.SendChatReq; import protocol.Msg.SendChatMsg.SendChatRsp; import tools.Debug; import model.Chatting; import model.HibernateSessionFactory; /** * 网络逻辑层(微信消息模块) * * @author Feng */ public class ServerModel_Chatting { public static final int SAVE_DATA_HOUR = 1; public static final int INTERVAL_HOUR = 24 * 60 * 60; public static final int DELETE_INTERVAL = 24 * 3 * 60 * 60; private Logger logger = Logger.getLogger(this.getClass()); public Hashtable<String, LinkedBlockingQueue<Chatting>> chattingHashtable; private ServerModel serverModel; private ServerNetwork serverNetwork; public ServerModel getServerModel() { return serverModel; } public void setServerModel(ServerModel serverModel) { this.serverModel = serverModel; init(); } public ServerNetwork getServerNetwork() { return serverNetwork; } public void setServerNetwork(ServerNetwork serverNetwork) { this.serverNetwork = serverNetwork; } public ServerModel_Chatting(){ } /** * 初始化 * * @author Feng */ public void init() { if (chattingHashtable != null) return; chattingHashtable = new Hashtable<String, LinkedBlockingQueue<Chatting>>(); // 监听用户登陆事件 serverModel.addObserver(new Observer() { /** * 检查是否有未接收的消息 */ @Override public void update(Observable o, Object arg) { ObserverMessage om = (ObserverMessage) arg; if (om.type == ObserverMessage.Type.Login) { ObserverMessage_Login oml = (ObserverMessage_Login) om; Debug.log(new String[] { "ServerModel_Chatting", "ServerModel_Chatting" }, "Catch User( " + oml.userId + ") 'LoginEvent'!"); ArrayList<Chatting> chattingList = getChattingNotReceive(oml.userId); if (chattingList != null && chattingList.size() > 0) { Debug.log(new String[] { "ServerModel_Chatting", "ServerModel_Chatting" }, "User(" + oml.userId + ") has " + chattingList.size() + " 'Chattings' doesn't be received,Start transmit!"); ReceiveChatSync.Builder receiveChatting = ReceiveChatSync.newBuilder(); // 加入所有未接收消息 for (Chatting chatting : chattingList) receiveChatting.addChatData(chatting.createChatItem()); // 发送 serverNetwork.sendToClient(oml.ioSession, new PacketFromServer( ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC_VALUE, receiveChatting.build().toByteArray())); // byte[] messageWillSend = // receiveChatting.build().toByteArray(); // 添加监听 // addListenReceiveChatting(oml.ioSession, chattingList, // messageWillSend); } } } }); // 添加每日聊天记录存入数据库 // Date firstStartDate = new Date(); // firstStartDate.setDate(firstStartDate.getDate() + 1); // firstStartDate.setHours(SAVE_DATA_HOUR); // Timer timer = new Timer(); // timer.schedule(new SaveDataThread(), firstStartDate, INTERVAL_HOUR); // test(); } /** * 发送一条聊天消息 * * @param ioSession * @param sendChattingBuilder * @author Feng */ public void sendChatting(final Chatting chatting) { sendChatting(new Chatting[] { chatting }); } public void sendChatting(final Chatting[] chattings) { if (chattings.length < 1) return; IoSession receiverIoSession; ReceiveChatSync.Builder receiverChatObj; ClientUser clientUser; Chatting chatting; // 获取接收者 for (int i=0; i<chattings.length; i++) { chatting = chattings[i]; clientUser = serverModel.getClientUserByUserId(chattings[0].getReceiverUserId()); // 接受者不在线,存入内存 if (clientUser == null) { logger.debug("ServerModel_Chatting : sendChatting : The Receiver(" + chattings[0].getReceiverUserId() + ") is offline, Chatting will be save in Server!"); addChatting(chatting); return; } receiverIoSession = clientUser.ioSession; // 创建要发送的消息包 receiverChatObj = ReceiveChatSync.newBuilder(); receiverChatObj.addChatData(chatting.createChatItem()); serverNetwork.sendToClient(new WaitClientResponse(receiverIoSession, new PacketFromServer( ProtoHead.ENetworkMessage.RECEIVE_CHAT_SYNC_VALUE, receiverChatObj.build().toByteArray()), new SendChattingHandle(chatting))); } } /** * 发送微信消息失败处理 * @author Feng * */ private class SendChattingHandle implements WaitClientResponseCallBack{ private Chatting chatting; public SendChattingHandle(Chatting chatting) { this.chatting = chatting; } @Override public void beforeDelete() { // 添加发送失败时删除前的回调 addChatting(chatting); } } /** * 往消息队列中添加一条未接收的消息 * * @param chatting * @author Feng */ public void addChatting(Chatting chatting) { LinkedBlockingQueue<Chatting> chattingQueue; if (!chattingHashtable.containsKey(chatting.getReceiverUserId())) { chattingQueue = new LinkedBlockingQueue<Chatting>(); chattingHashtable.put(chatting.getReceiverUserId() + "", chattingQueue); } else chattingQueue = chattingHashtable.get(chatting.getReceiverUserId()); chattingQueue.add(chatting); } /** * 获取未被接收的聊天消息 * * @param receiveUserId * @return * @author Feng */ public ArrayList<Chatting> getChattingNotReceive(String receiveUserId) { if (chattingHashtable.containsKey(receiveUserId)) { LinkedBlockingQueue<Chatting> chattingQueue = chattingHashtable.get(receiveUserId); ArrayList<Chatting> chattingList = new ArrayList<Chatting>(); while (!chattingQueue.isEmpty()) chattingList.add(chattingQueue.poll()); return chattingList; } return new ArrayList<Chatting>(); } /** * 将内存中所有聊天记录存入数据库 * * @author Feng */ public class SaveDataThread extends TimerTask { public void run() { try { Iterator iterator = chattingHashtable.keySet().iterator(); LinkedBlockingQueue<Chatting> queue; // 删除过期消息 Calendar calendar = Calendar.getInstance(); calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR) - 3); Session session = HibernateSessionFactory.getSession(); String sql = "delete from " + Chatting.TABLE_NAME + " where time<" + calendar.getTimeInMillis() + ";"; session.createQuery(sql); session = HibernateSessionFactory.getSession(); while (iterator.hasNext()) { queue = (LinkedBlockingQueue<Chatting>) iterator.next(); // 读取哈希表,存入硬盘 for (Chatting chatting : queue) { session.save(chatting); } } HibernateSessionFactory.commitSession(session); // 清空内存 chattingHashtable.clear(); } catch (Exception e) { Debug.log(Debug.LogType.FAULT, new String[] { "ServerModel_Chatting", "SaveDataThread" }, "Save Chatting which were to long ago Fail!"); } } } // public void test2() { // Iterator iterator = chattingHashtable.keySet().iterator(); // LinkedBlockingQueue<Chatting> queue; // // // 删除过期消息 // Date date = new Date(); // date.setDate(date.getDate() - 3); // // date.setDate(date.getDate() + 3); // Session session = HibernateSessionFactory.getSession(); // String tableName = Chatting.TABLE_NAME; // tableName = tableName.substring(0, 1).toUpperCase() + tableName.substring(2, tableName.length()); // String sql = "delete from " + Chatting.class.getName() + " where time<" + date.getTime(); // session.createQuery(sql); // // HibernateSessionFactory.commitSession(session); // session = HibernateSessionFactory.getSession(); // // session = HibernateSessionFactory.getSession(); // Chatting a = new Chatting("a3", "a4", ChatType.TEXT, "abcde", 20140526, false, 2); // a.setId(1); // session.save(a); // // while (iterator.hasNext()) { // queue = chattingHashtable.get(iterator.next().toString()); // // // 读取哈希表,存入硬盘 // for (Chatting chatting : queue) { // Chatting c = new Chatting(chatting.getSenderUserId(), chatting.getReceiverUserId(), chatting.getChattingType(), // chatting.getMessage(), Calendar.getInstance().getTimeInMillis()); // session.save(c); // // session.save(chatting); // } // } // HibernateSessionFactory.commitSession(session); // // // 清空内存 // chattingHashtable.clear(); // } /** * 测试用 * * @param args * @author Feng */ // private void test() { // addChatting(new Chatting("a", "b", ChatType.TEXT, "Fuck", 0)); // addChatting(new Chatting("c", "d", ChatType.TEXT, "Fuck", 0)); // System.out.println("size: " + chattingHashtable.size()); // // // Timer timer = new Timer(); // // timer.schedule(new SaveDataThread(), 0); // // test2(); // // System.out.println("size: " + chattingHashtable.size()); // } }