1. 程式人生 > >將red5專案部署到tomcat下,並且red5專案嵌入到J2EE專案中

將red5專案部署到tomcat下,並且red5專案嵌入到J2EE專案中

接觸Flex和java通訊有一段時間了,但是在這個過程中有一點不爽,用Flex做客戶端的一個缺點是當用戶點選了瀏覽器右上角的 關閉 按鈕時,在伺服器端是檢測不到的,所以就產生了無法實時統計客戶端線上數量的問題,雖然有人說可以在伺服器端使用 HttpSessionListener進行監聽,但是也只能是在flex連線客戶端的時候建立Session,當flex斷開的時候不會立刻去執行sessionDestroyed()方法,而是在超過了Session設定的時間後才會執行sessionDestroyed()方法,預設的是30分鐘(可以修改),這樣就無法準確統計客戶端線上數量。為此找到了red5,其中的appConnect()和appDisconnect()可以準確捕捉到Flex的連線和關閉。現在就開始步驟:

首先是選擇red5的版本,目前出到了1.0RC,但是本人覺得0.8的版本比較穩定,下載地址:http://code.google.com/p/red5/

從網上下載兩個東西:red5-war-0.8.0.zip 和 setup-Red5-0.8.0.exe,red5-war-0.8.0.zip解壓之後有兩個檔案ROOT.war和Red5 War.pdf其中Red5 War.pdf是幫助文件,裡面全是英文,看不懂,不過已經有人翻譯過了,雖然不是太準確,還是能大概看懂意思。

1:安裝 setup-Red5-0.8.0.exe(C:\Program Files\Red5);

2:刪除你tomcat重conf裡面的catalina檔案件,刪除work資料夾,刪除webapps\ROOT資料夾(因為這裡的兩個資料夾都是tomcat的,現在你要整合red5,所以刪掉,當你配置完,所有後重啟tomcat時這兩個檔案會重新的生成);

3:找到你的tomcat的webapps,然後將ROOTwar包放在webapps下,(將webapps下的root資料夾命名為root_old,因為一會重啟tomcat時會解壓ROOTwar,重新生成新 的root資料夾);

4:重啟tomcat;

5:開啟tomcat下webapps\ROOT\WEB-INF\classes,裡面的root-web.xml.將裡面的所有埠都換成8080,PS:現在看來該這裡東西對我們以後寫的專案也沒影響,該它只是為了訪問red5主頁或者它裡面的例子。

6.再重啟tomcat,現在在瀏覽器中輸入:http://localhost:8080  如果出現red5的主頁,而不 是以往 我們熟知的tomcat主頁就行了。

現在下面的才是真正我們需要的東西:

新建java web專案,命名為red5Server:

7:我們來到0.:8windows安裝版的安裝路徑下找到red5.jar 把它拷工程的lib下,同時你也去tomcat的root資料夾下的classes裡面 的lib的所以jar拷的你工程的lib下         同時你也去tomcat下找到Root資料夾,裡面的web-inf下的classes裡面的配置檔案,將所有檔案拷到你工程src下,將tomcat6\webapps\ROOT\WEB-INF下的web.xml  和log4j的配置檔案拷到你的專案的web-inf下,覆蓋以前的檔案。到這裡,你的專案基本快要完成了,接下來就是修改裡面的 配置。

樣子如圖:


現在你就要新建一個包了:

前面那兩 個包你們不用管,主要是red5.example.red5Server這個包,裡面建個類:

import org.red5.server.adapter.ApplicationAdapter;
import java.util.ArrayList;  
import java.util.Iterator;  
import java.util.List;  
 
import org.red5.server.api.IConnection;  
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;
import org.red5.server.api.service.IServiceCapableConnection;


public class Application extends ApplicationAdapter { 
    private String userName;  
          
        //客戶端呼叫的方法  
        public String callFromClient(String userName) {
       System.out.println("ddd");
            this.userName = userName;  
            callClient();  
            return "Hello:"+userName;  
       }  
          
