IM即時(shí)通訊研究

          openfire專(zhuān)題研究

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            2 Posts :: 0 Stories :: 12 Comments :: 0 Trackbacks

          常用鏈接

          留言簿(5)

          我參與的團(tuán)隊(duì)

          隨筆檔案

          相冊(cè)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

           

          openfire開(kāi)發(fā)文檔
          版本:Openfire3.5.
          作者:---------- 日期:-----------

           

          一、初始工作····································2

          1、安裝jdk1.5

          2、安裝eclipse,myeclipse

          3、安裝oracle10gXE

          4、安裝openfire3.5.1源代碼

          二、環(huán)境配置····································

          1、配置java環(huán)境

          2、配置openfire運(yùn)行環(huán)境

          三、代碼研究····································

          四、功能擴(kuò)展····································

          五、與客戶(hù)端一起調(diào)試··························


          第一章:初始工作

          1.1安裝jdk1.5

          方法1:放在F盤(pán)的安裝程序的java開(kāi)發(fā)工具文件夾里

              方法2:可從www.sun.com.cn下載jdk1.5.

          1.2安裝eclipse3.3,myeclipse6.0

              放在F盤(pán)的安裝程序的java開(kāi)發(fā)工具文件夾里

          1.3安裝oracle10gXE

              放在F盤(pán)的安裝程序的java開(kāi)發(fā)工具文件夾里

          1.4安裝openfire3.5.1源代碼

              源代碼的下載

          方法1:放在F盤(pán)的openfire文件夾里

          方法2:可從openfire的官方網(wǎng)站下載,網(wǎng)址在IE的收藏夾里

          ②源代碼的安裝

          將下載好的openfire源代碼解壓出來(lái),復(fù)制到eclipseworkspace里,打開(kāi)eclipse,點(diǎn)新建java工程,在Contents里選擇第二個(gè),即Create project from existing source, Directory選項(xiàng)里點(diǎn)右邊的Browse按鈕,選擇eclipseworkspace里的openfire文件夾(這個(gè)文件夾的名字應(yīng)該叫:openfire_src),點(diǎn)確定。再填入Project name,工程名字一定要和eclipseworkspace里的openfire源代碼的文件夾名字相同,如下圖所示:

          點(diǎn)擊完成,即成功導(dǎo)入openfire源代碼到eclipse中。如下圖所示:

          右擊工程,點(diǎn)屬性->Java Build Path ->Libraries加入所對(duì)應(yīng)的測(cè)試jar包,叫test什么什么的,放在E盤(pán)里。點(diǎn)擊完成,即可將錯(cuò)誤消除。

          第二章:環(huán)境配置

          2.1、配置java環(huán)境

              我的電腦點(diǎn)右鍵,選擇“屬性”。

          選擇“高級(jí)”標(biāo)簽。

          進(jìn)入環(huán)境變量設(shè)置:

          分別設(shè)置如下三個(gè)環(huán)境變量:
          PATH=C:"jdk1.6.0"bin
          CLASSPATH=.;%JAVA_HOME%"lib"tools.jar;%JAVA_HOME%"lib"dt.jar(注意,CLASSPATH最前面是有個(gè)“.”的,表示當(dāng)前目錄)
          JAVA_HOME=C:"jdk1.6.0

          設(shè)置完成之后,我們來(lái)測(cè)試一下。開(kāi)始-》運(yùn)行,輸入“CMD”,回車(chē)。

          在打開(kāi)的DOS命令窗口中輸入“java -version”,回車(chē)。

          如果能像上圖那樣顯示JDK的版本,說(shuō)明“PATH”變量設(shè)置沒(méi)有問(wèn)題,如果有問(wèn)題,檢查PATH變量設(shè)置,輸入“echo %PATH%”。

          看其中是否存在“C:"jdk1.6.0"bin”。如果不存在則返回到環(huán)境變量設(shè)置中檢查。

          接下來(lái)我們編寫(xiě)一個(gè)簡(jiǎn)單的Java程序測(cè)試CLASSPATH是否設(shè)置正確。

          打開(kāi)記事本,輸入下面的內(nèi)容,保存至C:"java目錄下,文件名為HelloWorld.java。(注意大小寫(xiě))

          class HelloWorld{
          public static void main(String[] arg){
          System.out.println("HelloWorld");
          }
          }

          在打開(kāi)的DOS命令窗口,進(jìn)入C:"java,輸入“java HelloWorld.java”,回車(chē)。

          這時(shí)在C:"java目錄下多了一個(gè)“HelloWorld.class”的文件。

          在打開(kāi)DOS命令窗口,輸入“java HelloWorld”,回車(chē)。

          如果程序沒(méi)錯(cuò),那么將輸出“HelloWorld”。

          恭喜,你的Java環(huán)境配置成功了。

          2.2、配置openfire運(yùn)行環(huán)境

              點(diǎn)擊運(yùn)行按鈕旁邊的小的黑色三角,點(diǎn)擊Open Run Dialog…

          出現(xiàn)如下窗口,雙擊Java Application,Name框里的名字改成:openfire_src3.5.1,點(diǎn)擊Main class右邊的Search按鈕,

           

           

          出現(xiàn)如下窗口:

          在第一個(gè)文本框里輸入server,在第二個(gè)框里選擇ServerStarter-org.jivesoftware.openfire.starter,點(diǎn)OK

           

          點(diǎn)擊eclipse菜單Window->Show View->Ant,如圖:

           

          ant窗口里右擊選擇Add Buildfiles…,如下圖所示:

           

          出現(xiàn)如下窗口:選擇:openfire_src->build->build.xml,點(diǎn)擊OK按鈕。

           

          雙擊在ant窗口里生成的菜單,即開(kāi)始部署項(xiàng)目。

           

          察看console里顯示的信息:如果顯示BUILD SUCCESSFUL就表示項(xiàng)目部署成功。如圖:

           

           

          第三章:代碼研究

          Openfiresocket網(wǎng)絡(luò)連接包括:

          <!--[if !supportLists]-->1.       <!--[endif]-->服務(wù)器和服務(wù)器之間的連接(監(jiān)聽(tīng)在端口5269

          <!--[if !supportLists]-->2.       <!--[endif]-->外部組件和服務(wù)器之間的連接(監(jiān)聽(tīng)在端口5275

          <!--[if !supportLists]-->3.       <!--[endif]-->多元(complex)連接(監(jiān)聽(tīng)在端口5269

          <!--[if !supportLists]-->4.       <!--[endif]-->客戶(hù)端和服務(wù)器的連接(監(jiān)聽(tīng)在端口5222

          <!--[if !supportLists]-->5.       <!--[endif]-->和客戶(hù)端通過(guò)TLS/SSL3.0和服務(wù)器的連接。(監(jiān)聽(tīng)在端口5223

          這些連接都是通過(guò)ConnectionManager接口實(shí)現(xiàn)管理的,程序中對(duì)ConnectionManager接口的實(shí)現(xiàn)類(lèi)是ConnectionManagerImpl,它是作為一個(gè)模塊(Module)類(lèi)加載到服務(wù)器中的。

          下面分析的是客戶(hù)端和服務(wù)器的連接。

           

          ConnectionManagerImpl中是通過(guò)調(diào)用startClientListeners方法來(lái)初始化和開(kāi)始端口監(jiān)聽(tīng)的。

          Mina框架<!--[endif]-->startClientListeners方法使用的是ApacheMina框架來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)連接的,Mina框架的模式如下:

          IoFilter

                 IoFilterMINA的功能擴(kuò)展提供了接口。它攔截所有的IO事件進(jìn)行事件的預(yù)處理和后處理。它與Servlet中的filter機(jī)制十分相似。多個(gè)IoFilter存放在IoFilterChain

                 IoFilter能夠?qū)崿F(xiàn)以下功能:

                        數(shù)據(jù)轉(zhuǎn)換

                        事件日志

                        性能檢測(cè)

                 Openfire中主要用filter這種機(jī)制來(lái)進(jìn)行數(shù)據(jù)轉(zhuǎn)換。

          Protocol Codec Factory

                 Protocol Codec Factory提供了方便的Protocol支持,通過(guò)它的EncoderDecoder,可以方便的擴(kuò)展并支持各種基于Socket的網(wǎng)絡(luò)協(xié)議,比如HTTP服務(wù)器、FTP服務(wù)器、Telnet服務(wù)器等等。

                 要實(shí)現(xiàn)自己的編碼/解碼器(codec)只需要實(shí)現(xiàn)interface: ProtocolCodecFactory即可,在Openfire中實(shí)現(xiàn)ProtocolCodecFactory的類(lèi)為XMPPCodecFactory

          IoHandler:

              MINA中,所有的業(yè)務(wù)邏輯都有實(shí)現(xiàn)了IoHandlerclass完成    ,當(dāng)事件發(fā)生時(shí),將觸發(fā)IoHandler中的方法:

                     sessionCreated

          sessionOpened

          sessionClosed

          sessionIdle

          exceptionCaught

          messageReceived

          messageSent

                 Openfire中客戶(hù)端和服務(wù)器連接的IoHandler實(shí)現(xiàn)類(lèi)是ClientConnectionHandler,它是從ConnectionHandler中繼承來(lái)的。

          startClientListeners方法首先為Mian框架設(shè)置線(xiàn)程池,再將一個(gè)由XMPPCodecFactory作為Protocol Codec FactoryFilter放入到FilterChain中,然后綁定到端口5222,并將ClientConnectionHandler作為IoHandler對(duì)數(shù)據(jù)進(jìn)行處理。完成這些步驟后Openfire就在5222等待客戶(hù)端的連接。

          客戶(hù)端連接的處理過(guò)程:

           

          當(dāng)有客戶(hù)端進(jìn)行連接時(shí)根據(jù)Mina框架的模式首先調(diào)用的是sessionOpened方法。

                 sessionOpened首先為此新連接構(gòu)造了一個(gè)parserXMLLightWeightParser),這個(gè)parser是專(zhuān)門(mén)給XMPPDecoder(是XMPPCodecFactory的解碼器類(lèi))使用的,再創(chuàng)建一個(gè)OpenfireConnection類(lèi)實(shí)例connection和一個(gè)StanzaHandler的實(shí)例。最后將以上的parser, connectionStanzaHandler的實(shí)例存放在Minasession中,以便以后使用。

                 當(dāng)有數(shù)據(jù)發(fā)送過(guò)來(lái)時(shí),Mina框架會(huì)調(diào)用messageReceived方法

                 messageReceived首先從Minasession中得到在sessionOpened方法中創(chuàng)建的StanzaHandler實(shí)例handler,然后從parsers中得到一個(gè)parser(如果parsers中沒(méi)有可以創(chuàng)建一個(gè)新的實(shí)例)(注意這個(gè)parser和在sessionOpened方法中創(chuàng)建的parser不同,這個(gè)parser是用來(lái)處理Stanza的,而在sessionOpened方法中創(chuàng)建的parser是在filter中用來(lái)解碼的,一句話(huà)說(shuō)就是在sessionOpened方法中創(chuàng)建的parser是更低一層的parser)。最后將xml數(shù)據(jù)包交給StanzaHander的實(shí)例hander進(jìn)行處理。

                 StanzaHander的實(shí)例hander處理xml數(shù)據(jù)包的過(guò)程

                 StanzaHander首先判斷xml數(shù)據(jù)包的類(lèi)型,.如果數(shù)據(jù)包以“<stream:stream”打頭那么說(shuō)明客戶(hù)端剛剛連接,需要初始化通信(符合XMPP協(xié)議)Openfire首先為此客戶(hù)端建立一個(gè)與客戶(hù)端JID相關(guān)的ClientSession,而后與客戶(hù)端交互協(xié)商例如是否使用SSL,是否使用壓縮等問(wèn)題。當(dāng)協(xié)商完成之后進(jìn)入正常通信階段,則可以將xml數(shù)據(jù)包交給這個(gè)用戶(hù)的ClientSession進(jìn)行派送(deliever),經(jīng)過(guò)派送數(shù)據(jù)包可以發(fā)送給PacketRouteImpl模塊進(jìn)行處理。

           

           

           

           

           

           

           

           

           

           

           

           

           

           

          第四章:功能擴(kuò)展

          4.1修改源代碼

              用戶(hù)的創(chuàng)建。由于源代碼中用戶(hù)信息不能滿(mǎn)足要求,需要擴(kuò)展。服務(wù)器端創(chuàng)建用戶(hù)比較簡(jiǎn)單,主要是客戶(hù)端的創(chuàng)建比較復(fù)雜,主要有4個(gè)步驟,客戶(hù)端發(fā)送創(chuàng)建用戶(hù)的請(qǐng)求(get請(qǐng)求),請(qǐng)求創(chuàng)建的用戶(hù)字段,服務(wù)器端接收到之后進(jìn)行過(guò)濾,然后返回信息(result),信息中只包含合法的用戶(hù)屬性,客戶(hù)端收到之后,再將合法的用戶(hù)字段發(fā)送給服務(wù)器(set請(qǐng)求),服務(wù)器再根據(jù)收到的用戶(hù)字段創(chuàng)建用戶(hù),即寫(xiě)入數(shù)據(jù)庫(kù)。

          用戶(hù)的查詢(xún)。過(guò)程類(lèi)似上面用戶(hù)的創(chuàng)建。

          4.2插件開(kāi)發(fā)

          Openfire 服務(wù)器端是支持插件開(kāi)發(fā)的,開(kāi)發(fā)過(guò)程可能會(huì)涉及到數(shù)據(jù)庫(kù)的操作,本篇文章專(zhuān)注于Openfire 插件的部分,對(duì)服務(wù)器端涉及到數(shù)據(jù)庫(kù)的開(kāi)發(fā)只做簡(jiǎn)單介紹。

          Openfire
          是一個(gè)用Java 實(shí)現(xiàn)的XMPP 服務(wù)器,客戶(hù)端可以通過(guò)IQ 的方式與其進(jìn)行通信(其實(shí)就是XML),客戶(hù)端和服務(wù)器之間的通信是依靠底層Smack 庫(kù)提供的各種功能來(lái)完成的。其實(shí)利用插件方式來(lái)擴(kuò)展Openfire 服務(wù)器端主要有兩種擴(kuò)展方式,一種是對(duì)服務(wù)器控制臺(tái)頁(yè)面進(jìn)行擴(kuò)展(不是本文的主要內(nèi)容),其實(shí)就是遵循Openfire 頁(yè)面的布局方式,進(jìn)行相應(yīng)的頁(yè)面擴(kuò)展和功能擴(kuò)展;另一種是對(duì)通信功能進(jìn)行擴(kuò)展。本文主要針對(duì)后者進(jìn)行具體的描述

          本篇文章的結(jié)構(gòu)如下:

          1
          、創(chuàng)建plugin.xml(這是整個(gè)插件最關(guān)鍵的文檔)
          2
          、創(chuàng)建服務(wù)器插件實(shí)例(實(shí)現(xiàn)Plugin 接口的一個(gè)類(lèi)還有一批IQHandler
          3
          、打包插件(Openfire 插件也有自己的打包方式)和部署插件

          好滴,實(shí)刀實(shí)槍的來(lái)動(dòng)手做吧

          1
          、創(chuàng)建plugin.xml

          初次開(kāi)發(fā)Openfire Spark 插件的時(shí)候,很容易把二者搞混,千萬(wàn)記得,這里是Openfire plugin.xml 不是第二篇文章說(shuō)的那個(gè)啦!

          <?xml version="1.0" encoding="UTF-8"?>
          <plugin>
              <!-- Main plugin class 
          這里是最重要滴-->
              <class>com.im.server.plugin.GroupTreePlugin</class>

              <!-- Plugin meta-data -->
              <name>GroupTreePlugin</name>
              <description>This is the group plugin.</description>
              <author>Phoenix</author>

              <version>1.0</version>
              <date>14/03/2008</date>
              <url>http://localhost:9001/openfire/plugins.jsp</url>
              <minServerVersion>3.4.1</minServerVersion>
              <licenseType>gpl</licenseType>

              <!-- Admin console entries -->
              <adminconsole>
                  <!-- More on this below -->
              </adminconsole>
          </plugin>

          最重要的那一行我已經(jīng)標(biāo)記出來(lái)啦,就是你這個(gè)插件的初始化和垃圾清理類(lèi),例子中是在com.im.server.plugin 包中的GroupTreePlugin 類(lèi),下文會(huì)對(duì)這個(gè)類(lèi)進(jìn)行詳細(xì)描述。其余的都是描述信息,只要你提供了正確的描述信息,一般都不會(huì)出錯(cuò)。建議初次開(kāi)發(fā)者,在寫(xiě)完plugin.xml 文件后,寫(xiě)一個(gè)簡(jiǎn)單的Plugin 實(shí)例,并打印出一些信息,如果重新啟動(dòng)Openfire 信息成功顯示,恭喜你,你已經(jīng)邁出一大步了!

          2
          、實(shí)現(xiàn)Plugin 類(lèi)和IQHandler

          Plugin
          類(lèi)主要起到的作用是初始化和釋放資源,在初始化的過(guò)程中,最重要的的注冊(cè)一批IQHandlerIQHander 的作用有點(diǎn)類(lèi)似于Spark 中的IQProvider,其實(shí)就是解析XML 文件之后,生成一些有用的實(shí)例,以供處理。下面分別給出一個(gè)Plugin 類(lèi)的實(shí)例和IQProvider 的實(shí)例

          GroupTreePlugin
          類(lèi)

          /**
           *
          服務(wù)器端插件類(lèi)
           *
           * @author Phoenix
           *
           * Mar 14, 2008 11:03:11 AM
           *
           * version 0.1
           */
          public class GroupTreePlugin implements Plugin
          {
              private XMPPServer server;

              /*
               * (non-Javadoc)
               *
               * @see org.jivesoftware.openfire.container.Plugin#destroyPlugin()
               */
              public void destroyPlugin()
              {

              }

              /*
               * (non-Javadoc)
               *
               * @see org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware.openfire.container.PluginManager,
               *      java.io.File)
               */
              public void initializePlugin(PluginManager manager, File pluginDirectory)
              {
                  PluginLog.trace("
          注冊(cè)群組樹(shù)IQ處理器");
                  server = XMPPServer.getInstance();
                 
                  server.getIQRouter().addHandler(new GroupTreeIQHander()); //1
                  server.getIQRouter().addHandler(new UserInfoIQHandler());
                  server.getIQRouter().addHandler(new DelUserIQHandler());
                  server.getIQRouter().addHandler(new CreateUserIQHandler());
                  server.getIQRouter().addHandler(new AddGroupUserIQHandler());
                  server.getIQRouter().addHandler(new SetRoleIQHandler());

              }

          }

          上例所示,在初始化中先找到IQRouter,然后通過(guò)IQRouter 注冊(cè)一批IQHandler,這些IQHander 會(huì)自動(dòng)監(jiān)聽(tīng)相應(yīng)命名空間的IQ,然后進(jìn)行處理;由于這個(gè)Plugin 不需要做資源釋放的工作,所以在destroyPlugin() 方法中沒(méi)有任何內(nèi)容。具體的IQHander 類(lèi)如下

          GroupTreeIQHander

          /**
           *
          處理客戶(hù)端發(fā)來(lái)的IQ,并回送結(jié)果IQ
           *
           * @author Phoenix
           *
           * Mar 14, 2008 4:55:33 PM
           *
           * version 0.1
           */
          public class GroupTreeIQHander extends IQHandler
          {

              private static final String MODULE_NAME = "group tree handler";

              private static final String NAME_SPACE = "com:im:group";

              private IQHandlerInfo info;

              public GroupTreeIQHander()
              {
                  super(MODULE_NAME);
                  info = new IQHandlerInfo("gruops", NAME_SPACE);
              }

              /*
               * (non-Javadoc)
               *
               * @see org.jivesoftware.openfire.handler.IQHandler#getInfo()
               */
              @Override
              public IQHandlerInfo getInfo()
              {
                  return info;
              }

              /*
               * (non-Javadoc)
               *
               * @see org.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)
               */
              @Override
              public IQ handleIQ(IQ packet) throws UnauthorizedException
              {
                  IQ reply = IQ.createResultIQ(packet);
                  Element groups = packet.getChildElement();//1
                 
                  if (!IQ.Type.get.equals(packet.getType()))
                  {
                      System.out.println("
          非法的請(qǐng)求類(lèi)型");
                      reply.setChildElement(groups.createCopy());
                      reply.setError(PacketError.Condition.bad_request);
                      return reply;
                  }
                 
                  String userName = StringUtils.substringBefore(packet.getFrom().toString(),"@");

                  GroupManager.getInstance().initElement(groups,userName);
                 
                  reply.setChildElement(groups.createCopy());//2

                  System.out.println("
          返回的最終XML" + reply.toXML());

                  return reply;
              }

          }

          可以看到主要有兩個(gè)方法,一個(gè)是getInfo() 這個(gè)方法的目的是提供要解析的命名空間,在本例中,這個(gè)IQHandler 對(duì)每個(gè)命名空間為"com:im:group" 的實(shí)例進(jìn)行處理;還有一個(gè)最重要的方法:handleIQ() 該方法對(duì)包含指定命名空間的XML 進(jìn)行解析,然后返回一個(gè)解析好的IQ。其實(shí)我認(rèn)為,這個(gè)IQHandler IQ 的關(guān)系就是Controller Model 的關(guān)系(如果你了解MVC 的話(huà),那么你一定知道我再說(shuō)什么),只不過(guò)這里并沒(méi)有指定什么View,你完全可以把IQ 當(dāng)成Model 類(lèi)進(jìn)行理解。在這里,我用了GroupManager 進(jìn)行了XML 的處理,因?yàn)槲曳祷氐?/span>IQ 內(nèi)容中要從數(shù)據(jù)庫(kù)讀取所有群組信息,所以轉(zhuǎn)交給GroupManager 進(jìn)行處理,你完全可以在這個(gè)方法中進(jìn)行具體的XML 處理,在這里,解析和創(chuàng)建新的XML 主要用到的是JDOM(如果你對(duì)Java 解析XML 有所了解,那真的太好了!)。程序//1 處主要是獲取創(chuàng)建返回的IQ,并獲取原來(lái)IQ 的子元素(用于創(chuàng)建我們返回的IQ);程序//2 處很關(guān)鍵,如果你不調(diào)用createCopy 方法,程序會(huì)出錯(cuò)(程序會(huì)死鎖還是什么,忘記咧,不好以西)。

          這就是程序的主體部分,我在這里有一個(gè)建議,能不用Openfire 原始的程序函數(shù),就不要用它們。我的提取數(shù)據(jù)庫(kù)方式都是自己寫(xiě)的Bean,這樣有利于你自己對(duì)程序的掌控,其實(shí)更有利于快速開(kāi)發(fā)(這世道不是啥都講究敏捷么,哇哈哈)

          3
          、打包插件

          打包依然遵循二次打包的原則(如果你不了解啥叫要二次打包,請(qǐng)看上一篇)
          這是我的ant 文件,由于Eclipse 幫我做了build 等很多工作,實(shí)際我的ant 工作就是在打包,并放入插件目錄下的plugin 文件夾下

          <?xml version="1.0" encoding="UTF-8"?>
          <project name="IM" default="release" basedir=".">

              <property name="openfire.path"
                  value="E:/workspace/europa/openfire_src/target/openfire" />
              <property name="classes.dir" value="classes" />
              <property name="lib.dir" value="lib" />

              <target name="jar">
                  <jar jarfile="${lib.dir}/grouptreeplugin.jar" basedir="${classes.dir}" >
                      <fileset dir=".">
                          <include name="*.jar"/>
                      </fileset>
                  </jar>
                  <jar jarfile="${openfire.path}/plugins/groupTreePlugin.jar">
                      <fileset dir=".">
                          <include name="lib/*.jar" />
                          <include name="plugin.xml" />
                          <include name="logo_small.gif" />
                          <include name="logo_large.gif" />
                          <include name="readme.html" />
                          <include name="changelog.html" />
                          <include name="build.xml" />
                      </fileset>
                  </jar>

              </target>

              <target name="release" depends="jar">
              </target>

          </project>

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

          第五章:與客戶(hù)端一起調(diào)試

          5.1debug模式啟動(dòng)服務(wù)器,根據(jù)客戶(hù)端的需要在相應(yīng)位置設(shè)置端點(diǎn),分析數(shù)據(jù)。

          posted on 2009-02-11 10:07 gissing 閱讀(46718) 評(píng)論(7)  編輯  收藏

          Feedback

          # re: openfire開(kāi)發(fā)指南[未登錄](méi) 2009-05-25 23:16 alex
          你很強(qiáng),,我很崇拜你  回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南 2009-06-29 21:36 錢(qián)奕
          研究小組:
          您們好!
          我現(xiàn)在安裝配置openfire時(shí)出現(xiàn)一些障礙,想請(qǐng)高手支招。

          我是一個(gè)完全不懂程序的人,呵呵,openfire+spark程序在本地電腦上調(diào)試一切正常,可是不知道為什么遠(yuǎn)程服務(wù)器的時(shí)候鏈接數(shù)據(jù)庫(kù)總是失敗。
          提示:The Openfire database schema does not appear to be installed. Follow the installation guide to fix this error.
          我用的是MSSQL,localhost/數(shù)據(jù)庫(kù)名稱(chēng),用戶(hù)名和密碼都正確的,但總是過(guò)不去這一關(guān),不知是何原因。急急急…………

          我的QQ:70734260(輸贏(yíng)) 幫幫忙,呵呵  回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南[未登錄](méi) 2009-09-03 14:02 knight
          你真的很強(qiáng) 我崇拜!我的qq是24568468希望以后能多交流  回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南 2009-09-08 17:07 yzheng
          很不錯(cuò),我也在研究openfire,想將其優(yōu)化一下,希望你能寫(xiě)一些關(guān)于優(yōu)化openfire的文章,給我一些指點(diǎn),謝謝了!
          郵箱:zhengyu.willian@gmail.com
          QQ:119079436
          我會(huì)一直關(guān)注的!  回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南[未登錄](méi) 2009-09-14 09:28 gissing
          我們小組得研究群號(hào)碼是:28588322,歡迎進(jìn)群討論
            回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南[未登錄](méi) 2011-10-21 17:52 vincent
          群滿(mǎn)了。
          請(qǐng)問(wèn)openfire的網(wǎng)頁(yè)是怎么實(shí)現(xiàn)的,能不能把基本原理講一下?  回復(fù)  更多評(píng)論
            

          # re: openfire開(kāi)發(fā)指南 2014-07-31 17:54 ACE
          mark  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 定边县| 嘉义县| 镇坪县| 汪清县| 齐齐哈尔市| 乾安县| 永登县| 新闻| 沂水县| 东光县| 和龙市| 永新县| 阳信县| 新津县| 荥经县| 鹤峰县| 马关县| 乐业县| 沙田区| 仪陇县| 武陟县| 长岛县| 寿宁县| 视频| 且末县| 河源市| 武义县| 江孜县| 阳江市| 台南县| 南城县| 申扎县| 大余县| 城口县| 北辰区| 禹城市| 广东省| 昭觉县| 高台县| 离岛区| 丹东市|