將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:臨時的;
有什麼問題可以聯絡我,共同交流,共同進步。