        //伺服器端呼叫客戶端的方法  
        public void callClient() {  
            IConnection conn=Red5.getConnectionLocal();  
            if (conn instanceof IServiceCapableConnection) {  
                IServiceCapableConnection sc = (IServiceCapableConnection) conn;  
                sc.invoke("callFromServer", new Object[]{"hi,"+userName+" this message from server"});  
           }  
        }  
}


首先要改的就是web.xml,容器從這裡找到你的服務,

將web.xml中的

<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/</param-value>
</context-param>

改成

<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/red5Server</param-value>
</context-param>

然後在src建立以個red5Server.xml檔案,類容為:

<?xml version="1.0" encoding="UTF-8"?> 
< !DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> 
< beans> 
 
    <bean id="web.context.red5Server" class="org.red5.server.Context"> 
        <property name="scopeResolver" ref="red5.scopeResolver" /> 
        <property name="clientRegistry" ref="global.clientRegistry" /> 
        <property name="serviceInvoker" ref="global.serviceInvoker" /> 
        <property name="mappingStrategy" ref="global.mappingStrategy" /> 
    </bean> 
 
   <bean id="web.scope" class="org.red5.server.WebScope" 
        init-method="register"> 
        <property name="server" ref="red5.server" /> 
        <property name="parent" ref="global.scope" /> 
         <property name="context" ref="web.context.red5Server" /> 
        <property name="handler" ref="web.handler.red5Server" /> 
        <property name="contextPath" value="/red5Server" /> 
       <property name="virtualHosts" 
            value="*,localhost, localhost:8080, 127.0.0.1:8080" /> 
    </bean> 
 
    <bean id="web.handler.red5Server" 
       class="red5.example.red5server.Application" /> 
 
< /beans> 

想必你們也能明白這裡的意思了。

然後這裡就非常的重要了,打re5-core.xml,找到裡面的:

<bean id="rtmpTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop">
<property name="ioHandler" ref="rtmpMinaIoHandler" />
<property name="address" value="10.30.6.221" />
<property name="port" value="8080" />
<property name="receiveBufferSize" value="65536" />
<property name="sendBufferSize" value="271360" />
<property name="eventThreadsCore" value="4" />
<property name="eventThreadsMax" value="8" />
<property name="eventThreadsQueue" value="-1 " />
<property name="eventThreadsKeepalive" value="60" />
</bean>

首先要改的就是web.xml,容器從這裡找到你的服務,

將web.xml中的

<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/</param-value>
</context-param>

改成

<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/red5Server</param-value>
</context-param>

然後在src建立以個red5Server-web.xml檔案,內容為:

<?xml version="1.0" encoding="UTF-8"?> 
< !DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> 
< beans> 
 
    <bean id="web.context.red5Server" class="org.red5.server.Context"> 
        <property name="scopeResolver" ref="red5.scopeResolver" /> 
        <property name="clientRegistry" ref="global.clientRegistry" /> 
        <property name="serviceInvoker" ref="global.serviceInvoker" /> 
        <property name="mappingStrategy" ref="global.mappingStrategy" /> 
    </bean> 
 
   <bean id="web.scope.red5Server" class="org.red5.server.WebScope" 
        init-method="register"> 
        <property name="server" ref="red5.server" /> 
        <property name="parent" ref="global.scope" /> 
         <property name="context" ref="web.context.red5Server" /> 
        <property name="handler" ref="web.handler.red5Server" /> 
        <property name="contextPath" value="/red5Server" /> 
       <property name="virtualHosts" 
            value="*,localhost, localhost:8080, 127.0.0.1:8080" /> 
    </bean> 
 
    <bean id="web.handler.red5Server" 
       class="red5.example.red5server.Application" /> 
 
< /beans> 

然後這裡就非常的重要了,打re5-core.xml,找到裡面的:

