- 浏览: 732352 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
18335864773:
看了楼主写的用jxl生成excel。有地方用到了流,还特别强调 ...
jxl导出excel文件简单示例 -
shaoshou111:
查看Apache的并发请求数及其TCP连接状态netstat ...
Linux查看连接数,并发数 -
gengjunshi:
非常感谢哈,刚好在学webservice编程,很有用呢。
JAX-WS开发webservice示例详解 -
zcgewu:
encrypt2()和encrypt()有什么区别
JAVA实现AES加密 -
java爱好者92:
ireport的操作还是相对比较复杂的,帆软报表会相对简单一点 ...
iReport报表开发中常见的问题
- 在XMPP消息推送这个问题上,网上已经有很多资料了,本人觉得很好的一篇资料是:http://www.iteye.com/topic/1117043
- 提供了一个连接下载源码:http://115.com/file/bhkfse3i#%20Androidpn.rar
- 很感谢前辈们的研究结果。
- 在源码的使用过程中要注意的地方有两点,网上的那篇资料好像忽略了一个重要的地方,就是要改resources文件夹下面的jdbc.properties,将里面关于数据库的配置改为自己的,另一个需要注意的地方就是改android端的ip了。
在项目部署到tomcat下之后,发现了不少的bug,其中一个就是当tomcat重新启动,客户端的连接将断开,不能进行自动重连。
对于这个BUG,我们可以在Androidpn-clieng下的XmppManager这个类中做简要的处理即可修改。源码如下:
/* * Copyright (C) 2010 Moduad Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.androidpn.client; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.Future; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketIDFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Registration; import org.jivesoftware.smack.provider.ProviderManager; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Handler; import android.util.Log; /** * This class is to manage the XMPP connection between client and server. * * @author Sehwan Noh (devnoh@gmail.com) */ public class XmppManager { private static final String LOGTAG = LogUtil.makeLogTag(XmppManager.class); private static final String XMPP_RESOURCE_NAME = "AndroidpnClient"; private Context context; private NotificationService.TaskSubmitter taskSubmitter; private NotificationService.TaskTracker taskTracker; private SharedPreferences sharedPrefs; private String xmppHost; private int xmppPort; private XMPPConnection connection; private String username; private String password; private ConnectionListener connectionListener; private PacketListener notificationPacketListener; private Handler handler; private List<Runnable> taskList; private boolean running = false; private Future<?> futureTask; private Thread reconnection; public XmppManager(NotificationService notificationService) { context = notificationService; taskSubmitter = notificationService.getTaskSubmitter(); taskTracker = notificationService.getTaskTracker(); sharedPrefs = notificationService.getSharedPreferences(); xmppHost = sharedPrefs.getString(Constants.XMPP_HOST, "localhost"); xmppPort = sharedPrefs.getInt(Constants.XMPP_PORT, 5222); username = sharedPrefs.getString(Constants.XMPP_USERNAME, ""); password = sharedPrefs.getString(Constants.XMPP_PASSWORD, ""); connectionListener = new PersistentConnectionListener(this); notificationPacketListener = new NotificationPacketListener(this); handler = new Handler(); taskList = new ArrayList<Runnable>(); reconnection = new ReconnectionThread(this); } public Context getContext() { return context; } public void connect() { Log.d(LOGTAG, "connect()..."); submitLoginTask(); } public void disconnect() { Log.d(LOGTAG, "disconnect()..."); terminatePersistentConnection(); } public void terminatePersistentConnection() { Log.d(LOGTAG, "terminatePersistentConnection()..."); Runnable runnable = new Runnable() { final XmppManager xmppManager = XmppManager.this; public void run() { if (xmppManager.isConnected()) { Log.d(LOGTAG, "terminatePersistentConnection()... run()"); xmppManager.getConnection().removePacketListener( xmppManager.getNotificationPacketListener()); xmppManager.getConnection().disconnect(); } xmppManager.runTask(); } }; addTask(runnable); } public XMPPConnection getConnection() { return connection; } public void setConnection(XMPPConnection connection) { this.connection = connection; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public ConnectionListener getConnectionListener() { return connectionListener; } public PacketListener getNotificationPacketListener() { return notificationPacketListener; } public void startReconnectionThread() { synchronized (reconnection) { if (!reconnection.isAlive()) { reconnection.setName("Xmpp Reconnection Thread"); reconnection.start(); } } } public Handler getHandler() { return handler; } public void reregisterAccount() { removeAccount(); submitLoginTask(); runTask(); } public List<Runnable> getTaskList() { return taskList; } public Future<?> getFutureTask() { return futureTask; } public void runTask() { Log.d(LOGTAG, "runTask()..."); synchronized (taskList) { running = false; futureTask = null; if (!taskList.isEmpty()) { Runnable runnable = (Runnable) taskList.get(0); taskList.remove(0); running = true; futureTask = taskSubmitter.submit(runnable); if (futureTask == null) { taskTracker.decrease(); } } } taskTracker.decrease(); Log.d(LOGTAG, "runTask()...done"); } private String newRandomUUID() { String uuidRaw = UUID.randomUUID().toString(); return uuidRaw.replaceAll("-", ""); } private boolean isConnected() { return connection != null && connection.isConnected(); } private boolean isAuthenticated() { return connection != null && connection.isConnected() && connection.isAuthenticated(); } private boolean isRegistered() { return sharedPrefs.contains(Constants.XMPP_USERNAME) && sharedPrefs.contains(Constants.XMPP_PASSWORD); } private void submitConnectTask() { Log.d(LOGTAG, "submitConnectTask()..."); addTask(new ConnectTask()); } private void submitRegisterTask() { Log.d(LOGTAG, "submitRegisterTask()..."); submitConnectTask(); addTask(new RegisterTask()); } private void submitLoginTask() { Log.d(LOGTAG, "submitLoginTask()..."); submitRegisterTask(); addTask(new LoginTask()); } private void addTask(Runnable runnable) { Log.d(LOGTAG, "addTask(runnable)..."); taskTracker.increase(); synchronized (taskList) { if (taskList.isEmpty() && !running) { running = true; futureTask = taskSubmitter.submit(runnable); if (futureTask == null) { taskTracker.decrease(); } } else { taskList.add(runnable); } } Log.d(LOGTAG, "addTask(runnable)... done"); } private void removeAccount() { Editor editor = sharedPrefs.edit(); editor.remove(Constants.XMPP_USERNAME); editor.remove(Constants.XMPP_PASSWORD); editor.commit(); } /** * A runnable task to connect the server. */ private class ConnectTask implements Runnable { final XmppManager xmppManager; private ConnectTask() { this.xmppManager = XmppManager.this; } public void run() { Log.i(LOGTAG, "ConnectTask.run()..."); if (!xmppManager.isConnected()) { // Create the configuration for this new connection ConnectionConfiguration connConfig = new ConnectionConfiguration( xmppHost, xmppPort); // connConfig.setSecurityMode(SecurityMode.disabled); connConfig.setSecurityMode(SecurityMode.required); connConfig.setSASLAuthenticationEnabled(false); connConfig.setCompressionEnabled(false); XMPPConnection connection = new XMPPConnection(connConfig); xmppManager.setConnection(connection); try { // Connect to the server connection.connect(); Log.i(LOGTAG, "XMPP connected successfully"); // packet provider ProviderManager.getInstance().addIQProvider("notification", "androidpn:iq:notification", new NotificationIQProvider()); } catch (XMPPException e) { Log.e(LOGTAG, "XMPP connection failed", e); } xmppManager.runTask(); } else { Log.i(LOGTAG, "XMPP connected already"); xmppManager.runTask(); } } } /** * A runnable task to register a new user onto the server. */ private class RegisterTask implements Runnable { final XmppManager xmppManager; private RegisterTask() { xmppManager = XmppManager.this; } public void run() { Log.i(LOGTAG, "RegisterTask.run()..."); //如果账号不存在的话,随机生成一个uuid的用户名和mima if (!xmppManager.isRegistered()) { final String newUsername = newRandomUUID(); final String newPassword = newRandomUUID(); // final String newUsername = "af100042487d4b06a49adda8c3a82d41"; // final String newPassword = "af100042487d4b06a49adda8c3a82d41"; Registration registration = new Registration(); PacketFilter packetFilter = new AndFilter(new PacketIDFilter( registration.getPacketID()), new PacketTypeFilter( IQ.class)); PacketListener packetListener = new PacketListener() { public void processPacket(Packet packet) { Log.d("RegisterTask.PacketListener", "processPacket()....."); Log.d("RegisterTask.PacketListener", "packet=" + packet.toXML()); if (packet instanceof IQ) { IQ response = (IQ) packet; if (response.getType() == IQ.Type.ERROR) { if (!response.getError().toString().contains( "409")) { Log.e(LOGTAG, "Unknown error while registering XMPP account! " + response.getError() .getCondition()); } } else if (response.getType() == IQ.Type.RESULT) { xmppManager.setUsername(newUsername); xmppManager.setPassword(newPassword); Log.d(LOGTAG, "username=" + newUsername); Log.d(LOGTAG, "password=" + newPassword); Editor editor = sharedPrefs.edit(); editor.putString(Constants.XMPP_USERNAME, newUsername); editor.putString(Constants.XMPP_PASSWORD, newPassword); editor.commit(); Log .i(LOGTAG, "Account registered successfully"); xmppManager.runTask(); } } } }; connection.addPacketListener(packetListener, packetFilter); registration.setType(IQ.Type.SET); // registration.setTo(xmppHost); // Map<String, String> attributes = new HashMap<String, String>(); // attributes.put("username", rUsername); // attributes.put("password", rPassword); // registration.setAttributes(attributes); registration.addAttribute("username", newUsername); registration.addAttribute("password", newPassword); connection.sendPacket(registration); } else { Log.i(LOGTAG, "Account registered already"); xmppManager.runTask(); } } } /** * A runnable task to log into the server. */ private class LoginTask implements Runnable { final XmppManager xmppManager; private LoginTask() { this.xmppManager = XmppManager.this; } public void run() { Log.i(LOGTAG, "LoginTask.run()..."); if (!xmppManager.isAuthenticated()) { Log.d(LOGTAG, "username=" + username); Log.d(LOGTAG, "password=" + password); try { xmppManager.getConnection().login( xmppManager.getUsername(), xmppManager.getPassword(), XMPP_RESOURCE_NAME); Log.d(LOGTAG, "Loggedn in successfully"); // connection listener if (xmppManager.getConnectionListener() != null) { xmppManager.getConnection().addConnectionListener( xmppManager.getConnectionListener()); } // packet filter PacketFilter packetFilter = new PacketTypeFilter( NotificationIQ.class); // packet listener PacketListener packetListener = xmppManager .getNotificationPacketListener(); connection.addPacketListener(packetListener, packetFilter); //判断是否处于连接状态(添加) if(!getConnection().isConnected()) { xmppManager.runTask(); } xmppManager.runTask(); } catch (XMPPException e) { Log.e(LOGTAG, "LoginTask.run()... xmpp error"); Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: " + e.getMessage()); String INVALID_CREDENTIALS_ERROR_CODE = "401"; String errorMessage = e.getMessage(); if (errorMessage != null && errorMessage .contains(INVALID_CREDENTIALS_ERROR_CODE)) { xmppManager.reregisterAccount(); return; } xmppManager.startReconnectionThread(); } catch (Exception e) { Log.e(LOGTAG, "LoginTask.run()... other error"); Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: " + e.getMessage()); xmppManager.startReconnectionThread(); } //添加 xmppManager.runTask(); } else { Log.i(LOGTAG, "Logged in already"); xmppManager.runTask(); } } } }
新添加代码450-454行和477行
还有一个问题是:当客户端的用户有不在线的时候,消息应怎么进行推送,是直接忽略呢还是下次登录的时候在进行推送,想qq那样,很显然对已一个具体的实用项目来说是不能忽略的,那么怎么进行消息的离线推送呢,下次告诉大家,因为我现在还没解决,不过快了。和大家说下我的思路吧:在androidpn服务端有一个UserController这个类,源码如下:
View Code /* * Copyright (C) 2010 Moduad Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.androidpn.server.console.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.androidpn.server.model.User; import org.androidpn.server.service.ServiceLocator; import org.androidpn.server.service.UserService; import org.androidpn.server.xmpp.presence.PresenceManager; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.multiaction.MultiActionController; /** * A controller class to process the user related requests. * * @author Sehwan Noh (devnoh@gmail.com) */ public class UserController extends MultiActionController { private UserService userService; public UserController() { userService = ServiceLocator.getUserService(); } //用户列表 public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws Exception { PresenceManager presenceManager = new PresenceManager(); List<User> userList = userService.getUsers(); for (User user : userList) { if (presenceManager.isAvailable(user)) { // Presence presence = presenceManager.getPresence(user); user.setOnline(true); } else { user.setOnline(false); } // logger.debug("user.online=" + user.isOnline()); } ModelAndView mav = new ModelAndView(); mav.addObject("userList", userList); mav.setViewName("user/list"); return mav; } }
该源码里面有用户是否在线的判断,我们只要将用户的列表取出来,如果用户在线就将消息进行推送,如果有不在线的用户,我们就把该消息放到缓存中(也可以放到数据库中更加保险),当然为了防止用户过长没有登陆系统,导致下次登录时出现过多托送过来的消息,我们还可以在服务端进行设置时间,比如服务端只缓存近N天的消息,利用
session.getCreationDate(); session.getLastActiveDate();
这两句代码应该可以完成,本人没尝试过,还不知道。效果如如下:
发表评论
-
nginx反向代理后,打开页面很慢
2020-05-26 11:26 5143nginx反向代理后,打开页面很慢 在做前后端完全分离的 ... -
【国】前后端国际化的问题
2020-04-23 17:21 995前端有国际化,但是后端service无法使用国际化。 原 ... -
(转)Java jacob调用打印机打印word文档
2017-12-01 17:33 3747折腾了好久,最终决定由用一个第三方的,找到了jacob,还不 ... -
BIRT参数设置详解
2016-05-18 15:15 4386在使用birt报表的时候感 ... -
gson的使用分享
2016-01-15 13:48 1815一、 最基本的对象与JSON相互转换 1、 定义java对象 ... -
(转)FindBugs规则整理
2015-12-18 10:40 6603FindBugs是基于Bug Patterns ... -
Gson注解和GsonBuilder
2015-04-07 11:49 1684//注意这里的Gson的构建方式为GsonBuilder, ... -
javax.xml.ws.soap.SOAPFaultException: Cannot create a secure XMLInputFactory
2014-06-04 20:26 1793javax.xml.ws.soap.SOAPFaultExce ... -
照片打包下载
2014-05-22 09:32 1219设计思路: 通过业务表中照片编号获得需要下载的照片列表 ... -
Oracle merge 合并
2013-10-21 09:38 1319@Transactional public void ... -
httpclient测试请求方法
2013-09-22 15:24 3689貌似很多人不知道服务器端代码怎么写,在此mark一下: ... -
jxl导入excel
2013-09-17 16:56 924jxl读取excel和写excel基本类似,只是Writab ... -
findbugs清理总结
2013-08-19 14:45 3005findbugs警告26个。主要有以下9类问题。 1、B ... -
JAX-WS开发webservice示例详解
2013-08-09 11:06 24059目录: 概述 实验环境 服务端的实现 客户端的实 ... -
将传进来的十六进制表示的字符串转换成byte数组 文件下载
2013-06-06 22:36 1786/** * 将传进来的十六进制表示的字符串转换成by ... -
Java:定时启动线程及线程池的用法
2013-05-23 18:01 3966这里提供两种在指定时间后启动线程的方法。一是通过java.ut ... -
依赖倒转原则
2013-04-13 12:31 988A、高层模块不应该依赖低层模块,两个都应该依赖抽象。 B、抽象 ... -
策略模式
2013-04-12 17:31 1030策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替 ... -
调用xfire发布的wsdl遇到的问题
2013-02-20 14:25 1159java.lang.NoClassDefFoundError ... -
(转)在java中通过JDBC连接Oracle,ResultSet返回总为空,这个问题是怎么解决呢
2013-01-08 10:38 16419数据库基本访问格式 Class.forName(“JDBC驱动 ...
相关推荐
在Tomcat中部署XMPP服务,可以使用Openfire或者Ignite Real Time等支持XMPP的服务器软件。 接着,你需要设置MySQL数据库。确保MySQL服务已经启动,并创建一个用于AndroidPN的数据库。数据库中需要包含用于存储用户...
然后,在服务器的“发布”目录下,将AndroidPN-server的构建结果(WAR文件或已编译的类文件)部署到适当的位置,通常是`webapps`目录。 4. **配置XML文件**:AndroidPN-server可能需要一些特定的XML配置文件,例如`...
8. **故障排查**:在部署和运行AndroidPN-tomcat时,可能会遇到各种问题,如网络连接问题、服务器配置错误或客户端兼容性问题。掌握基本的故障排查技巧非常重要。 9. **性能优化**:为了提供良好的用户体验,开发者...
将此WAR文件放入Tomcat的webapps目录下,Tomcat会自动部署该应用。 4. **配置服务器**:根据项目文档,配置AndroidPN服务器的XML配置文件,如server.xml和context.xml,设置数据库连接、端口等参数。 5. **创建...
另一方面,"androidpn-server-tomcat.zip"则包含了AndroidPN服务端的部署包,这部分是基于Tomcat服务器运行的。Tomcat是Apache软件基金会的Jakarta项目下的一个开源产品,它实现了Java Servlet和JavaServer Pages...
2. **独立WebServer与Openfire通信**:另一种方法是将WebServer(如Apache Tomcat、Nginx或Lighttpd)与Openfire分开部署,通过HTTP或者XMPP协议进行通信。这种方式下,WebServer负责处理HTTP请求,而Openfire专注于...
一旦构建成功,Openfire会产生一个可运行的WAR文件,可以部署到任何支持Java Servlet容器的应用服务器上,如Tomcat或Jetty。如果你选择Tomcat,将WAR文件复制到Tomcat的webapps目录下,Tomcat会自动解压并启动...
在部署Openfire WebChat时,你需要将这些JAR文件添加到你的应用服务器(如Tomcat)的类路径中,确保服务器能够正确处理JSP并编译它们为Servlet。通常,这可以通过将这些文件放入服务器的lib目录来实现。一旦完成,...
要将ActiveMQ与Tomcat整合,你需要完成以下步骤: 1. **下载和安装ActiveMQ**: 获取ActiveMQ的最新版本,并解压到合适的位置。 2. **配置ActiveMQ**: 修改`conf.activemq.xml`配置文件,设置所需的参数,如端口、...
- `XMPPServer`: 负责处理客户端的连接和断开,接收推送消息。 - `NotificationManager`: 存储和管理设备注册信息,负责消息的广播。 - `DatabaseAccess`: 使用Hibernate操作数据库,存储用户和设备信息。 二、...
它将所有静态和动态资源集成在一起,便于在支持Java EE的服务器上进行部署,如Tomcat、Jetty或Glassfish等。 2. **fastpath-webchat**:Fastpath-Webchat是一个互动式聊天平台,旨在增强openfire即时通讯系统的功能...
- **服务端**:接收到推送请求后,服务端会验证请求的有效性,然后通过网络协议(如HTTP或XMPP)将消息发送给指定的客户端。服务端通常维护一个客户端在线状态的数据库,以便在需要时向特定客户端推送消息。 - **...
集成过程通常包括配置ActiveMQ为Tomcat的独立服务或者作为Tomcat内部模块,通过修改Tomcat的服务器配置文件(如`server.xml`)来设置ActiveMQ的相关参数。 **使用Apache ActiveMQ-5.11.3需要注意:** 1. **硬件和...
在服务器端部署中,AndroidPn-server-0.5.0需要在Tomcat上运行,配合MySQL数据库。客户端则接收即时推送信息,提供用户友好的交互界面。 总结来说,Android平台的消息推送技术通过优化的推送机制和协议,如XMPP,...
AndroidPN的源代码结构包含了服务器端和客户端的相关模块,例如,`org.androidpn.server.xmpp.net.Connection`类代表服务器的XMPP连接,而`org.androidpn.server.xmpp.session.SessionManager`负责会话管理。...
- **jersey-servlet-1.19.jar**:提供了Servlet容器的适配器,使得Jersey可以部署在Web应用服务器上,如Tomcat。 - **javax.ws.rs-api-2.0.jar**:定义了JAX-RS 2.0标准的接口,是RESTful服务开发的基础。 4. **...
例如,`xmpp-server`模块包含了处理连接、认证、会话管理和消息路由的类。通过解析XML流,Openfire可以理解客户端的需求,如登录、发送消息或建立多用户聊天室。 三、源码关键模块分析 1. 用户管理:`user`模块是...
10. **负载均衡与分布式**:随着用户量的增加,系统可能需要部署在多台服务器上,这就涉及到负载均衡和分布式计算的概念。Java的NIO(New I/O)库和Netty框架可以帮助实现高性能的网络通信,而像Apache Tomcat这样的...
3. **部署**:将应用程序部署到生产环境,如AWS、Azure或阿里云等云服务平台,保证服务的稳定性和可扩展性。 4. **监控**:通过日志分析、性能监控工具(如Prometheus、Grafana)对系统运行状态进行监控,及时发现...
- 将RED5应用部署到Web服务器中,例如Apache Tomcat。 - 配置RED5应用的基本设置,确保其能够与Openfire和Spark客户端协同工作。 ##### 5.2 Spark客户端配置视频插件 - 在Spark客户端中启用视频插件,以便支持视频...