<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆:25 文章:1 評(píng)論:66 引用:0
    BlogJava 首頁 發(fā)新隨筆
    發(fā)新文章 聯(lián)系 聚合管理

    2006年4月7日

    Sorry, I have already moved to JavaEye and Fanfou, please update if you have questions.
    posted @ 2009-05-09 22:13 steeven 閱讀(235) | 評(píng)論 (0)編輯 收藏
     
    最近讓新來的實(shí)習(xí)生寫訂餐機(jī)器人,羽毛球活動(dòng)預(yù)定機(jī)器人,兩個(gè)人寫了幾個(gè)星期,看得我心急火燎。現(xiàn)在的研究生啊。。。。

    自己拿來skype4java看了一下,感覺很好用。里面提供了一個(gè)application機(jī)制,類似socket,又強(qiáng)于socket。為什么說強(qiáng)呢?因?yàn)槭腔趕kype, 穿透防火墻啦。
    windows自帶的遠(yuǎn)程桌面很好用,在速度上,比以前基于位圖傳送的netmeeting/pcanywhere之類的都要強(qiáng)。
    linux下面的遠(yuǎn)程桌面做的比較好的是nx系列。但是這些遠(yuǎn)程桌面的致命問題就是網(wǎng)關(guān)、防火墻問題。
    就是說你要在家訪問公司電腦,基本上要在防火墻上鑿洞,或者借助于vpn,softether之類的東東。

    skype的application利用skype自身的通訊機(jī)制,屏蔽了這些問題,當(dāng)然,你的應(yīng)用也必須依賴skype了。

    java做遠(yuǎn)程桌面要能截屏、控制鼠標(biāo)鍵盤,所幸有java.awt.Robot, 原來這個(gè)東西是為了做自動(dòng)化測(cè)試,剛好。
    剩下就是穿數(shù)據(jù)的問題。屏幕圖片,如果是bmp,比較碩大,即使是上網(wǎng)等文本界面,壓縮下來也要幾十k, 如果網(wǎng)絡(luò)帶寬不夠的話,比如公司有幾個(gè)下載愛好者,會(huì)比較慘。所以呢,決定傳差異,緩存前面的屏幕,看看如果差別不大,就只傳變化的部分。這樣數(shù)據(jù)量就比較小。但是呢,壓縮圖片的時(shí)候就不能采用有損壓縮啦,否則屏幕會(huì)變得越來越怪異。。。

    比較遺憾的是沒能象windows自帶的rdp那樣攔截繪圖操作,在點(diǎn)陣圖的方案上效率還是比較低的。希望有高手指點(diǎn)!

    skype4java是個(gè)日本人寫的,幾個(gè)聽了我介紹的朋友都有這疑問:日本人寫的?
    呵呵,如果你能寫出更好的,咱就不用它。那個(gè)日本作者還不錯(cuò),上班比較忙,還是答應(yīng)抽空fix幾個(gè)bug,感謝中~

    體驗(yàn)一下吧:skypeRDP
    posted @ 2006-12-06 20:18 steeven 閱讀(2610) | 評(píng)論 (6)編輯 收藏
     

    適用版本GWT 1.0.21。
    由于目前google web toolkit還沒有正式release, 所以問題多多。記錄一下碰到的問題:

    1. Shell調(diào)試模式和實(shí)際編譯結(jié)果有差異。
    shell中報(bào)告的異常在運(yùn)行中只是一些凌亂的腳本錯(cuò)誤,或者干脆沒有響應(yīng)。
    shell中通過的程序在實(shí)際運(yùn)行時(shí)還會(huì)有錯(cuò)誤。
    2. 避免錯(cuò)誤的方法是捕獲異常,
    在onModuleLoad方法中try catch
    或者GWT.setUnCaughtExceptionHandler()//全局異常捕獲
    3. LOG, 利用GWT.log(). shell模式下會(huì)輸出到控制臺(tái)。
    4. 遠(yuǎn)程調(diào)用屬于異步。同步遠(yuǎn)程調(diào)用可以自己包裝ClientCallback,在一個(gè)結(jié)束后調(diào)用另外一個(gè).
    5. RPC調(diào)用中Set傳遞有bug, 暫時(shí)用List
    6. Eclipse直接運(yùn)行Compiler/Shell, 加入gwt-dev-windows.jar。
    main: com.google.gwt.dev.GWTCompiler/GWTShell
    arguments: -out ${project_loc}\WebContent real/Index.html
    classpath->UserEnties->advanced->add folder->選擇項(xiàng)目的src目錄,要在第一位。
    7. Tomcat5問題多多, 用tomcat4.
    8. gwt-user中非法包含javax.servlet, tomcat認(rèn)為其無效。直接放到tomcat/common/lib中。或者在jar中去掉。
    9. Exception.getStackTrace() 在Shell模式下有效, GWT.isScript()可以判斷
    10. 靜態(tài)中文在html中亂碼,要在html header中加入<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    posted @ 2006-07-14 18:10 steeven 閱讀(2950) | 評(píng)論 (6)編輯 收藏
     
    開發(fā)設(shè)計(jì)兩個(gè)類:
    雞,構(gòu)造的時(shí)候要帶入蛋.
    蛋,構(gòu)造的時(shí)候要帶入雞.

    編譯沒問題,初始化數(shù)據(jù)的時(shí)候問題出來了.
    new 雞(new 蛋(???)) //蛋是誰下的?
    作為一個(gè)正統(tǒng)的進(jìn)化論學(xué)生,解決如下:構(gòu)造原始雞類,雞開始是不下蛋的,把雞的構(gòu)造函數(shù)改成空的,這時(shí)候初始化一條原始雞的數(shù)據(jù)沒問題.然后進(jìn)化出來蛋,雞下的,類不用改,把蛋的數(shù)據(jù)初始化好.這時(shí)候雞進(jìn)化,由蛋孵出來,構(gòu)造方法要帶蛋進(jìn)來,初始化一只新雞,刪除原始雞數(shù)據(jù).

    OK,問題解決了嗎?這樣程序每次初始化數(shù)據(jù)的時(shí)候要改造雞類,好像不大容易啊....

    那上帝造物學(xué)說怎樣解決問題呢?:
    雞1 = new 雞(null);
    蛋1 = new 蛋(null);
    雞1.set蛋(蛋1);
    蛋1.set雞(雞1);
    save(雞1,蛋1);
    雞和蛋同時(shí)出來了.上帝造物法勝利

    是不是我的類設(shè)計(jì)有問題,怎么會(huì)碰到雞生蛋蛋孵雞這種郁悶的問題呢?
    posted @ 2006-07-02 20:28 steeven 閱讀(1461) | 評(píng)論 (2)編輯 收藏
     

    db4o目前還沒有unique index/primary key機(jī)制。(5.4)

    ???? public ? static ? void ?main(String[]?args)? {
    ????????ObjectContainer?db?
    = ?Db4o.openFile( " test.yap " );
    ????????db.set(
    new ?User( " abc " , 234 ));
    ????????db.set(
    new ?User( " abc " , 234 ));
    ????????ObjectSet
    < User > ?list? = ?db.query(User. class );
    ????????System.out.println(list);
    ????????db.close();?
    // halt?without?this?line?in?5.2
    ????}

    上面的例子會(huì)存儲(chǔ)兩個(gè)同樣的User對(duì)象。
    僅有的ID是一個(gè)存儲(chǔ)文件中的ID, 經(jīng)過碎片整理之后會(huì)發(fā)生變化,顯然不適用。
    要實(shí)現(xiàn)一個(gè)auto_increament的主鍵恐怕要自行實(shí)現(xiàn)。或者用已有的UUID實(shí)現(xiàn)。

    可能db4o太年輕的關(guān)系,目前還沒有支援這些功能。建議用@Annotation來實(shí)現(xiàn)。并且控制存儲(chǔ)。
    @ID
    @Unique
    @Index
    在EJB3里面已經(jīng)有現(xiàn)成的定義可以參考。
    posted @ 2006-06-19 18:15 steeven 閱讀(919) | 評(píng)論 (0)編輯 收藏
     
    原來說是xaml只是隨著下一個(gè)版本的windows放出,后來改編到winfx里面,最近聽說作為.net3.0出現(xiàn).這樣的直接后果就是這個(gè)b/s+c/s通吃的UI框架不但要寄生在新版windows里面,也要被用來在xp上攻城略地.

    微軟這回蓄勢(shì)待發(fā)xaml有多強(qiáng)大呢?3d(感覺不夠純粹)/強(qiáng)大的數(shù)據(jù)綁定/動(dòng)畫/多媒體支持...
    這里可怕的不僅僅是框架,還有配套的GUI開發(fā)工具.有趣的是Interactive Designer據(jù)說就是用wpf開發(fā)的.
    xaml只是個(gè)xml描述文件,里面可以包含代碼,編譯成UI界面.所有的界面內(nèi)容也可以由程序動(dòng)態(tài)運(yùn)行.
    這樣未來運(yùn)行在browser里面的UI不是復(fù)雜的ajax,是和后臺(tái)一致的托管代碼.

    Java怎樣應(yīng)對(duì)呢?Java+Flash? 開發(fā)bs都困難重重.除非Flash能放棄as,直接同java結(jié)合,或者兩個(gè)公司合作開發(fā)一個(gè)新框架.這個(gè)新框架應(yīng)該是什么樣子呢?完全的3D視角,時(shí)間軸控制...重演c#后來居上的歷史.

    Java在Sun的手里一直半死不活,真希望能趕快被google并購(gòu),或者sun主動(dòng)把java捐贈(zèng)出來.

    如果沒有"意外",在wpf正式發(fā)行以后,桌面應(yīng)用將逐步過渡到wpf開發(fā).HTML由于其跨平臺(tái),可能會(huì)平分秋色.

    面對(duì)wpf,如何反抗?java.net是太監(jiān),在.net陣營(yíng)里面連二奶都不算,等于投降.
    利用xaml? xaml被編譯加載,其執(zhí)行框架還是.net,機(jī)會(huì)似乎不大.在瀏覽器上可能會(huì)有類似lasszlo的組合.

    作為Java愛好者,祈禱奇跡發(fā)生吧,還好在Java世界中奇跡是家常便飯 :)
    posted @ 2006-06-18 22:57 steeven 閱讀(2458) | 評(píng)論 (3)編輯 收藏
     

    一般Apply按鈕應(yīng)該在用戶有輸入時(shí)有效,輸入沒有變化時(shí)無效。
    為了達(dá)到這個(gè)效果,一般界面上每個(gè)輸入控件要監(jiān)聽,并且和以前的值做比較,實(shí)現(xiàn)起來相當(dāng)麻煩。

    因?yàn)槲覀円延械慕缑媸腔跀?shù)據(jù)綁定,綁定到一個(gè)克隆的對(duì)象上。這樣判斷有沒有變化就很簡(jiǎn)單,updateInput之后,比較兩個(gè)對(duì)象是否一致即可。

    什么時(shí)候去判斷呢?在用戶輸入之后:捕捉鍵盤、鼠標(biāo)事件。

    攔截鍵盤鼠標(biāo)事件目前找到兩種方法:
    1. Toolkit.getDefaultToolkit().addAWTEventListener(listener,eventMask);
    這個(gè)方法注冊(cè)全局的監(jiān)聽機(jī)制,無論哪個(gè)窗口。里面注冊(cè)為weakHashmap,應(yīng)該不用考慮垃圾回收問題。因?yàn)槭侨值模唤ㄗh采用。
    2. 攔截每個(gè)component自己的事件。
    正常來說,如果在textbox里面打字,事件不會(huì)交給window處理。enableInputMethods(true)可以幫忙。
    enable以后調(diào)用getInputContext(),取得InputContext處理。
    注意,InputContext的dispatchEvent(AWTEvent)會(huì)接到各種消息,感興趣的getID()有以下三個(gè):
    ???MouseEvent.MOUSE_CLICKED
    ???MouseEvent.MOUSE_WHEEL
    ???KeyEvent.KEY_TYPED

    posted @ 2006-06-13 16:52 steeven 閱讀(1633) | 評(píng)論 (2)編輯 收藏
     
    上海這方面活動(dòng)比較少,難得逮到一個(gè),跑去湊個(gè)熱鬧。天不作美,下班前一場(chǎng)大雨,讓參加的人少了很多。

    零星記了一些筆記,對(duì)我這個(gè)ajax門外漢來說收獲還是很大。主講是ajaxcn.org的兩位高手。robbin的Rubby講座因?yàn)闀r(shí)間關(guān)系要改期。

    1. JS2的一些新特性:class/extend/interface/package/import/塊作用域/操作符函數(shù). 明年底會(huì)有browser開始支持。
    //干脆把java直接搬到browser里面算了。
    //以后是不是弄個(gè)標(biāo)準(zhǔn)接口允許加載不同語言的腳本引擎?大家就不用受js的鳥氣了。
    2. 推薦的ajax框架:Dojo/DWR/Prototype/GWT/YUI
    //排名有先后
    3. 新技術(shù):
    canvas 畫圖,已有多數(shù)瀏覽器支持。據(jù)說有人用它實(shí)現(xiàn)了3D游戲
    SVG 基于xml的矢量圖。據(jù)說和canvas都支持3d繪圖。
    E4X: xml的包裝, firefox支持
    4. 技術(shù)和需求水漲船高 //我們不會(huì)失業(yè)了
    5. HiJax:
    用傳統(tǒng)方式快速開發(fā)。在傳統(tǒng)網(wǎng)頁基礎(chǔ)上hack成ajax應(yīng)用。
    對(duì)禁用js的瀏覽器表現(xiàn)為傳統(tǒng)網(wǎng)頁。
    前期開發(fā)和后期改造獨(dú)立性很強(qiáng)。
    //后期要改造為完美的ajax,對(duì)server端要做些小的改動(dòng)來適應(yīng)。
    6. 推薦用FireFox調(diào)試AJAX, 插件三劍客:
    firebug/web develope tool/temper data分別用來調(diào)試腳本,觀察頁面dom,監(jiān)聽通信。
    //js調(diào)試的日子好過多了,但不要忘記總體效率。。。

    回來路上和一位tx聊起來ajax在企業(yè)中的地位好像不高,他對(duì)敏捷開發(fā)很有好感,對(duì)辦公室環(huán)境的要求很有趣。
    本次活動(dòng)的主要心得是:自助餐很好吃,以后有活動(dòng)還要去吃 :)
    posted @ 2006-06-07 23:44 steeven 閱讀(1327) | 評(píng)論 (4)編輯 收藏
     
    gwt的這些特性還是很有意思的,感覺比echo更貼近html, 比如說尺寸等數(shù)據(jù),寫"20%"和"200px"都可以。echo則盡量封裝的象swing, 屏蔽掉html.

    anyway, 對(duì)于大多數(shù)邏輯都在客戶端的應(yīng)用,gwt可以大展身手。比如小游戲~

    guess number demo看這里:http://steeven.googlepages.com/MyApp.html
    完全在瀏覽器上運(yùn)行的玩意,沒有寫一句js,感覺還是很爽的~

    代碼如下:
    package?org.steeven.gwt.test.client;

    import?com.google.gwt.core.client.EntryPoint;
    import?com.google.gwt.user.client.Random;
    import?com.google.gwt.user.client.ui.Button;
    import?com.google.gwt.user.client.ui.ClickListener;
    import?com.google.gwt.user.client.ui.DialogBox;
    import?com.google.gwt.user.client.ui.Grid;
    import?com.google.gwt.user.client.ui.HasHorizontalAlignment;
    import?com.google.gwt.user.client.ui.RootPanel;
    import?com.google.gwt.user.client.ui.TextBox;
    import?com.google.gwt.user.client.ui.VerticalPanel;
    import?com.google.gwt.user.client.ui.Widget;

    /**
    ?*?
    @author?steeven@gmail.com
    ?
    */

    public?class?MyApp?implements?EntryPoint?{

    ????TextBox?txtCount?
    =?new?TextBox();

    ????
    private?Grid?pnlMain;

    ????
    private?Button[]?numbers?=?new?Button[100];

    ????
    private?int?target;

    ????
    private?int?count;

    ????
    private?DialogBox?box;

    ????
    private?Button?btnRetry;

    ????
    private?Button?btnClose;

    ????
    /**
    ?????*?This?is?the?entry?point?method.
    ?????
    */

    ????
    public?void?onModuleLoad()?{
    ????????VerticalPanel?pnlStatus?
    =?new?VerticalPanel();
    ????????pnlStatus.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    ????????pnlStatus.setSpacing(
    20);

    ????????txtCount.setEnabled(
    false);
    ????????txtCount.setVisibleLength(
    10);
    ????????pnlStatus.add(txtCount);
    ????????btnRetry?
    =?new?Button();
    ????????btnRetry.setHTML(
    "<img?src=\"replay.gif\"/>?<u>R</u>etry");
    ????????btnRetry.setAccessKey(
    'r');
    ????????btnRetry.addClickListener(
    new?ClickListener()?{
    ????????????
    public?void?onClick(Widget?sender)?{
    ????????????????doInit();
    ????????????}

    ????????}
    );
    ????????pnlStatus.add(btnRetry);

    ????????Button?btnAbout?
    =?new?Button();
    ????????btnAbout.setHTML(
    "<img?src='about.gif'/>?<u>A</u>bout");
    ????????btnAbout.setAccessKey(
    'a');
    ????????btnAbout.addClickListener(
    new?ClickListener()?{
    ????????????
    public?void?onClick(Widget?sender)?{
    ????????????????doAbout();
    ????????????}

    ????????}
    );
    ????????pnlStatus.add(btnAbout);

    ????????RootPanel.get(
    "status").add(pnlStatus);

    ????????pnlMain?
    =?new?Grid(10,?10);
    ????????RootPanel.get(
    "main").add(pnlMain);

    ????????
    for?(int?i?=?0;?i?<?100;?i++)?{
    ????????????numbers[i]?
    =?new?Button();
    ????????????numbers[i].setText(i?
    +?"");
    ????????????numbers[i].addClickListener(
    new?ClickListener()?{
    ????????????????
    public?void?onClick(Widget?sender)?{
    ????????????????????doGuess(sender);
    ????????????????}

    ????????????}
    );
    ????????????pnlMain.setWidget(i?
    /?10,?i?%?10,?numbers[i]);
    ????????}


    ????????box?
    =?new?DialogBox();
    ????????box.setPopupPosition(
    400,?200);
    ????????btnClose?
    =?new?Button("<u>C</u>lose",?new?ClickListener()?{
    ????????????
    public?void?onClick(Widget?sender)?{
    ????????????????box.hide();
    ????????????????doInit();
    ????????????}

    ????????}
    );
    ????????btnClose.setAccessKey(
    'c');
    ????????box.add(btnClose);
    ????????doInit();
    ????}


    ????
    protected?void?doGuess(Widget?sender)?{
    ????????Button?btn?
    =?(Button)?sender;
    ????????btnRetry.setEnabled(
    true);
    ????????
    int?n?=?Integer.parseInt(btn.getText());
    ????????txtCount.setText(
    ""?+?(++count));
    ????????
    if?(n?==?target)?{
    ????????????numbers[n].setEnabled(
    false);
    ????????????btnClose.setFocus(
    true);
    ????????????box.clear();
    ????????????box
    ????????????????????.setHTML(
    "<center><img?src='win.gif'/><h1>YOU?WIN!!!</h1><br/><br/><br/>");
    ????????????box.add(btnClose);
    ????????????box.show();
    ????????}
    ?else?{
    ????????????
    if?(n?<?target)
    ????????????????
    for?(int?i?=?0;?i?<=?n;?i++)
    ????????????????????numbers[i].setEnabled(
    false);
    ????????????
    else
    ????????????????
    for?(int?i?=?n;?i?<?100;?i++)
    ????????????????????numbers[i].setEnabled(
    false);
    ????????}


    ????}


    ????
    protected?void?doAbout()?{
    ????????box.clear();
    ????????box
    ????????????????.setHTML(
    "<img?src='about.gif'/><h1>Guess?Number</h1><h3>Google?web?toolkit?test</h3>");
    ????????box.add(btnClose);
    ????????box.show();
    ????}


    ????
    private?void?doInit()?{
    ????????btnRetry.setEnabled(
    false);
    ????????target?
    =?Random.nextInt(99);
    ????????count?
    =?0;
    ????????txtCount.setText(
    "0");
    ????????
    for?(int?i?=?0;?i?<?100;?i++)?{
    ????????????numbers[i].setVisible(
    true);
    ????????????numbers[i].setEnabled(
    true);
    ????????}

    ????}


    }


    第一次玩gwt, 總共花了3個(gè)小時(shí),菜呀
    posted @ 2006-06-02 15:23 steeven 閱讀(1846) | 評(píng)論 (13)編輯 收藏
     

    前面轉(zhuǎn)貼Liebeck(echo的主要開發(fā)者,我的偶像)關(guān)于echo2和gwt的對(duì)比:http://m.tkk7.com/steeven/archive/2006/06/01/49379.html

    今天仔細(xì)做了一些筆記,并且加入了一些自己的想法,供選型者參考:

    綜合對(duì)比:
    1. 兩個(gè)都是非傳統(tǒng)的b/s框架,都是用AJAX來構(gòu)造動(dòng)態(tài)網(wǎng)站。編程過程都和SWT/Swing差不多。
    2. 區(qū)別在于一個(gè)運(yùn)行于客戶端,一個(gè)運(yùn)行于服務(wù)器

    3. gwt把代碼編譯為html+js, 目前只支持java1.4規(guī)范。echo沒這限制。
    4. gwt可以運(yùn)行于任何web server, echo則需要傳統(tǒng)的servlet容器。(意義不大,現(xiàn)在哪有靜態(tài)網(wǎng)站啊,后臺(tái)交互肯定還是需要的)
    5. echo2的客戶端引擎通過ajax提交用戶動(dòng)作,對(duì)用戶界面增量更新。
    ?
    性能:
    1. gwt的頁面logic都在瀏覽器上,所以很快。但是如果需要和中間層交互,就會(huì)碰到同樣的網(wǎng)絡(luò)問題。
    2. echo2的代碼跑在server上,所以所有的交互都需要反饋給server。echo2在設(shè)計(jì)上盡量減少這種交互,比如客戶對(duì)文本的修改都是延遲發(fā)送到服務(wù)器,而服務(wù)器只發(fā)送頁面的變化部分到瀏覽器。
    3. gwt應(yīng)用被編譯成一個(gè)頁面,雖然應(yīng)用的復(fù)雜化,這個(gè)編譯結(jié)果也隨之變得可怕。。。(個(gè)人認(rèn)為隨著編譯器的發(fā)展,不同的頁面可以做到lazy load)
    4. echo的js模塊是lazy加載到瀏覽器的,界面上呈現(xiàn)哪些控件才去加載并且緩存對(duì)應(yīng)的js模塊。發(fā)送到客戶端的不是邏輯代碼,只有用戶狀態(tài)(個(gè)人認(rèn)為echo2現(xiàn)在過于lazy,導(dǎo)致初始化階段多次訪問server加載一些基本的js模塊,應(yīng)該揉合到一起。另外,因?yàn)閑cho邏輯代碼在服務(wù)器上,相對(duì)來說可以防止盜版)
    ?
    中間層和數(shù)據(jù)訪問:
    1. 如果要訪問數(shù)據(jù),gwt還是要回到傳統(tǒng)的模式,通過rpc訪問servlet。gwt提供把遠(yuǎn)程服務(wù)透明的包裝起來,中間傳送pojo. 盡管包裝了,中間的安全和和校驗(yàn)還是必須要開發(fā)者考慮。
    2. echo支持SOA,但是不必須。大多數(shù)情況下安全不是問題,因?yàn)閿?shù)據(jù)和邏輯都不會(huì)暴露到瀏覽器上。(以前給echo提過建議,瀏覽器用戶很可能去模擬一個(gè)被disabled按鈕提交,這種問題現(xiàn)在無需考慮)
    ?
    運(yùn)行環(huán)境:
    1. gwt運(yùn)行在瀏覽器上,并非所有的java類都能編譯成js. gwt現(xiàn)在只支持java.lang/java.util下面的一個(gè)子集(版本?1.0.21):27 classes, 11 interfaces, and 18 exception(這讓人想起了j2me開發(fā)). 一些現(xiàn)有的類庫就別想了。
    ?
    調(diào)試:
    1. gwt調(diào)試需要一套和運(yùn)行時(shí)完全不同的環(huán)境:HOST模式,代碼作為真正的java在運(yùn)行。(個(gè)人認(rèn)為這里因?yàn)槭羌僯ava調(diào)試,比echo的web調(diào)試要稍微方便一些。做單元測(cè)試也更方便些,但不是對(duì)最終browser的測(cè)試)
    2. echo調(diào)試就是傳統(tǒng)的servlet調(diào)試。
    ?
    授權(quán):
    1. gwt的api是開源的,編譯器和host模式瀏覽器不公開。整體來說:free. (個(gè)人認(rèn)為,如果要擴(kuò)充gwt可能會(huì)遇到麻煩)
    2. echo2開源,mozilla public license. free(個(gè)人認(rèn)為:echostudio也free就好了。nextapp畢竟要生存)
    ?
    應(yīng)用:
    1. gwt可以嵌入傳統(tǒng)的靜態(tài)html, 也能作為一個(gè)完整應(yīng)用。做大應(yīng)用要考慮編譯后的重量、本地化、庫支持等問題(關(guān)于18n, 可以在gwt支持論壇上搜索i18n,似乎已經(jīng)有方案)
    2. echo2成熟得可以適用各種應(yīng)用,但是不能作為靜態(tài)頁面的一部分使用。(有點(diǎn)吹牛,在大訪問量下,服務(wù)器的壓力肯定不會(huì)小)
    ?
    ?
    ?
    個(gè)人結(jié)論:
    1. 開發(fā)方式都很優(yōu)秀,用純java開發(fā)b/s
    2. gwt可用于大型網(wǎng)站,把壓力轉(zhuǎn)嫁給客戶端。
    3. echo可用于快速開發(fā)復(fù)雜的企業(yè)應(yīng)用,把壓力丟給服務(wù)器(企業(yè)里面最清閑的就是前臺(tái)和服務(wù)器)

    兩個(gè)產(chǎn)品都很優(yōu)秀,GWT是2006年的IT颶風(fēng),波及后面幾年。M$的日子要難過了, GOOGLE的確是個(gè)令人頭痛的對(duì)手。

    然而,還有比gwt/echo2更美好的未來嗎?
    有!把他們的輸出變成flash,用java開發(fā)flash應(yīng)用。去年探索過一段時(shí)間,原型已經(jīng)出來,因?yàn)閒lash開發(fā)調(diào)試太ugly, 沒有繼續(xù)下去。
    另外,微軟的WPF(AVALON)相當(dāng)值得關(guān)注。
    posted @ 2006-06-01 11:32 steeven 閱讀(1946) | 評(píng)論 (3)編輯 收藏
     

    Google Web Toolkit 雖然還是beta版本,和google的其他產(chǎn)品一樣,剛出生就注定不凡,也許將影響后面幾年的b/s開發(fā)。

    gwt利用了java開發(fā)的一切成熟條件,包括Unit test, refactor, IDE(eclipse...),傳統(tǒng)的b/s framework必將受到重創(chuàng),橫掃過后,JSF/ECHO等Server side framework可能幸存。如果哪天google加上serverside支持(從包命名上看是留有余地的)。。。雖然gwt目前還是小樣一個(gè),但是背后站的是重量級(jí)的google,強(qiáng)大的資源和數(shù)不完的銀子。。。。

    看到這玩意首先想到的是echo2, 客戶端技術(shù)都是ajax, 編碼都是java. 不同的是gwt發(fā)行時(shí)編譯成HTML+JS,Echo2則是完全的服務(wù)器端生成+更新。gwt跟server端交互依靠類似于ws的service把前后臺(tái)完全區(qū)分開。

    在echo的論壇里面已經(jīng)有人在討論這玩意了,并且八卦了一下gwt的前身似乎是Morfik的一部分(待證實(shí))
    從原理上,echo的開發(fā)者作出了對(duì)比,這個(gè)網(wǎng)站似乎被封鎖,這里轉(zhuǎn)貼一下:


    ===============================
    http://echotwo.blogspot.com/?作者tod liebeck

    Comparing the Google Web Toolkit to Echo2
    The Google Web Toolkit (GWT) is being compared to Echo2 quite frequently. Some of these comparisons have been fairly accurate, while others contain bits of misinformation. This article, written by the lead developer of Echo2, discusses the similarities and differences between these two frameworks.

    Overview

    The Google Web Toolkit and Echo2 definitely make for an interesting comparison. Both of these frameworks take a non-traditional approach toward web application development, even considering the latest crop of "AJAX-based frameworks" available today.

    The most obvious similarity between GWT and Echo2 is that they both enable the developer to create dynamic, AJAX-driven web user interfaces using only Java. In both projects, UIs are developed in a fashion similar to SWT or Swing: by assembling hierarchies of components and registering event handlers. Neither project requires the developer to work with HTML, JavaScript, or XML.

    The most obvious difference between GWT and Echo2 is that all of your GWT code is executed on the client, whereas your Echo2 code is executed on the server. There are advantages and disadvantages to both of these approaches, which will be highlighted throughout the article.

    GWT's defining attribute is the Java-to-JavaScript compiler. This compiler allows you to develop the web interface to your application in Java, then compile it to JavaScript. GWT limits the developer to a subset of the Java 1.4 libraries. GWT applications can be served by any web server, such as Apache, without the need for server-side processing.

    Echo2 applications are compiled to Java byte code and run on a Java server. Their Java code is executed by Echo2's "Web Application Container" layer, which sits atop a Java Servlet. On the web browser, the Echo2 "Client Engine" communicates user input to the Web Application Container via AJAX requests, with the server responding with directives to perform incremental updates to the state of the client web browser.

    User Interface Performance

    With GWT, all of your user interface code exists on the client browser. In operations that do not require server communication--that is, that do not require retrieving data from the middle tier--this configuration results in response times that are not dependent on the server. When data must be retrieved from the application's middle tier or business logic layer, the response time is subject to the same criteria as any other AJAX application, i.e., network latency, bandwidth, and server performance.

    Echo2 application code is run on the server, so for each user interaction that requires a call to the middle tier or immediate execution of the application's Java code, an AJAX connection is made to the server. Echo2 components are designed to minimize the client/server communication as much as is possible, limiting it to times when the server must be notified immediately of events. For example, simple events such as user input to a TextField component will not result in server contact. The server's response is the minimum set of instructions to incrementally update the client to reflect the new screen state.

    GWT applications are served to the client as a single HTML/JavaScript file, containing the entirety of the user interface. The size of this file will be proportional to the size of your user interface code and the toolkit libraries used by your application.

    Echo2 JavaScript modules are lazy-loaded to the client, and thereafter cached. A module will be retrieved when a component first appears on-screen that requires it. Application code is never sent to the client, only the state of the user interface.

    Middle Tier / Data Retrieval

    To access business data or perform a business process, a GWT user interface makes a remote procedure call (RPC) from the browser to a Servlet. GWT provides a mechanism to make the RPC invocation transparent to the developer, allowing the developer to build the application with "Plain Old Java Objects" (POJOs). However, any application that provides an RPC capability is a distributed application -- even when the RPC is accomplished transparently to the developer. Distributed applications in businesses and enterprises usually have security considerations and the remote objects serving the GWT clients must be designed with a focus on security to deflect attacks from imitated or hostile client applications.

    Echo2 applications support, but do not require, the use of distributed application logic or a Service Oriented Architecture (SOA). Alternatively, Echo2 applications can be built to run entirely within a single JVM instance, backed by a POJO-based middle tier. This allows Echo2 developers to build applications without the security concerns of distributed application logic -- and leverage the many strong frameworks built around POJO development such as the Spring Framework and Hibernate. Echo2 accomplishes this by keeping the state of a user's web interface on the server so that no remote objects need to be exposed.

    Run-time Environment

    GWT has some limitations due to the fact that applications are run on the client browser. First, GWT applications are limited to using a subset of the core Java class libraries, consisting of 27 classes, 11 interfaces, and 18 exception types found in the java.util and java.lang packages (as of GWT 1.0.21). This limitation prevents GWT applications from linking to most existing Java libraries. Additionally, all Java code must be compliant with the Java 1.4 specification; 1.5 is not supported. Localization-related portions of the Java API are not provided.

    Debugging

    GWT provides an alternate deployment environment for applications to facilitate debugging. The environment, called "Hosted Mode", allows a GWT application to be run as Java byte code in a local JVM, to which an IDE's debugger can be connected. In this mode, the application's user interface is displayed in a special web browser (a Mozilla/Firefox derivative).

    Echo2 applications may be debugged in the conventional manner, by connecting an IDE's debugger to a JVM running a Servlet container.

    Licensing

    The primary component of GWT, the Java-to-JavaScript cross-compiler, is proprietary, binary-only software. The Java API libraries are open source software, distributed under the Apache License. The API libraries have essentially no value without the proprietary compiler. The (non-critical) hosted-mode browser is also under the proprietary license. GWT is provided free of charge.

    Echo2 is open source software, licensed under the Mozilla Public License, and provided free of charge.

    Applicability

    GWT can be used as a means of creating AJAX components to embed in traditional web applications (or even in static web pages) as well as for creating complete application user interfaces. There are some issues to using it for the creation of large applications, where downloading an entire application to a client web browser in one shot would not be practical. The lack of localization and full Java API support also presents a problem for larger solutions.

    Echo2 is practical for creating web applications of any size. It is however not intended to scale downward to function as a platform for simply creating AJAX components in traditional web frameworks (or static web sites).

    More Information

    Google Web Toolkit:
    Home Page, Example Applications, Getting Started Guide, Developer Guide

    Echo2:
    Home Page, Example Applications, Tutorial
    posted by Tod Liebeck at 5:13 AM | 0 comments??

    ======================================
    畢竟gwt還是小baby, 以后怎么發(fā)展還難說,現(xiàn)在下結(jié)論太早。這兩天試用一下,有空從細(xì)節(jié)上對(duì)比一下。

    posted @ 2006-06-01 00:55 steeven 閱讀(608) | 評(píng)論 (0)編輯 收藏
     

    測(cè)試一下getResource(URI,boolean):

    ????????System.out.println(EcorePackage.eINSTANCE.eResource());? // 1
    ????????System.out.println(XMLTypePackage.eINSTANCE.eResource());? // 2

    ????????ResourceSet?rs?
    = ? new ?ResourceSetImpl();
    ????????rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
    ????????????????Resource.Factory.Registry.DEFAULT_EXTENSION,
    ????????????????
    new ?XMIResourceFactoryImpl());
    ????????String?uri?
    = ? " http://abc.eg/asdf " ;
    // ????????System.out.println(rs.createResource(URI.createURI(uri)));? // ?如果創(chuàng)建過臨時(shí)的,得到這個(gè)
    // ????????System.out.println(rs.createResource(URI.createURI(uri)));? // ?如果創(chuàng)建過多個(gè)臨時(shí)的,返回第一個(gè),這個(gè)忽略
    ????????rs.getPackageRegistry().put(uri,?EcorePackage.eINSTANCE);? // 得到結(jié)果同1,如果上面取消注釋,本地創(chuàng)建的優(yōu)先

    ????????System.out.println(rs.getResource(URI.createURI(uri),?
    false ));? // 同1


    createResource每次創(chuàng)建新的,getResource則是唯一實(shí)例的。

    每個(gè)生成的XxxPackage.eINSTANCE會(huì)自行創(chuàng)建自己的Resource。如果在插件中修改了EcorePackge.eInstance.eResource(),會(huì)不會(huì)天下大亂呢?

    ==================
    eclispe編輯器右邊的Mark Occurrence很方便,但是家里電腦上的這個(gè)黃色小標(biāo)記很不清楚。前幾天調(diào)整了老半天,修改配色方案,換顯示器驅(qū)動(dòng),調(diào)整顯示器對(duì)比度、亮度都收效不大。昨天偶然把XP的桌面風(fēng)格換回傳統(tǒng)模式,搞定了。

    ecore.ecore這個(gè)問題很有意思,以前看過schema.xsd,就是自己定義自己。據(jù)說JDK也是用java開發(fā)編譯出來的。。。
    先有雞還是現(xiàn)有蛋呢?

    posted @ 2006-05-26 10:22 steeven 閱讀(1024) | 評(píng)論 (1)編輯 收藏
     

    在RS中同一URI可以createResource多個(gè)Resource,List方式存放。還存在另外一種Map存放方式, getResource(URI,boolean loadOnDemand)就是通過這種方式存取,如果不存在的話創(chuàng)建。這兩個(gè)方法看起來有些沖突。似乎用于不同場(chǎng)合。

    再來看看怎樣通過URL存取EObject:
    RS整個(gè)相當(dāng)于一個(gè)DataBase, Resource相當(dāng)于表,存放的是EObject, 每個(gè)EObject可以看成對(duì)象或者XML。
    表用URI來區(qū)分,URI中的Segment用來定位EObject。URI的例子參見探索(1)
    getEObject(URL, boolean loadOnDemand)很簡(jiǎn)單,getResource找到對(duì)應(yīng)的Resource,在里面根據(jù)Segment查找,就是那個(gè)#///@xxx.n格式的東西,注意,還有ID方式。

    getPackageRegistry()用來返回RS的URL->Package注冊(cè)表,它也是個(gè)本地的注冊(cè)表,代理了全局的EPackage.Registry.INSTANCE。這個(gè)注冊(cè)表用于取得EPackage(類型信息)和EFactory(創(chuàng)建實(shí)例)


    Resource就不說了,主要load,save, 一些具體子類,比如XmlResourceImpl可以直接使用,指定Encoding之類。

    看看ResourceSet對(duì)EMF了解了很多~

    posted @ 2006-05-26 01:23 steeven 閱讀(1097) | 評(píng)論 (0)編輯 收藏
     
    來看看ResourceSet.createResource(URI):Resource方法,從URI到Resource的過程如下:
    1. getResourceFactoryRegistry()
    ??public?Resource.Factory.Registry?getResourceFactoryRegistry()
    ??
    {
    ????
    if?(resourceFactoryRegistry?==?null)
    ????
    {//可以自行Set一個(gè)注冊(cè)表實(shí)現(xiàn),沒有的話用系統(tǒng)缺省注冊(cè)表
    ??????resourceFactoryRegistry?=
    ????????
    new?ResourceFactoryRegistryImpl()
    ????????
    {
    ??????????
    public?Resource.Factory?delegatedGetFactory(URI?uri)
    ??????????
    {
    ????????????
    return?Resource.Factory.Registry.INSTANCE.getFactory(uri);
    ??????????}

    ????????}
    ;?//代理系統(tǒng)注冊(cè)表,注意這個(gè)應(yīng)該是正宗的。
    ????}

    ????
    return?resourceFactoryRegistry;
    ??}

    所以自己new 出來的ResourceSet可以向注冊(cè)表中任意添加工廠實(shí)現(xiàn)。
    2. 調(diào)用注冊(cè)表的getFactory(URI), 實(shí)現(xiàn)如下:
    ?public?Resource.Factory?getFactory(URI?uri)
    ??
    {
    ????String?protocol?
    =?uri.scheme();
    ????Object?resourceFactory?
    =??protocolToFactoryMap.get(protocol);?//先根據(jù)protocol查找
    ????if?(resourceFactory?==?null)
    ????
    {
    ??????String?extension?
    =?uri.fileExtension();
    ??????resourceFactory?
    =?extensionToFactoryMap.get(extension);?//找不到再根據(jù)擴(kuò)展名查找
    ??????if?(resourceFactory?==?null)
    ??????
    {
    ????????resourceFactory?
    =?extensionToFactoryMap.get("*");?//嘗試查找缺省擴(kuò)展
    ????????if?(resourceFactory?==?null)
    ????????
    {
    ??????????resourceFactory?
    =?delegatedGetFactory(uri);?//自行實(shí)現(xiàn)可以擴(kuò)展此方法解析。
    ????????}

    ??????}

    ????}


    ????
    //Descriptor可以用于編程使用
    ????return?
    ??????resourceFactory?
    instanceof?Resource.Factory.Descriptor??
    ????????((Resource.Factory.Descriptor)resourceFactory).createFactory()?:
    ????????(Resource.Factory)resourceFactory;
    ??}

    查找一個(gè)工廠居然這么復(fù)雜!正因?yàn)檫@么復(fù)雜,才能支持platform/file/fttp等眾多千奇百怪的URI
    不同類型的工廠加工出不同類型的Resource, 才會(huì)輸出為XSD/XML/XMI/....

    如果直接操作系統(tǒng)注冊(cè)表要小心。EMF中定義了幾個(gè)擴(kuò)展點(diǎn),可以實(shí)現(xiàn)類似目的。
    已知的ResourceFactory實(shí)現(xiàn)有:XSD/ECore/EMOF/XML/XMI,XSD的輸出方法的介紹可以參考Eclipse Development using the Graphical Editing Framework and the Eclipse Modeling Framework電子書。



    posted @ 2006-05-26 00:02 steeven 閱讀(1131) | 評(píng)論 (0)編輯 收藏
     
    這個(gè)東西比較有趣,代碼還要區(qū)分是否在Eclipse環(huán)境下運(yùn)行。
    先看看現(xiàn)象,以EMF例子Library.ecore為例, 測(cè)試代碼如下:
    public?class?Test?{
    ????
    public?static?void?main(String[]?args)?throws?IOException?{
    ????????ResourceSet?rs?
    =?new?ResourceSetImpl();
    ????????rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
    ????????????????Resource.Factory.Registry.DEFAULT_EXTENSION,
    ????????????????
    new?XMIResourceFactoryImpl()); //outside eclipse
    ????????Resource?resource?
    =?rs.createResource(URI
    ????????????????.createURI(EXTLibraryPackage.eNS_URI));
    ????????
    //step?a
    ????????Library?library?=?EXTLibraryFactory.eINSTANCE.createLibrary();
    ????????library.setName(
    "some?lib");
    ????????resource.getContents().add(library);
    ????????
    //step?b
    //????????Book?book?=?EXTLibraryFactory.eINSTANCE.createBook();
    //????????book.setTitle("some?book");
    //????????Employee?employee?=?EXTLibraryFactory.eINSTANCE.createEmployee();
    //????????employee.setFirstName("some?one");
    ????????
    //step?c
    //????????library.getBooks().add(book);
    //????????library.getEmployees().add(employee);
    ????????
    //step?d
    //????????resource.getContents().add(book);
    ????
    //????????System.out.println(EcoreUtil.getURI(employee));
    //????????System.out.println(EcoreUtil.getURI(book));
    ????????resource.save(System.out,?null);
    ????}

    }


    步驟 輸出
    a ----------------
    <?xml version="1.0" encoding="ASCII"?>
    <extlib:Library xmi:version="2.0" xmlns:xmi="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0" name="some lib"/>
    b?#//
    #//
    <?xml version="1.0" encoding="ASCII"?>
    <extlib:Library xmi:version="2.0" xmlns:xmi="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0" name="some lib"/>
    c http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0#//@employees.0
    #//
    <?xml version="1.0" encoding="ASCII"?>
    <extlib:Library xmi:version="2.0" xmlns:xmi="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0" name="some lib">
    ? <employees firstName="some one"/>
    </extlib:Library>
    d http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0#/0/@employees.0
    http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0#/1
    <?xml version="1.0" encoding="ASCII"?>
    <xmi:XMI xmi:version="2.0" xmlns:xmi="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0">
    ? <extlib:Library name="some lib">
    ??? <employees firstName="some one"/>
    ? </extlib:Library>
    ? <extlib:Book title="some book"/>
    </xmi:XMI>

    可以看到,沒有加入lib的時(shí)候,employee/book實(shí)例的URI都是#//, employee加入以后有了#//@employees.0, book依舊。
    在book加入resource以后有了#/1的URI, employee/book在containment定義分別是true,false,所以employee加入lib以后就隨lib加入resource(實(shí)例容器)。book則要單獨(dú)加入。

    另外一個(gè)有趣的現(xiàn)象是Resource可以容納多個(gè)實(shí)例,在step d可以看到輸出的根節(jié)點(diǎn)由lib變成匿名容器。

    如果lib不加入resource又如何呢?
    步驟 輸出
    a ----------------
    b?#//
    #//
    c #///@employees.0
    #//
    d ----------------
    沒加入resource之前,URI是未知的,知道的只是相對(duì)父節(jié)點(diǎn)的相對(duì)segment.

    posted @ 2006-05-25 22:40 steeven 閱讀(1199) | 評(píng)論 (1)編輯 收藏
     
    Eclipse的Ecore編輯工具里面Annotation完全要手寫,比如寫ExtendedMetaData就很費(fèi)勁。
    手寫指定Source,指定每個(gè)Key/Value很容易出錯(cuò)。
    這個(gè)插件通過向?qū)нx擇source, 通過PropertySheet編寫Key/Value。并且根據(jù)Ecore的定義實(shí)現(xiàn)校驗(yàn)。

    Step1:


    Step 2:
    AllDataTypes組合了該URL下面所有的EDataType


    Step3: 編輯屬性。注意source的變化:
    如果選擇的AllDataTypes,就是Ecore的URI
    如果選擇某個(gè)EClass, 后面會(huì)加上#EClassName


    Step4: 如果選擇AllDataTypes,自動(dòng)選擇所有EdataTypes。


    Step5: 工作結(jié)果



    請(qǐng)注意Source的生成規(guī)則!

    適用版本:eclipse3.2rc3
    下載地址: http://m.tkk7.com/Files/steeven/org.steeven.eclipse.emf.annotation.wizard.zip (含源碼)
    posted @ 2006-05-24 20:14 steeven 閱讀(1237) | 評(píng)論 (3)編輯 收藏
     
    EMF驗(yàn)證方面的文檔很少, 日他娘的微軟拼音,真討厭啊。
    因?yàn)楸容^少,所以這里總結(jié)一下。

    驗(yàn)證的定義有兩種方式:
    1. 生成驗(yàn)證方法框架,代碼自己實(shí)現(xiàn)。參見EMF Overview:
    ? 添加Annotatio, Source=http://www.eclipse.org/emf/2002/Ecore, 然后添加DetailsEntry:key=constraints, Value=validateXxx
    ? EDataType,EClass支持,屬性不支持。
    2. 定義類似Schema的Facet,自動(dòng)生成對(duì)應(yīng)的驗(yàn)證代碼,用于驗(yàn)證簡(jiǎn)單數(shù)據(jù)類型:
    ? 添加Annotatio, Source=http:///org/eclipse/emf/ecore/util/ExtendedMetaData, 然后添加DetailsEntry:key=maxLength, Value=2
    ? 支持的facet參見ExtendedMetaData。
    ? 僅EDataType支持,屬性不支持。

    示例Ecore:

    新生成SqlmodelValidator.java, 代碼如下:

    可見Table_ValidateC, MyLabel_ValidateA,MyLabel_validateB都自動(dòng)生成,修改里面的if(false)為需要的業(yè)務(wù)判斷邏輯。
    validateMyLabel_MaxLength()方法是根據(jù)ExtendedMetaData自動(dòng)生成的,無需修改。

    總結(jié):
    1. EMF驗(yàn)證利用了Annotation擴(kuò)展,這種機(jī)制很靈活,但是給用戶帶來不便。
    2. Attribute屬性不能生成驗(yàn)證規(guī)則(eclipse3.2rc3),可以定義為單獨(dú)的EDataType,然后引用之。
    3. Constraints+Facet+本身的結(jié)構(gòu)驗(yàn)證可以構(gòu)成很強(qiáng)的驗(yàn)證規(guī)則,并且屬于Model層,數(shù)據(jù)本身即可驗(yàn)證自身。
    4. EObjectValidator.DynamicEDataTypeValidator似乎可用于動(dòng)態(tài)驗(yàn)證,有知道用法的朋友給講解一下~

    posted @ 2006-05-19 19:03 steeven 閱讀(1143) | 評(píng)論 (0)編輯 收藏
     
    SDO,簡(jiǎn)單理解就是EMF的脫機(jī)版。類似于resultSet和DataSet。可用于smartclient等脫機(jī)數(shù)據(jù)加工場(chǎng)合。
    主要特點(diǎn):(個(gè)人理解)
    可驗(yàn)證
    強(qiáng)類型
    可取出完整數(shù)據(jù)和差異。

    生成SDO代碼和EMF大同小異,主要是在my.genmodel的第一個(gè)節(jié)點(diǎn)的右鍵菜單中選擇:Set SDO defaults.

    體驗(yàn):
    1. 生成Editor后,執(zhí)行生成的Editor Plugin
    2. 新建Example EMF Model Creation Wizards->Data Graph Model
    3. 在Changes節(jié)點(diǎn)上Start Loggin, 然后編輯數(shù)據(jù)即可看到自動(dòng)生成的差異。

    網(wǎng)上手工操作SDO的示例代碼比較少,這里簡(jiǎn)單demo如下:
    import?java.util.Iterator;

    import?org.eclipse.emf.ecore.EObject;
    import?org.eclipse.emf.ecore.sdo.EDataGraph;
    import?org.eclipse.emf.ecore.sdo.SDOFactory;
    import?org.steeven.family.FamilyFactory;
    import?org.steeven.family.個(gè)人;
    import?org.steeven.family.家庭;

    import?commonj.sdo.ChangeSummary;
    import?commonj.sdo.DataGraph;
    import?commonj.sdo.DataObject;

    public?class?Server?{

    ????
    public?static?void?main(String[]?args)?{
    ????????
    //?client?side
    ????????EDataGraph?graph?=?loadGraph();
    ????????graph.getChangeSummary().beginLogging(); // important!
    ????????家庭?family?
    =?(家庭)?graph.getRootObject();
    ????????family.setTitle(
    "my?family");
    ????????個(gè)人?baby?
    =?FamilyFactory.INSTANCE.create個(gè)人();
    ????????baby.set姓名(
    "sophie");
    ????????family.get兔崽子().add(baby);
    ????????graph.getChangeSummary().endLogging();
    ????????saveGraph(graph);
    ????????update(graph);
    ????}


    ????
    //server?side
    ????public?static?EDataGraph?loadGraph()?{
    ????????家庭?family?
    =?FamilyFactory.INSTANCE.create家庭();?//?or?load?from
    ????????
    //?database
    ????????EDataGraph?graph?=?SDOFactory.eINSTANCE.createEDataGraph();
    ????????graph.setERootObject((EObject)?family);
    ????????
    return?graph;
    ????}


    ????
    //server?side?full?save
    ????public?static?void?saveGraph(EDataGraph?graph)?{
    ????????System.out.println(graph.getRootObject());
    ????}


    ????
    //server?side?update?changed?objects
    ????public?static?void?update(DataGraph?dataGraph)?{
    ????????ChangeSummary?changeSummary?
    =?dataGraph.getChangeSummary();
    ????????
    for?(Iterator?it?=?changeSummary.getChangedDataObjects().iterator();?it
    ????????????????.hasNext();)?
    {
    ????????????DataObject?changedObject?
    =?(DataObject)?it.next();
    ????????????System.out.println(
    "Update?for?"?+?changedObject);
    ????????????
    for?(Iterator?settingIt?=?changeSummary.getOldValues(changedObject)
    ????????????????????.iterator();?settingIt.hasNext();)?
    {
    ????????????????ChangeSummary.Setting?changeSetting?
    =?(ChangeSummary.Setting)?settingIt
    ????????????????????????.next();
    ????????????????System.out.println(
    "?(changed?"
    ????????????????????????
    +?changeSetting.getProperty().getName()?+?"?from?\""
    ????????????????????????+?changeSetting.getValue()?+?"\"?to?\""
    ????????????????????????
    +?changedObject.get(changeSetting.getProperty())
    ????????????????????????
    +?"\")");
    ????????????}

    ????????}

    ????}

    }

    輸出:
    org.steeven.family.impl.家庭Impl@9664a1?(title:?my?family)
    Update?for?org.steeven.family.impl.個(gè)人Impl@1729854?(姓名:?sophie,?性別:?男)
    Update?for?org.steeven.family.impl.家庭Impl@9664a1?(title:?my?family)
    ?(changed?title?from?"null"?to?"my?family")
    ?(changed?兔崽子?from?"[]"?to?"[org.steeven.family.impl.個(gè)人Impl@1729854?(姓名:?sophie,?性別:?男)]")

    SDO生成的代碼似乎更加純凈一點(diǎn),沒有很多的eXxxx()方法(有需要的也可以取到)。
    據(jù)說log的開銷比較大,不建議對(duì)大量數(shù)據(jù)使用。
    posted @ 2006-05-15 19:00 steeven 閱讀(1819) | 評(píng)論 (5)編輯 收藏
     

    看到eclipse3.2里面的GMF, 覺得比較有趣,底層還是用到了EMF. 花了兩天時(shí)間仔細(xì)研究了以下EMF,的確是個(gè)好東西.

    EMF根據(jù)ecore建模(可以和schema的xsd相互轉(zhuǎn)換)生成強(qiáng)類型的EMF代碼. 這個(gè)強(qiáng)類型更強(qiáng)的地方是可以取得meta信息,從而可以用于校驗(yàn)和界面輔助信息的生成.類似于動(dòng)態(tài)bean,屬性也可以根據(jù)名稱動(dòng)態(tài)取得.

    以前考慮過用xsd描述界面, 但是數(shù)據(jù)載體只能是xml, 即使利用apache的schema編譯工具生成強(qiáng)類型的類,后臺(tái)代碼也是xml. 不利于持久化. emf在代碼生成引擎比較智能,可以標(biāo)記出用戶代碼和自動(dòng)生成代碼.不會(huì)有生成覆蓋問題.

    這里做個(gè)簡(jiǎn)單示例:
    1. Ecore:
    可以新建Ecore, 建立好以后用GMF可視化編輯(Eclipse3.2RC2)

    2. 生成Model:
    點(diǎn)擊my.ecore文件,菜單:File->New->Other->Eclipse Modeling Framework->EMF Model
    3. 打開生成的my.genmodel, 選擇樹頂點(diǎn)的:Generate Model Code
    生成的代碼里面會(huì)有一個(gè)編譯錯(cuò)誤. 是中文編程的問題, 中文沒有大小寫(先天不足啊),結(jié)果性別這個(gè)成員變量和性別類名混淆,出錯(cuò).在錯(cuò)誤代碼前面加上包全名即可.
    4. 利用生成的代碼構(gòu)建一個(gè)家庭,輸出xml并且校驗(yàn)之:

    import ?java.io.IOException;
    import ?java.util.Iterator;

    import ?org.eclipse.emf.common.util.Diagnostic;
    import ?org.eclipse.emf.common.util.URI;
    import ?org.eclipse.emf.ecore.EObject;
    import ?org.eclipse.emf.ecore.resource.Resource;
    import ?org.eclipse.emf.ecore.util.Diagnostician;
    import ?org.eclipse.emf.ecore.xmi.XMLResource;
    import ?org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
    import ?org.steeven.family.FamilyFactory;
    import ?org.steeven.family.人物;
    import ?org.steeven.family.家庭;
    import ?org.steeven.family.性別;

    public ? class ?TestMy? {

    ????
    public ? static ? void ?main(String[]?args)? throws ?IOException? {
    ????????testFamily();
    ????}


    ????
    private ? static ? void ?testFamily()? throws ?IOException? {
    ????????家庭?family?
    = ?FamilyFactory.eINSTANCE.create家庭();
    ????????family.setTitle(
    " steeven家 " );
    ????????family.set老公(FamilyFactory.eINSTANCE.create人物());
    ????????family.get老公().set姓名(
    " steeven " );
    ????????family.set老婆(FamilyFactory.eINSTANCE.create人物());
    ????????family.get老婆().set姓名(
    " stella " );
    ????????family.get老婆().set性別(性別.女_LITERAL);
    ????????人物?sophie?
    = ?FamilyFactory.eINSTANCE.create人物();
    ????????sophie.set姓名(
    " sophie " );
    ????????sophie.set性別(性別.女_LITERAL);
    ????????family.get兔崽子().add(sophie);
    ????????dump(family);
    ????????validate(family);
    ????}


    ????
    private ? static ? void ?validate(EObject?family)? {
    ????????Diagnostic?diagnostic?
    = ?Diagnostician.INSTANCE.validate(family);
    ????????System.out.println(diagnostic);
    ????????
    for ?(Iterator?it? = ?diagnostic.getChildren().iterator();?it.hasNext();)? {
    ????????????Diagnostic?diag?
    = ?(Diagnostic)?it.next();
    ????????????System.out.println(diag.getMessage());
    ????????}

    ????}


    ????
    private ? static ?Resource?dump(EObject?objs)? throws ?IOException? {
    ????????
    // ?ResourceSet?rs?=?new?ResourceSetImpl();
    ????????
    // ?rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
    ????????
    // ?Resource.Factory.Registry.DEFAULT_EXTENSION,
    ????????
    // ?new?XMIResourceFactoryImpl());
    ????????
    // ?Resource?resource?=?rs.createResource(URI
    ????????
    // ?.createFileURI("c:\\temp\\test.xml"));
    ????????XMLResource?resource? = ? new ?XMLResourceImpl(URI
    ????????????????.createFileURI(
    " c:\\temp\\test.xml " ));
    ????????resource.setEncoding(
    " GBK " );
    ????????
    for ?(EObject?obj?:?objs)
    ????????????resource.getContents().add(obj);?
    // ?目前版本不加入resource驗(yàn)證會(huì)報(bào)singling異常
    ????????resource.save(System.out,? null );
    ????????
    return ?resource;
    ????}

    }

    運(yùn)行結(jié)果如下:

    <? xml?version="1.0"?encoding="GBK" ?>
    < family: 家庭?xmlns:family ="http://org.steeven/family" ?title ="steeven家" ?老公 ="/" ?老婆 ="/" ?兔崽子 ="/" />
    Diagnostic?ERROR?
    The?feature?'老公'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@6eb38a{#//}'
    The?feature?'老婆'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@1cd2e5f{#//}'
    The?feature?'兔崽子'?of?'org.steeven.family.impl.家庭Impl@f6a746{file:/c:/temp/test.xml#/}'?contains?a?dangling?reference?'org.steeven.family.impl.人物Impl@19f953d{#//}'

    可見輸出的xml中沒有包含人物的具體信息. 修改my.ecore中老公/老婆/兔崽子屬性的containment屬性為true,重新生成代碼后運(yùn)行結(jié)果如下:
    <?xml?version="1.0"?encoding="GBK"?>
    <family:家庭?xmlns:family="http://org.steeven/family"?title="steeven家">
    ??
    <老公?姓名="steeven"/>
    ??
    <老婆?性別="女"?姓名="stella"/>
    ??
    <兔崽子?性別="女"?姓名="sophie"/>
    </family:家庭>
    Diagnostic?OK


    ====================
    EMF單獨(dú)運(yùn)行成功~

    這里ECORE似乎不支持嵌套定義,不像schema那樣一個(gè)complexType聲明里面可以定義的很復(fù)雜, 也不像Java的內(nèi)部類. 似乎被作了簡(jiǎn)化, 更像關(guān)系數(shù)據(jù)庫表之間的關(guān)系.

    待求證問題:
    1. EMF的校驗(yàn)信息是否支持國(guó)際化.
    2. EMF數(shù)據(jù)的能否更方便的保存到數(shù)據(jù).

    EMF的靈活和強(qiáng)大已經(jīng)驗(yàn)證過, 用于C/S還是B/S應(yīng)該都不是問題.
    posted @ 2006-05-14 21:27 steeven 閱讀(2076) | 評(píng)論 (3)編輯 收藏
     
    最近照葫蘆畫瓢,寫了一個(gè)manifest的可視化編輯和自動(dòng)更新工具。

    主要想法是運(yùn)行程序一句話搞定: java -jar xxx.jar。所有class path在jar里面的manfiest.mf中設(shè)定。
    當(dāng)需要引用的jar很多的時(shí)候,windows2000有命令行的長(zhǎng)度限制,會(huì)報(bào)錯(cuò)。

    主要功能:
    1. new wizard
    2. gui editor
    3. switch auto-update in project menu

    Class-Path in auto-updated manifest.mf file will be auto updated
    while increase & full building.

    下載:http://m.tkk7.com/Files/steeven/org.steeven.eclipse.manifest_1.0.zip

    安裝:eclipse菜單[help]->?Software Updates->?Find and Install ->????Search for new features to install ->???new archieved site
    posted @ 2006-04-07 16:24 steeven 閱讀(967) | 評(píng)論 (2)編輯 收藏
     

    最近碰到幾個(gè)怪問題:
    1. 在新裝的XP上Swing界面文字不顯示,加上遠(yuǎn)程調(diào)試參數(shù)就能出來。安裝最新的jre/jdk也沒用。啟動(dòng)時(shí)加上遠(yuǎn)程調(diào)試參數(shù)OK,但不能這樣交付啊。后來給顯卡升級(jí)了一下驅(qū)動(dòng),搞定!真是奇怪
    2. xp上跑的很好的批處理在win2k下失敗,%~dps0失敗,這是用來取批處理的短格式當(dāng)前路徑。google后知道這個(gè)參數(shù)在xpsp2以前都返回錯(cuò)誤路徑,我倒。。。 %~dps1, %~dp0都能正常工作,于是乎,寫了兩個(gè)批處理,把%dp0(長(zhǎng)路徑)傳給另外一個(gè),在那里面用%~dps1取得后設(shè)定環(huán)境變量,成功~
    3.?Java程序安裝成服務(wù)以后不能接受其他電腦的訪問,獨(dú)立運(yùn)行的時(shí)候沒問題。用超級(jí)用戶權(quán)限也沒戲。后來拍拍腦袋發(fā)現(xiàn)是防火墻的問題,手動(dòng)啟動(dòng)服務(wù)的時(shí)候windows防火墻不提示是否允許訪問網(wǎng)絡(luò),所以缺省就被禁止鳥~。在防火墻中添加例外程序以后OK。所以安裝程序需要聰明一些,自己在注冊(cè)表中增加相關(guān)設(shè)定。

    posted @ 2006-04-07 16:15 steeven 閱讀(672) | 評(píng)論 (0)編輯 收藏
    CALENDER
    <2006年4月>
    2627282930311
    2345678
    9101112131415
    16171819202122
    23242526272829
    30123456

    常用鏈接

    留言簿(10)

    隨筆分類

    隨筆檔案

    文章檔案

    相冊(cè)

    我的鏈接

    搜索

    •  

    最新評(píng)論

    • 1.?re: 編程使用SDO[EMF兄弟篇]
    • 最近也在看這個(gè),有沒有好點(diǎn)的文章和代碼啊,有的話麻煩給些,謝謝,郵箱:
      huanggenping2002@163.com
    • --zebrahgp
    • 2.?re: SNMP親密接觸
    • 請(qǐng)問,我在接收Trap時(shí),同時(shí)有多個(gè)設(shè)備發(fā)送,在同一時(shí)間接收到的會(huì)有丟失的情況,怎么解決呢?snmp4j自帶的ThreadPool類有沒有在這方面起到多線程作用?
    • --analyser
    • 3.?re: 編程使用SDO[EMF兄弟篇]
    • 我也在研究soa,如果你有sdo方面的代碼,麻煩您給我一份作為參考,謝謝
      郵箱: litao5168@sohu.com 謝謝
    • --litao
    • 4.?re: 編程使用SDO[EMF兄弟篇]
    • 我也在研究soa,如果你有sdo方面的代碼,麻煩您給我一份作為參考,謝謝
    • --litao
    • 5.?re: 編程使用SDO[EMF兄弟篇]
    • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
    • --1984prince

    Powered By: 博客園
    模板提供滬江博客

    主站蜘蛛池模板: 亚洲毛片av日韩av无码| 国产精品亚洲а∨天堂2021| 成人性生交大片免费看中文| www国产亚洲精品久久久| 亚洲精品国产精品| 成人免费无毒在线观看网站| 亚洲国产精品乱码在线观看97| 午夜爽爽爽男女免费观看影院| 伊人久久大香线蕉亚洲五月天 | 亚洲专区在线视频| 中国一级毛片视频免费看| 国产L精品国产亚洲区久久| 男女啪啪免费体验区| 免费v片视频在线观看视频| 精品国产亚洲一区二区三区在线观看| 在线观看成人免费| 亚洲人成人伊人成综合网无码| 国色精品卡一卡2卡3卡4卡免费| 亚洲成a人片在线网站| 222www在线观看免费| 337p欧洲亚洲大胆艺术| 91成人在线免费观看| 久久亚洲AV无码精品色午夜麻豆| 亚洲免费在线视频| 精品日韩亚洲AV无码一区二区三区| 色欲A∨无码蜜臀AV免费播| 久久精品国产精品亚洲艾草网| 美女在线视频观看影院免费天天看 | 无码av免费网站| 亚洲视频免费一区| 亚洲人成在线免费观看| 91亚洲精品自在在线观看| 成人福利免费视频| 亚洲砖码砖专无区2023| 日本人的色道www免费一区| 精品成人一区二区三区免费视频| 免费永久在线观看黄网站| 五月天婷婷免费视频| 亚洲日韩小电影在线观看| 亚欧免费无码aⅴ在线观看| 久久精品国产亚洲AV嫖农村妇女|