<!-- RTMP Mina Transport -->
 <bean id="rtmpTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop">
  <property name="ioHandler" ref="rtmpMinaIoHandler" />
        <property name="connectors">
            <list>
                <bean class="java.net.InetSocketAddress">
                    <constructor-arg index="0" type="java.lang.String" value="192.168.1.192" /> 
                    <constructor-arg index="1" type="int" value="5081" /> 
                </bean>
                <!-- You can now add additional ports and ip addresses
                <bean class="java.net.InetSocketAddress">
                    <constructor-arg index="0" type="java.lang.String" value="0.0.0.0" /> 
                    <constructor-arg index="1" type="int" value="1936" /> 
                </bean>
                 -->
            </list>
        </property>  
  <property name="receiveBufferSize" value="65536" />
  <property name="sendBufferSize" value="271360" />
  <property name="eventThreadsCore" value="4" />
  <property name="eventThreadsMax" value="8" />
  <property name="eventThreadsQueue" value="-1 " />
  <property name="eventThreadsKeepalive" value="60" />
  <!-- This is the interval at which the sessions are polled for stats. If mina monitoring is not
    enabled, polling will not occur. -->
  <property name="jmxPollInterval" value="1000" />
  <property name="tcpNoDelay" value="true" />
 </bean>

將其中的

<constructor-arg index="0" type="java.lang.String" value="192.168.1.192" />  
<constructor-arg index="1" type="int" value="5081" />  修改為自己所要監聽的伺服器的IP地址和埠號,(一會會說為什麼修改成5081);

下面寫前臺吧,我用Flex

<?xml version="1.0" encoding="utf-8"?> 
< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"> 
 
     <mx:Script> 
        <![CDATA[ 
            import flash.net.*; 
             import flash.events.*;    
             import flash.utils.*;    
            import mx.controls.*;  
            private var nc:NetConnection; 
             
            public function connServer():void { 
                 nc = new NetConnection();                   
                 nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);    
                 nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, netSecurityError);    
                 nc.connect(txtServerURL.text,txtUserName.text);    
             } 


           
            public function init():void { 
//            Alert.show("頁面初始化完成!")
                  nc = new NetConnection();                   
                 nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);    
                 nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, netSecurityError);    
                 nc.connect("rtmp://192.168.1.192:5081/red5Server");    
                 nc.client = this;  
                 //Alert.show("連線完成");
             } 
              
             private function netStatus(event:NetStatusEvent):void {    
                var connStatus:String = event.info.code; 
                 Alert.show(connStatus);  
                 if(connStatus == "NetConnection.Connect.Success") {
                     txtResult.text += "登陸成功";  
                     nc.call("callFromClient",new Responder(callServerMethodResult,callServerMethodFault),Math.random().toString()); 
                } 
                 else if(connStatus == "NetConnection.Connect.Rejected") 
                 { 
                     //登入被拒絕 
                     txtResult.text += event.info.application; 
                 } 
                 else if(connStatus == "NetConnection.Connect.Failed") 
                 { 
                     //登入被拒絕 
                     txtResult.text += event.info.application; 
                 }
             }    
             
             private function netSecurityError(event:SecurityErrorEvent):void {    
                 Alert.show("netSecurityError: " + event);    
             } 

           public function callServerMethodResult(re:String):void { 
                Alert.show("客戶端呼叫伺服器端方法成功,返回結果:"+re); 
             } 
             
           public function callServerMethodFault(fo:Object):void { 
               Alert.show("客戶端呼叫伺服器端方法失敗:"+fo.toString()); 
            } 
             
            public function callFromServer(re:Object):void { 
                Alert.show("伺服器端呼叫客戶端方法,傳遞的引數為:"+re.toString()); 
           }




        ]]> 
     </mx:Script> 
      <mx:Label x="10" y="38" text="輸入使用者名稱:"/> 
     <mx:TextInput x="83" y="36" id="txtUserName" width="167"/> 
     <mx:Label x="10" y="10" text="連線的伺服器:"/> 
    <mx:TextInput x="83" y="8" id="txtServerURL" text="rtmp://10.30.6.221:8080/red5Server"/> 
    <mx:Button x="10" y="64" label="連線到red5伺服器" width="240" click="this.connServer()"/> 
    <mx:TextArea x="10" y="94" width="240" height="154" id="txtResult"/> 
      
