openfire 保存离线消息
RoutingTableImpl类中的/* * (non-Javadoc) * @see org.jivesoftware.openfire.RoutingTable#routePacket(org.xmpp.packet.JID, org.xmpp.packet.Packet, boolean) * * @param jid the recipient of the packet to route. * @param packet the packet to route. * @param fromServer true if the packet was created by the server. This packets should * always be delivered * @throws PacketException thrown if the packet is malformed (results in the sender's * session being shutdown). */public void routePacket(JID jid, Packet packet, boolean fromServer) throws PacketException {boolean routed = false;if (serverName.equals(jid.getDomain())) {// Packet sent to our domain.routed = routeToLocalDomain(jid, packet, fromServer);}else if (jid.getDomain().contains(serverName)) {// Packet sent to component hosted in this serverrouted = routeToComponent(jid, packet, routed);}else {// Packet sent to remote serverrouted = routeToRemoteDomain(jid, packet, routed);}if (!routed) {if (Log.isDebugEnabled()) {Log.debug("RoutingTableImpl: Failed to route packet to JID: {} packet: {}", jid, packet.toXML());}if (packet instanceof IQ) {iqRouter.routingFailed(jid, packet);}else if (packet instanceof Message) {//查看routingFailedf()方法里面的内容messageRouter.routingFailed(jid, packet);}else if (packet instanceof Presence) {presenceRouter.routingFailed(jid, packet);}}}/** * Notification message indicating that a packet has failed to be routed to the recipient. * * @param recipient address of the entity that failed to receive the packet. * @param packet Message packet that failed to be sent to the recipient. */public void routingFailed(JID recipient, Packet packet) {// If message was sent to an unavailable full JID of a user then retry using the bare JIDif (serverName.equals(recipient.getDomain()) && recipient.getResource() != null &&userManager.isRegisteredUser(recipient.getNode())) {routingTable.routePacket(recipient.asBareJID(), packet, false);} else {// Just store the message offline//将消息保存到数据库中ofoffline表中messageStrategy.storeOffline((Message) packet);}}备注:userManager.isRegisteredUser(recipient.getNode())这个类会判断用户是否是注册用户,/** * Returns true if the specified local username belongs to a registered local user. * * @param username to username of the user to check it it's a registered user. * @return true if the specified JID belongs to a local registered user. */public boolean isRegisteredUser(String username) {if (username == null || "".equals(username)) {return false;}try {getUser(username);return true;}catch (UserNotFoundException e) {return false;}}备注:getUser(username)就是从缓存或者数据库中查询用户/** * Returns the User specified by username. * * @param username the username of the user. * @return the User that matches <tt>username</tt>. * @throws UserNotFoundException if the user does not exist. */public User getUser(String username) throws UserNotFoundException {if (username == null) {throw new UserNotFoundException("Username cannot be null");}// Make sure that the username is valid.username = username.trim().toLowerCase();//判断用户是否在缓存中User user = userCache.get(username);if (user == null) {synchronized (username.intern()) {user = userCache.get(username);if (user == null) {//用户不在缓存中则从数据库中查询这个用户是否在用户表中,如果存在则放入缓存中user = provider.loadUser(username);userCache.put(username, user);}}}return user;}备注:provider是UserProvider接口的实例,这个接口就是访问用户表的接口,具体的实现类是根据具体的配置实现的,可以在ofproperty中查询这个接口
?