-
- cmt的項目背景:
搞java已經3年了,感覺java的應用情境主要還是局限在b/s程式上面,因為用java來做C/S程式不僅比較麻煩,而且運行速度還很慢,與作業系統的介面外觀格格不入。eclipse的swt運行速度比swing快得多,但是蹩腳的線程封裝和繁瑣的控制項調用,讓swt的介面開發工作變得非常的麻煩。
因為工作的原因接觸flex已經快一年了,雖然他的文法跟java比較起來不是那麼的完美,但是每種語言都有它的長處,flex也不例外,用它來做介面開發,不僅開發速度快,介面美觀,運行速度也很快,而且和與其他系統的整合也相當方便,畢竟flex編譯出來的swf可以用flash activeX來播放,可以與任何支援activeX容器的平台整合。
由於上面的原因,有了將flex與java平台整合於一體互相取長補短的想法,實現方便的互相調用,就像調用本地方法一樣。當前基於
web service的flex庫,可以讓flex調用web service,實現對其他平台的調用,但是這種調用只是單向的,服務方不能調用flex,而且作為C/S程式分發和配置也相當繁瑣。
cmt的實現原理:
flex調用java:
將flex的本機物件序列化為對應的XML字串,然後將此字串通過通訊端發送給java。java接收到字串後解析此字串,通過反射機制,將此字串轉換為對應的java對象,最後調用對應的方法。
java調用flex:
與flex調用java類似
基本開發過程:
好了廢話不多說了,讓我們來看看基本的開發步驟吧:)
java方面:
1:開啟eclipse建立一java項目
2:匯入cmt.jar和dom4j.jar兩個需要的庫
flex方面
:
建立一web application 將cmt.swc庫匯入到此項目中
圖一:
圖二:
flex調用java:
1:在java項目中建立test.IvkTest類,作為服務類,具體代碼如下:
package test;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.communicator.server.ChannelFactory;
public class IvkTest {
/**
* flex 會調用此方法,此方法會簡單的返回一字串
* @param input
* @return
*/
public String hello(String input){
System.out.println(input);
return "java的返回";
}
/**
* flex會調用此方法,並傳入flex可以與平台互動的所有資料類型
*
* @param bl
* @param it
* @param uit
* @param num
* @param dt
* @param str
* @param lst
* @param map
* @return 此方法返回一簡單的bean對象,bean對象的屬性包含了java可以與平台進行互動的所有單一資料型別
*/
public TypesTest testFlexToJava(boolean bl, int it, long uit, double num,
Date dt, String str, List lst, Map map) {
return new TypesTest();//返回一個自訂類型對象
}
public static void main(String[] args) {
//只需下面的一句代碼就可以開啟java服務端的資料通道處理站,等待flex用戶端的串連
ChannelFactory.init();
//死迴圈,防止程式的結束
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
稍後flex會調用此類的hello和testFlexToJava方法。
2:在flex項目中建立test包,與java的IvkTest類所在的包對應
3:在該包中建立IvkTest類(此類是java方IvkTest類的代理類,調用此類的方法時,它會去調用java的對應方法完成特定的功能,這種類在真正的項目中很多)
該類的具體代碼如下:
package test
{
import mx.collections.ArrayCollection;
import org.communicator.server.BaseIvkServer;
public class IvkTest extends BaseIvkServer //所有的代理類都繼承自BaseIvkServer類,它封裝了具體的調用細節
{
public static var url:String="127.0.0.1:1236";//java服務端地址,前面是ip後面是連接埠
public static var INSTANCE:IvkTest=new IvkTest();//為了類比單列模式,所以在此建立了該類的靜態欄位
public function IvkTest()
{
}
/**
此方法就是一個簡單的代理方法,此方法被調用時,它會自動的去調用java的test.IvkTest類的hello方法,並按程式將args數組中的
每個元素,做為hello方法的參數傳入。java返回後,作為回呼函數的resFun會被自動調用完成相應的功能。
url為java服務端的網路地址
"hello"為調用的方法名稱
args 為調用java方法時傳入的參數,順序與args數組中的順序一致。
* resFun為調用返回後系統自動調用的方法
*/
public function hello(str:String,resFun:Function):String{
var args:Array=[str];
this.sendRequest(url,"hello",args,resFun);
return null;
}
/**
*與hello方法類型
*/
public function testFlexToJava(bl:Boolean,it:int,uit:uint,num:Number,dt:Date,str:String
,ar:ArrayCollection,map:Object):void{
var args:Array=[bl,it,uit,num,dt,str,ar,map];
this.sendRequest(url,"testFlexToJava",args,function ret(ret:Object):void{
trace(ret);
});
}
}
}
4:在flex項目中建立CmtTest.mxml Application 檔案具體代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:initialize>
<![CDATA[
//通道的id,通過此標識符java服務端可以區分不同的通道。
var channelPort:int=22;
//建立資料通道
var channel:DataChannel=DataChannelFactory.CREATE_CHANNEL("127.0.0.1",1236,channelPort);
//資料通道與java連通後會調用this.onConnect方法
channel.onOpenFun=this.onConnect;
//串連java,開啟資料通道
channel.open();
]]>
</mx:initialize>
<mx:Script>
<![CDATA[
import org.communicator.DataChannel;
import mx.collections.ArrayCollection;
import test.IvkFlex;
import mx.controls.Alert;
import test.IvkTest;
import org.communicator.ChannelUrl;
import org.communicator.DataChannelFactory;
//這裡聲明IvkFlex類型對象的作用是 使flex的反射機制可以成功建立該類型的對象
var ivkFlex:IvkFlex;
//按鈕點擊會調用此方法
function onClick():void{
IvkTest.INSTANCE.hello("hello 我是flex",function ret(res:String):void{
Alert.show(res);
});
}
/**
*請求java的test.IvkTest.testFlexToJava方法測試所有的資料類型
*/
function onConnect():void{
var ar:ArrayCollection=new ArrayCollection(['1','2','3']);
var ar2:ArrayCollection=new ArrayCollection(['1adf','2g','3df']);
IvkTest.INSTANCE.testFlexToJava(false,1,2,34.45,new Date(),"str",ar,{one:ar,sec:ar2});
}
]]>
</mx:Script>
<mx:Button label="ivkTest" click="onClick()"/>
</mx:Application>
串連上java方的資料通道。當按鈕被點擊後,onClick()方法會調用IvkTest類的hello方法,當java返回後,簡單的Alert出java的返回。
java調用flex:
這是最精彩的利用同一個資料通道,可以實現java與flex的互調,使java+flex做C/S程式成為可能。
1:首先在flex的test包下建立服務類型IvkFlex,讓java調用,具體代碼如下:
package test
{
import mx.controls.Alert;
public class IvkFlex
{
public function IvkFlex()
{
}
//java 會調用此方法
public function test(str:String):String{
Alert.show("java調用了我,並傳入了"+str);
return 'flex的返回';
}
}
}
2:在java中建立對應的代理類型(包名與類名稱相同),代碼如下:
package test;
import org.communicator.server.BaseIvkServer;
import org.communicator.server.ChannelFactory;
public class IvkFlex extends BaseIvkServer {
public IvkFlex() {
}
/**
* 此方法會調用資料通道id為22的flex用戶端的test.IvkFlex類中的test方法
* @param info
* @return
*/
public String test(String info){
//傳入的參數
String[] par=new String[]{info};
//通道id要與flex用戶端的通道id一致
int flexClientId=22;
//阻止當前線程,直到flex返回資料
Object ret=this.sendMiddVal(flexClientId, "test", par).getReturn();
//將資料返回
return ret.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
//只需下面的一句代碼就可以開啟java服務端的資料通道處理站,等待flex用戶端的串連
ChannelFactory.init();
//死迴圈,防止程式的結束
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
點擊此處下載開發包
歡迎加入cmt的qq群90636900大家交流