</mx:Application>
這個專案要對映到你的J2EE專案的目錄下,比如這裡我是對映到red5Server下,輸入路徑為/red5Server/chart
(事實上只要建一個Flex專案貼上上面程式碼,執行就可以了,不一定非要對映到red5Server下);

下面是我學習red5之後測試得到的總結:

總結1:關於重新整理:每次client端進行一次重新整理,則server端就斷開一次連線,然後再進行連線;

總結2:關於跳轉:如果是覆蓋了之前的頁面,則之前的連線斷開,進行新的連線,如果是又打開了一個新的頁面,則原有的連線不斷開;總結:如果是使用NetConnection進行對red5的連線,則連線是面向單個頁面的,頁面消失了,則連線也消失了,重新整理也是如此;

總結3:將red5整合到tomcat中時會遇到一個問題,將red5的監聽埠也設定成8080(tomcat一樣)時,在本機上測試是沒有問題的,但是在其他電腦上登入就不行了,無法登入,其原因可能是他們共同監聽了一個埠,如果異地登入的話,red5對其監聽進行處理,那麼tomcat就失去了作用;剛開始我修改了red5Server-web.xml檔案和root-we.xml檔案中的埠號為5080但是沒有修改red5-core.xml檔案,還是報錯,通過測試,找到了其解決方法:

找到red5-core.xml檔案,找到其中的

<bean id="rtmpTransport"class="org.red5.server.net.rtmp.RTMPMinaTransport"init-method="start" destroy-method="stop">

              <propertyname="ioHandler" ref="rtmpMinaIoHandler" />

       <property name="connectors">

           <list>

                <beanclass="java.net.InetSocketAddress">

                    <constructor-argindex="0" type="java.lang.String"value="192.168.1.192" /> 

<constructor-argindex="1" type="int" value="5081" /> 

                </bean>

                <!-- You can now addadditional ports and ip addresses

                <bean class="java.net.InetSocketAddress">

                    <constructor-argindex="0" type="java.lang.String" value="0.0.0.0"/> 

                    <constructor-argindex="1" type="int" value="1936" /> 

                </bean>

                 -->

           </list>

       </property>          

              <propertyname="receiveBufferSize" value="65536" />

              <propertyname="sendBufferSize" value="271360" />

              <propertyname="eventThreadsCore" value="4" />

              <propertyname="eventThreadsMax" value="8" />

              <propertyname="eventThreadsQueue" value="-1 " />

              <propertyname="eventThreadsKeepalive" value="60" />

              <!--This is the interval at which the sessions are polled for stats. If minamonitoring is not

                            enabled,polling will not occur. -->

              <propertyname="jmxPollInterval" value="1000" />

              <propertyname="tcpNoDelay" value="true" />

       </bean>

注意紅色的部分,將原有的8080埠修改為其他埠,如果本機上還安裝有red5的安裝版但是並未啟動,也不適合將埠號設定為5080。具體原因不詳。於是修改成了5081,在其他電腦上測試也沒有問題了。(疑問:只是修改了red5-core.xml檔案檔案就可以通過測試了,那兩個檔案修改不修改都一樣,是否修改了更好呢?)

總結4:關於伺服器端使用SharedObject的注意事項:

在伺服器端建立SharedObject

this.createSharedObject(scope,"chart", true);//第三個引數true:持久的;false:臨時的;

有什麼問題可以聯絡我,共同交流,共同進步。