好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

关于将XMPP server部署到Tomcat上的一些问题

关于将XMPP server部署到Tomcat上的一些问题

在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这个类中做简要的处理即可修改。源码如下:

   1   /* 
   2    * Copyright (C) 2010 Moduad Co., Ltd.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *        http://www.apache.org/licenses/LICENSE-2.0 
   9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */ 
  16   package   org.androidpn.client;
   17  
  18   import   java.util.ArrayList;
   19   import   java.util.List;
   20   import   java.util.UUID;
   21   import   java.util.concurrent.Future;
   22  
  23   import   org.jivesoftware.smack.ConnectionConfiguration;
   24   import   org.jivesoftware.smack.ConnectionListener;
   25   import   org.jivesoftware.smack.PacketListener;
   26   import   org.jivesoftware.smack.XMPPConnection;
   27   import   org.jivesoftware.smack.XMPPException;
   28   import   org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
   29   import   org.jivesoftware.smack.filter.AndFilter;
   30   import   org.jivesoftware.smack.filter.PacketFilter;
   31   import   org.jivesoftware.smack.filter.PacketIDFilter;
   32   import   org.jivesoftware.smack.filter.PacketTypeFilter;
   33   import   org.jivesoftware.smack.packet.IQ;
   34   import   org.jivesoftware.smack.packet.Packet;
   35   import   org.jivesoftware.smack.packet.Registration;
   36   import   org.jivesoftware.smack.provider.ProviderManager;
   37  
  38   import   android.content.Context;
   39   import   android.content.SharedPreferences;
   40   import   android.content.SharedPreferences.Editor;
   41   import   android.os.Handler;
   42   import   android.util.Log;
   43  
  44  
  45   /** 
  46    * This class is to manage the XMPP connection between client and server.
   47    * 
   48    *   @author   Sehwan Noh (devnoh@gmail.com)
   49    */ 
  50   public   class   XmppManager {
   51  
  52       private   static   final  String LOGTAG = LogUtil.makeLogTag(XmppManager. class  );
   53  
  54       private   static   final  String XMPP_RESOURCE_NAME = "AndroidpnClient" ;
   55  
  56       private   Context context;
   57  
  58       private   NotificationService.TaskSubmitter taskSubmitter;
   59  
  60       private   NotificationService.TaskTracker taskTracker;
   61  
  62       private   SharedPreferences sharedPrefs;
   63  
  64       private   String xmppHost;
   65  
  66       private   int   xmppPort;
   67  
  68       private   XMPPConnection connection;
   69  
  70       private   String username;
   71  
  72       private   String password;
   73  
  74       private   ConnectionListener connectionListener;
   75  
  76       private   PacketListener notificationPacketListener;
   77  
  78       private   Handler handler;
   79  
  80       private  List<Runnable>  taskList;
   81  
  82       private   boolean  running =  false  ;
   83  
  84       private  Future<?>  futureTask;
   85  
  86       private   Thread reconnection;
   87  
  88       public   XmppManager(NotificationService notificationService) {
   89          context =  notificationService;
   90          taskSubmitter =  notificationService.getTaskSubmitter();
   91          taskTracker =  notificationService.getTaskTracker();
   92          sharedPrefs =  notificationService.getSharedPreferences();
   93  
  94          xmppHost = sharedPrefs.getString(Constants.XMPP_HOST, "localhost" );
   95          xmppPort = sharedPrefs.getInt(Constants.XMPP_PORT, 5222 );
   96          username = sharedPrefs.getString(Constants.XMPP_USERNAME, "" );
   97          password = sharedPrefs.getString(Constants.XMPP_PASSWORD, "" );
   98  
  99          connectionListener =  new  PersistentConnectionListener( this  );
  100          notificationPacketListener =  new  NotificationPacketListener( this  );
  101  
 102          handler =  new   Handler();
  103          taskList =  new  ArrayList<Runnable> ();
  104          reconnection =  new  ReconnectionThread( this  );
  105       }
  106  
 107       public   Context getContext() {
  108           return   context;
  109       }
  110  
 111       public   void   connect() {
  112          Log.d(LOGTAG, "connect()..." );
  113           submitLoginTask();
  114       }
  115  
 116       public   void   disconnect() {
  117          Log.d(LOGTAG, "disconnect()..." );
  118           terminatePersistentConnection();
  119       }
  120  
 121       public   void   terminatePersistentConnection() {
  122          Log.d(LOGTAG, "terminatePersistentConnection()..." );
  123          Runnable runnable =  new   Runnable() {
  124  
 125               final  XmppManager xmppManager = XmppManager. this  ;
  126  
 127               public   void   run() {
  128                   if   (xmppManager.isConnected()) {
  129                      Log.d(LOGTAG, "terminatePersistentConnection()... run()" );
  130                       xmppManager.getConnection().removePacketListener(
  131                               xmppManager.getNotificationPacketListener());
  132                       xmppManager.getConnection().disconnect();
  133                   }
  134                   xmppManager.runTask();
  135               }
  136  
 137           };
  138           addTask(runnable);
  139       }
  140  
 141       public   XMPPConnection getConnection() {
  142           return   connection;
  143       }
  144  
 145       public   void   setConnection(XMPPConnection connection) {
  146           this .connection =  connection;
  147       }
  148  
 149       public   String getUsername() {
  150           return   username;
  151       }
  152  
 153       public   void   setUsername(String username) {
  154           this .username =  username;
  155       }
  156  
 157       public   String getPassword() {
  158           return   password;
  159       }
  160  
 161       public   void   setPassword(String password) {
  162           this .password =  password;
  163       }
  164  
 165       public   ConnectionListener getConnectionListener() {
  166           return   connectionListener;
  167       }
  168  
 169       public   PacketListener getNotificationPacketListener() {
  170           return   notificationPacketListener;
  171       }
  172  
 173       public   void   startReconnectionThread() {
  174           synchronized   (reconnection) {
  175               if  (! reconnection.isAlive()) {
  176                  reconnection.setName("Xmpp Reconnection Thread" );
  177                   reconnection.start();
  178               }
  179           }
  180       }
  181  
 182       public   Handler getHandler() {
  183           return   handler;
  184       }
  185  
 186       public   void   reregisterAccount() {
  187           removeAccount();
  188           submitLoginTask();
  189           runTask();
  190       }
  191  
 192       public  List<Runnable>  getTaskList() {
  193           return   taskList;
  194       }
  195  
 196       public  Future<?>  getFutureTask() {
  197           return   futureTask;
  198       }
  199  
 200       public   void   runTask() {
  201          Log.d(LOGTAG, "runTask()..." );
  202           synchronized   (taskList) {
  203              running =  false  ;
  204              futureTask =  null  ;
  205               if  (! taskList.isEmpty()) {
  206                  Runnable runnable = (Runnable) taskList.get(0 );
  207                  taskList.remove(0 );
  208                  running =  true  ;
  209                  futureTask =  taskSubmitter.submit(runnable);
  210                   if  (futureTask ==  null  ) {
  211                       taskTracker.decrease();
  212                   }
  213               }
  214           }
  215           taskTracker.decrease();
  216          Log.d(LOGTAG, "runTask()...done" );
  217       }
  218  
 219       private   String newRandomUUID() {
  220          String uuidRaw =  UUID.randomUUID().toString();
  221           return  uuidRaw.replaceAll("-", "" );
  222       }
  223  
 224       private   boolean   isConnected() {
  225           return  connection !=  null  &&  connection.isConnected();
  226       }
  227  
 228       private   boolean   isAuthenticated() {
  229           return  connection !=  null  &&  connection.isConnected()
  230                  &&  connection.isAuthenticated();
  231       }
  232  
 233       private   boolean   isRegistered() {
  234           return   sharedPrefs.contains(Constants.XMPP_USERNAME)
  235                  &&  sharedPrefs.contains(Constants.XMPP_PASSWORD);
  236       }
  237  
 238       private   void   submitConnectTask() {
  239          Log.d(LOGTAG, "submitConnectTask()..." );
  240          addTask( new   ConnectTask());
  241       }
  242  
 243       private   void   submitRegisterTask() {
  244          Log.d(LOGTAG, "submitRegisterTask()..." );
  245           submitConnectTask();
  246          addTask( new   RegisterTask());
  247       }
  248  
 249       private   void   submitLoginTask() {
  250          Log.d(LOGTAG, "submitLoginTask()..." );
  251           submitRegisterTask();
  252          addTask( new   LoginTask());
  253       }
  254  
 255       private   void   addTask(Runnable runnable) {
  256          Log.d(LOGTAG, "addTask(runnable)..." );
  257           taskTracker.increase();
  258           synchronized   (taskList) {
  259               if  (taskList.isEmpty() && ! running) {
  260                  running =  true  ;
  261                  futureTask =  taskSubmitter.submit(runnable);
  262                   if  (futureTask ==  null  ) {
  263                       taskTracker.decrease();
  264                   }
  265              }  else   {
  266                   taskList.add(runnable);
  267               }
  268           }
  269          Log.d(LOGTAG, "addTask(runnable)... done" );
  270       }
  271  
 272       private   void   removeAccount() {
  273          Editor editor =  sharedPrefs.edit();
  274           editor.remove(Constants.XMPP_USERNAME);
  275           editor.remove(Constants.XMPP_PASSWORD);
  276           editor.commit();
  277       }
  278  
 279       /** 
 280        * A runnable task to connect the server. 
  281        */ 
 282       private   class  ConnectTask  implements   Runnable {
  283  
 284           final   XmppManager xmppManager;
  285  
 286           private   ConnectTask() {
  287               this .xmppManager = XmppManager. this  ;
  288           }
  289  
 290           public   void   run() {
  291              Log.i(LOGTAG, "ConnectTask.run()..." );
  292  
 293               if  (! xmppManager.isConnected()) {
  294                   //   Create the configuration for this new connection 
 295                  ConnectionConfiguration connConfig =  new   ConnectionConfiguration(
  296                           xmppHost, xmppPort);
  297                   //   connConfig.setSecurityMode(SecurityMode.disabled); 
 298                   connConfig.setSecurityMode(SecurityMode.required);
  299                  connConfig.setSASLAuthenticationEnabled( false  );
  300                  connConfig.setCompressionEnabled( false  );
  301  
 302                  XMPPConnection connection =  new   XMPPConnection(connConfig);
  303                   xmppManager.setConnection(connection);
  304  
 305                   try   {
  306                       //   Connect to the server 
 307                       connection.connect();
  308                      Log.i(LOGTAG, "XMPP connected successfully" );
  309  
 310                       //   packet provider 
 311                      ProviderManager.getInstance().addIQProvider("notification" ,
  312                              "androidpn:iq:notification" ,
  313                               new   NotificationIQProvider());
  314  
 315                  }  catch   (XMPPException e) {
  316                      Log.e(LOGTAG, "XMPP connection failed" , e);
  317                   }
  318  
 319                   xmppManager.runTask();
  320  
 321              }  else   {
  322                  Log.i(LOGTAG, "XMPP connected already" );
  323                   xmppManager.runTask();
  324               }
  325           }
  326       }
  327  
 328       /** 
 329        * A runnable task to register a new user onto the server. 
  330        */ 
 331       private   class  RegisterTask  implements   Runnable {
  332  
 333           final   XmppManager xmppManager;
  334  
 335           private   RegisterTask() {
  336              xmppManager = XmppManager. this  ;
  337           }
  338  
 339           public   void   run() {
  340              Log.i(LOGTAG, "RegisterTask.run()..." );
  341  
 342               //  如果账号不存在的话,随机生成一个uuid的用户名和mima 
 343               if  (! xmppManager.isRegistered()) {
  344                   final  String newUsername =  newRandomUUID();
  345                   final  String newPassword =  newRandomUUID();
  346                   //   final String newUsername = "af100042487d4b06a49adda8c3a82d41";
  347                   //   final String newPassword = "af100042487d4b06a49adda8c3a82d41"; 
 348                  
 349                  Registration registration =  new   Registration();
  350  
 351                  PacketFilter packetFilter =  new  AndFilter( new   PacketIDFilter(
  352                          registration.getPacketID()),  new   PacketTypeFilter(
  353                          IQ. class  ));
  354  
 355                  PacketListener packetListener =  new   PacketListener() {
  356  
 357                       public   void   processPacket(Packet packet) {
  358                          Log.d("RegisterTask.PacketListener" ,
  359                                  "processPacket()....." );
  360                          Log.d("RegisterTask.PacketListener", "packet="
 361                                  +  packet.toXML());
  362  
 363                           if  (packet  instanceof   IQ) {
  364                              IQ response =  (IQ) packet;
  365                               if  (response.getType() ==  IQ.Type.ERROR) {
  366                                   if  (! response.getError().toString().contains(
  367                                          "409" )) {
  368                                       Log.e(LOGTAG,
  369                                              "Unknown error while registering XMPP account! "
 370                                                      +  response.getError()
  371                                                               .getCondition());
  372                                   }
  373                              }  else   if  (response.getType() ==  IQ.Type.RESULT) {
  374                                   xmppManager.setUsername(newUsername);
  375                                   xmppManager.setPassword(newPassword);
  376                                  Log.d(LOGTAG, "username=" +  newUsername);
  377                                  Log.d(LOGTAG, "password=" +  newPassword);
  378  
 379                                  Editor editor =  sharedPrefs.edit();
  380                                   editor.putString(Constants.XMPP_USERNAME,
  381                                           newUsername);
  382                                   editor.putString(Constants.XMPP_PASSWORD,
  383                                           newPassword);
  384                                   editor.commit();
  385                                   Log
  386                                           .i(LOGTAG,
  387                                                  "Account registered successfully" );
  388                                   xmppManager.runTask();
  389                               }
  390                           }
  391                       }
  392                   };
  393  
 394                   connection.addPacketListener(packetListener, packetFilter);
  395  
 396                   registration.setType(IQ.Type.SET);
  397                   //   registration.setTo(xmppHost);
  398                   //   Map<String, String> attributes = new HashMap<String, String>();
  399                   //   attributes.put("username", rUsername);
  400                   //   attributes.put("password", rPassword);
  401                   //   registration.setAttributes(attributes); 
 402                  registration.addAttribute("username" , newUsername);
  403                  registration.addAttribute("password" , newPassword);
  404                   connection.sendPacket(registration);
  405  
 406              }  else   {
  407                  Log.i(LOGTAG, "Account registered already" );
  408                   xmppManager.runTask();
  409               }
  410           }
  411       }
  412  
 413       /** 
 414        * A runnable task to log into the server. 
  415        */ 
 416       private   class  LoginTask  implements   Runnable {
  417  
 418           final   XmppManager xmppManager;
  419  
 420           private   LoginTask() {
  421               this .xmppManager = XmppManager. this  ;
  422           }
  423  
 424           public   void   run() {
  425              Log.i(LOGTAG, "LoginTask.run()..." );
  426  
 427               if  (! xmppManager.isAuthenticated()) {
  428                  Log.d(LOGTAG, "username=" +  username);
  429                  Log.d(LOGTAG, "password=" +  password);
  430  
 431                   try   {
  432                       xmppManager.getConnection().login(
  433                               xmppManager.getUsername(),
  434                               xmppManager.getPassword(), XMPP_RESOURCE_NAME);
  435                      Log.d(LOGTAG, "Loggedn in successfully" );
  436  
 437                       //   connection listener 
 438                       if  (xmppManager.getConnectionListener() !=  null  ) {
  439                           xmppManager.getConnection().addConnectionListener(
  440                                   xmppManager.getConnectionListener());
  441                       }
  442  
 443                       //   packet filter 
 444                      PacketFilter packetFilter =  new   PacketTypeFilter(
  445                              NotificationIQ. class  );
  446                       //   packet listener 
 447                      PacketListener packetListener =  xmppManager
  448                               .getNotificationPacketListener();
  449                       connection.addPacketListener(packetListener, packetFilter);
  450                     //  判断是否处于连接状态(添加) 
 451                       if (! getConnection().isConnected())
  452                       {
  453                            xmppManager.runTask();
  454                       }
  455                       xmppManager.runTask();
  456                  }  catch   (XMPPException e) {
  457                      Log.e(LOGTAG, "LoginTask.run()... xmpp error" );
  458                      Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: "
 459                              +  e.getMessage());
  460                      String INVALID_CREDENTIALS_ERROR_CODE = "401" ;
  461                      String errorMessage =  e.getMessage();
  462                       if  (errorMessage !=  null 
 463                              &&  errorMessage
  464                                       .contains(INVALID_CREDENTIALS_ERROR_CODE)) {
  465                           xmppManager.reregisterAccount();
  466                           return  ;
  467                       }
  468                       xmppManager.startReconnectionThread();
  469  
 470                  }  catch   (Exception e) {
  471                      Log.e(LOGTAG, "LoginTask.run()... other error" );
  472                      Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: "
 473                              +  e.getMessage());
  474                       xmppManager.startReconnectionThread();
  475                   }
  476                   //  添加 
 477                   xmppManager.runTask();
  478              }  else   {
  479                  Log.i(LOGTAG, "Logged in already" );
  480                   xmppManager.runTask();
  481               }
  482  
 483           }
  484       }
  485  
 486  }

新添加代码450-454行和477行

    还有一个问题是:当客户端的用户有不在线的时候,消息应怎么进行推送,是直接忽略呢还是下次登录的时候在进行推送,想qq那样,很显然对已一个具体的实用项目来说是不能忽略的,那么怎么进行消息的离线推送呢,下次告诉大家,因为我现在还没解决,不过快了。和大家说下我的思路吧:在androidpn服务端有一个UserController这个类,源码如下:

View Code

该源码里面有用户是否在线的判断,我们只要将用户的列表取出来,如果用户在线就将消息进行推送,如果有不在线的用户,我们就把该消息放到缓存中(也可以放到数据库中更加保险),当然为了防止用户过长没有登陆系统,导致下次登录时出现过多托送过来的消息,我们还可以在服务端进行设置时间,比如服务端只缓存近N天的消息,利用

   session.getCreationDate();
  session.getLastActiveDate(); 

这两句代码应该可以完成,本人没尝试过,还不知道。效果如如下:

 

 

绿色通道: 好文要顶 关注我 收藏该文 与我联系  

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于关于将XMPP server部署到Tomcat上的一些问题的详细内容...

  阅读:40次