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

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

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

    隨筆-19  評論-128  文章-1  trackbacks-0
      2010年7月12日
         摘要: 一、分布式實現原理               如上圖所示,主要通過Apache-Server作為中轉服務器,實現多個tomcat服務器之間的分布式處理,用戶直接請求Apache-Server,然后Apache-Server會將請求分發到具體的tomcat-server,之...  閱讀全文
    posted @ 2011-06-22 16:09 obpm 閱讀(8213) | 評論 (4)編輯 收藏
    從設計理念層面看abstract class和interface

    上面主要從語法定義和編程的角度論述了abstract class和interface的區別,這些層面的區別是比較低層次的、非本質的。本小節將從另一個層面:abstract class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。

    前面已經提到過,abstarct class在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"is a"關系,即父類和派生類在概念本質上應該是相同的(參考文獻〔3〕中有關于"is a"關系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface 來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的,僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。

    考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:

    使用abstract class方式定義Door:

    abstract class Door {
    abstract void open();
    abstract void close();
    }


    使用interface方式定義Door:


    interface Door {
    void open();
    void close();
    }


    其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區別。

    如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中,主要是為了展示abstract class和interface反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)?下面將羅列出可能的解決方案,并從設計理念層面對這些不同的方案進行分析。

    解決方案一:

    簡單的在Door的定義中增加一個alarm方法,如下:

    abstract class Door {
    abstract void open();
    abstract void close();
    abstract void alarm();
    }


    或者

    interface Door {
    void open();
    void close();
    void alarm();
    }


    那么具有報警功能的AlarmDoor的定義方式如下:

    class AlarmDoor extends Door {
    void open() { … }
    void close() { … }
    void alarm() { … }
    }


    或者

    class AlarmDoor implements Door {
    void open() { … }
    void close() { … }
    void alarm() { … }


    這種方法違反了面向對象設計中的一個核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。

    解決方案二:

    既然open、close和alarm屬于兩個不同的概念,根據ISP原則應該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract class方式定義,另一個概念使用interface方式定義。

    顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理。我們一一來分析、說明。

    如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器?2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。

    如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,abstract class在Java語言中表示一種繼承關系,而繼承關系在本質上是"is a"關系。所以對于Door這個概念,我們應該使用abstarct class方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:

    abstract class Door {
    abstract void open();
    abstract void close();
    }
    interface Alarm {
    void alarm();
    }
    class AlarmDoor extends Door implements Alarm {
    void open() { … }
    void close() { … }
    void alarm() { … }
    }


    這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計意圖。其實abstract class表示的是"is a"關系,interface表示的是"like a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。

    轉載人員-Nicholas
    posted @ 2010-11-07 13:57 obpm 閱讀(574) | 評論 (4)編輯 收藏
    可關閉的TabbedPane結構:


    測試代碼:

    package cn.demo.test;

    import java.awt.Component;

    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.UIManager;

    /**
     * Test
     * 
    @author Tom
     *
     
    */
    public class TestDemo {

        
    public static void main(String[] args) {
            
    try {
                String feel 
    = UIManager.getSystemLookAndFeelClassName();
                UIManager.setLookAndFeel(feel);
            } 
    catch (Exception e) {
                e.printStackTrace();
            } 
            
            JFrame frame 
    = new JFrame();
            frame.setTitle(
    "可關閉Tab測試");
            frame.setSize(
    300400);
            frame.setLocationRelativeTo(
    null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            TabbedPane tabbedPane 
    = new TabbedPane();
            tabbedPane.setCloseButtonEnabled(
    true);
            tabbedPane.addTab(
    "測試一"nullnew JLabel("測試一"));
            tabbedPane.addTab(
    "測試二"nullnew JLabel("測試二"));
            tabbedPane.addTab(
    "測試三"nullnew JLabel("測試三"));
            tabbedPane.addTab(
    "測試四"nullnew JLabel("測試四"));
            tabbedPane.addTabbedPaneListener(
    new TabbedPaneListener(){
                @Override
                
    public void allTabsRemoved() {
                    
    // TODO Auto-generated method stub
                    
                }
                @Override
                
    public boolean canTabClose(Tab tab, Component component) {
                    
    // TODO Auto-generated method stub
                    return false;
                }
                @Override
                
    public void tabAdded(Tab tab, Component component, int index) {
                    
    // TODO Auto-generated method stub
                    
                }
                @Override
                
    public void tabRemoved(Tab tab, Component component, int index) {
                    
    // TODO Auto-generated method stub
                    System.out.println("close");
                }
                @Override
                
    public void tabSelected(Tab tab, Component component, int index) {
                    
    // TODO Auto-generated method stub
                    
                }
            });
            
            frame.add(tabbedPane);
            frame.setVisible(
    true);
        }
        
    }

     測試效果:

         

    源碼下載:TabbedPane.rar

    發表人: Tom


    posted @ 2010-10-24 16:44 obpm 閱讀(6136) | 評論 (2)編輯 收藏

    在數據庫層使用SQL分頁可以很大程度增加平臺系統程序運行速度與效率。本人只是初入手半數據庫半程序的開發,所以對數據庫研究不深。于是要收集下列代碼以作參考,同時也Post出來可以讓需要的人參考一下,高手就請見笑了。說轉載說不上,說原創也... 國慶期間在家家里的機子跑DB比較困難,做不了過多測試。不過語句或函數方面本人都仔細看過抄回來的SQL的網頁里示例,感覺基本上大同小異,如果有錯誤查下做相應的修改或百度Google一下應該沒什么大問題,也請多多包涵。當然,有機會就會對下列SQL做測試,然后會進行修正。至于每個數據庫分頁在這就不進行深究,只是列出個可用的方法。

    ##########
    # MySQL#
    ##########

    select * from tlk_buginfo limit startPos, pageSize

    startPos: 定義當前頁起始位置(不包括startPos)
    pageSize: 每頁顯示數據的條數

    ##########
    # MSSQL#(2005的row_number,暫無2000)
    ##########

    1、
    --返回第20-40行數據
    select top 20 * from (select row_number() over (order by EmployeeID) as RowNumber, * from HumanResources.Employee) TableNickname where RowNumber>=20

    2、
    --返回第20-40行數據
    select * from (select row_number() over (order by EmployeeID) as RowNumber, * from HumanResources.Employee) TableNickname where RowNumber between 20 and 40

    3、
    --返回第20-40行數據
    with OrderedResults as
    (select *, ROW_NUMBER() OVER (order by EmployeeID) as RowNumber FROM HumanResources.Employee)
    select * from OrderedResults where RowNumber between 20 and 40

    ##########
    # Oracle#
    ##########

    ①采用rownum關鍵字(三層嵌套)
    --返回第5-15行數據
    select * from (select row_.*, rownum num from (select * from tlk_buginfo) row_ where rownum<=15) where num>=5

    ②采用row_number解析函數進行分頁(效率更高)
    --返回第5-15行數據
    select tab.* from (select t.*, row_number() over (order by lastmodified) as num from tlk_buginfo t) tab where num between 5 and 15

    ##########
    # DB2#
    ##########

    select * from (select *, rownumber() over(order by 排序字段 asc ) as rowid  from 表名 )as a where a.rowid >= startPage AND a.rowid <endPage

    ##########
    # Hsqldb#
    ##########

    select LIMIT 0 10 表名


    收集資料:(allen)
    posted @ 2010-10-10 21:32 obpm 閱讀(396) | 評論 (1)編輯 收藏
    jbpm4.3API(chn)下載
    (denny)
    posted @ 2010-10-08 00:11 obpm 閱讀(1465) | 評論 (1)編輯 收藏
    HTML5 是近十年來 Web 標準最巨大的飛躍。和以前的版本不同,HTML 5 并非僅僅用來表示 Web 內容,它的使命是將 Web 帶入一個成熟的應用平臺,在這個平臺上,視頻,音頻,圖象,動畫,以及同電腦的交互都被標準化。盡管 HTML 5 的實現還有很長的路要走,但 HTML 5 正在改變 Web。
    HTML 最近的一次升級是1999年12月發布的 HTML 4.01。自那以后,發生了很多事。最初的瀏覽器戰爭已經結束,Netscape 灰飛煙滅,IE5 作為贏家后來又發展到 IE6, IE7到IE8。Mozilla Firefox 從 Netscape 的死灰中誕生,并躍居第二位。蘋果和 Google 各自推出自己的瀏覽器,而小家碧玉的 Opera 仍然嚶嚶嗡嗡地活著,并以推動 Web 標準為己命。我們甚至在手機和游戲機上有了真正的 Web 體驗,感謝 Opera,iPhone 以及 Google 已經推出的 Android。
    然而這一切,僅僅讓 Web 標準運動變得更加混亂,HTML 5 和其它標準被束之高閣,結果,HTML 5 一直以來都是以草案的面目示人。
    于是,一些公司聯合起來,成立了一個叫做 Web Hypertext Application Technology Working Group (Web 超文本應用技術工作組 - WHATWG) 的組織,他們將重新揀起 HTML 5。這個組織獨立于 W3C,成員來自 Mozilla, KHTML/Webkit 項目組,Google,Apple,Opera 以及微軟。盡管 HTML 5 草案不會在短期內獲得認可,但 HTML 5 總算得以延續。
    HTML 5 將帶來什么?以下是 HTML 5 草案中最激動人心的部分:
    全新的,更合理的 Tag,多媒體對象將不再全部綁定在 object 或 embed Tag 中,而是視頻有視頻的 Tag,音頻有音頻的 Tag。本地數據庫。這個功能將內嵌一個本地的 SQL 數據庫,以加速交互式搜索,緩存以及索引功能。同時,那些離線 Web 程序也將因此獲益匪淺。不需要插件的富動畫。Canvas 對象將給瀏覽器帶來直接在上面繪制矢量圖的能力,這意味著我們可以脫離 Flash 和 Silverlight,直接在瀏覽器中顯示圖形或動畫。一些最新的瀏覽器,除了 IE,已經開始支持 Canvas。瀏覽器中的真正程序。將提供 API 實現瀏覽器內的編輯,拖放,以及各種圖形用戶界面的能力。內容修飾 Tag 將被剔除,而使用 CSS。理論上講,HTML 5 是培育新 Web 標準的土壤,讓各種設想在他的組織者之間分享,但 HTML 5 目前仍處于試驗階段。
    Mozilla 的技術副總裁 Mike Shaver 說,HTML 5 是一個被寄予厚望的概念,它既是 WHATWG 組織的實驗田,又是 W3C 的標準之路。
    Shaver 認為,Mozilla 的興趣和 WHATWG 實驗相吻合,Mozilla 在 HTML 5 工作組中非常活躍,我們對一些早期的細則進行實驗并將成熟的結果提交 W3C。
    在過去的幾年,Mozilla 隨著各種出現的新標準,推出多個富有前瞻性的項目,包括 Prism,一個用于離線運行 Web 程序的系統,以及 Weave,一個數據存儲框架。
    Shaver 說,HTML 5 運動肇始于對 W3C 的不耐煩,Web 標準中的很多進展都因 W3C 將重點從 HTML 轉移到 XML 而停滯不前。
    很多基于 XML 架構的新技術被設計出來替代 HTML,Shaver 說,這不是一條正確的道路,人們不應象黑瞎子掰玉米把樣一邊掰一邊丟。
    HTML 5 的新實驗在 Firefox 以及 基于 Webkit 的 Safari 和 Chrome 瀏覽器中逐漸得到強化,但仍有不少問題。
    Chrome 的開發者 Darin Fisher 說,Chrome 仍在襁褓中時,就不得不面臨幾個問題,盡管使用的是最新的 Webkit,HTML 5 的本地數據庫功能在 Chrome 的初期版本中并沒有實現。因為 Chrome 的沙箱機制和 Webkit 的數據庫功能有沖突。
    而由于 Chrome 屬于秘密開發,Chrome 的開發人員也不便參與 Webkit 的開發。
    我們要想保守 Chrome 的秘密,就無法參與 Webkit 社區。Fisher 說,我們很希望可以在某些方面給 Webkit 以幫助,我們擁有眾多經驗豐富的開發者,我們很想知道人們目前遇到的挑戰并樂意提供幫助。
    隨著 Chrome 的發布,Fisher 說他的團隊成員有時會和 Webkit 的人一起吃飯,有些人私下里還成了好朋友。Fisher 稱,他們迫切地想同其他 Webkit 開發組一起工作解決離線數據庫的問題。
    Chrome 里面還包含Google 的開源 Gears 技術,用來實現與 HTML 5 類似的離線功能。
    Gears 可以看作已有 API 的替代品,Fisher 說,HTML 5 對新瀏覽器來說是非常好的東西,但絕大多數用戶還使用舊瀏覽器。Gears 可以讓那些舊瀏覽器也獲得這樣的 API,我們正在為 HTML 5 版 API 提供兼容。
    Gears 兼容性非常好,它正成為將 HTML 5 帶向人們桌面的另外一條途徑。
    目前,絕大多數工作由 Apple,Mozilla, Opera, Google 以及 Trolltech 展開。微軟在干什么?IE 因其對 Web 標準的遲鈍而聞名,更不要說 HTML 5。但 IE8 可能會做出改變。
    微軟 IE 平臺與 WHAT 工作組主席 Chris Wilson 在郵件中稱,我們希望我們現在開始的工作可以在 HTML 工作組創建一套測試系統。Wilson 說,IE 開發組仍然對 HTML 5 的一些提議感到擔憂。我覺得工作組的所有成員都會承認我們還有很多事要做。
    目前處于 Beta 版的 IE9,已經包含 HTML 5 的諸多新功能。它擁有一個跨文檔消息系統,本地存儲,以及一些離線事件來檢測網絡的中斷。但還有些功能還未提上議程,如 Canvas。
    HTML 5 非常龐大,仍處在開發階段,我認為瀏覽器廠商應當盡快達成一致,而每個瀏覽器的具體實現時間可以自己選擇。Web 開發者和瀏覽器廠商會同意 Wilson 的下面這句話,這確切無疑是一個激動人心的時刻,我們希望看到 Web 成為新的應用平臺。
    HTML5寫的例子(IE9或google瀏覽器才有效果):
     
    Google Gravity
    http://mrdoob.com/projects/chromeexperiments/google_gravity/
    BallDropping
    http://balldroppings.com/js/
    Animated Harmonograph
    http://hernan.amiune.com/labs/harmonograph/animated-harmonograph.html
    Canopy
    http://onecm.com/projects/canopy/
    Ball Pool
    http://mrdoob.com/projects/chromeexperiments/ball_pool/
    Browser Ball
    http://experiments.instrum3nt.com/markmahoney/ball/parent.html
    Wavy Scrollbars
    http://the389.com/experiment/
    Twitch
    http://reas.com/twitch/window0.html
    Colorscube
    http://www.canvasdemos.com/2009/04/03/colorscube/
    InterNetris
    http://internetris.net/
    CanvasPaint
    http://canvaspaint.org/
    HTML5學習資料:
    http://www.chinabyte.com/bang/html5/
    收集資料:(denny)
    posted @ 2010-10-07 21:46 obpm 閱讀(2112) | 評論 (1)編輯 收藏
    首先,在jbpm4中,流程定義相關的部署信息就存在JBPM4_DEPLOYMENTJBPM4_DEPLOYPROPJBPM4_LOB (存放當發布一個png和xml文件后的流程定義后的記錄)。中。

    JBPM4_HIST_PROCINSTJBPM4_HIST_ACTINST兩張表中,分別存放的是process Instance、Activity Instance的歷史記錄,Activity Instance是指流程定義中各個步驟:task descition等存放Process Instance、Activity Instance歷史記錄的表有了,那他們的當前記錄存在什么地方呢?這就需要弄清楚jBPM的另外幾個概念。一般而言,在jBPM中,“a process instance is the root of a tree of executions”。因此,當一個流程實例Split出兩個并行步驟的時候,在JBPM4_EXECUTION表中將有三筆相關記錄,一筆是代表流程實例的Root Execution,另外兩筆是關于上述兩個并行步驟的Child Execution。

    此外,在jbpm中,Activity的種類是很豐富的,可以是Control Flow Activities,如sub-process,decision等,也可以是Automatic Activity,如java、script、sql等,其中需要人來參與完成的Activity被稱為Task,待辦任務放在JBPM4_TASK表中,而歷史任務放在JBPM4_HIST_TASK表中。

    對一個Task而言,它可能會有多個Participation(swim lane 同樣會有多個Participation),Participation的種類有Candidate、client、owner、Replaced Assignee和viewer,而具體的Participation既可以是單一用戶,也可以是用戶組,Participation的信息存放在JBPM4_PARTICIPATION中。

    Swim Lane是一種Runtime Process Role,通過Swim Lane,多個Task可以一次分配到同一Actor身上,存放這些信息是表JBPM4_PARTICIPATION

    JBPM4_ID_GROUPJBPM4_ID_MEMBERSHIPJBPM4_ID_USER這是基本的權限控制,建議關于用戶認證方面還是自己開發一套,這個功能太簡單了,難以滿足需求。

    JBPM4_JOB存放的是Timer的定義。

    JBPM4_PROPERTY這是jbpm引擎參數表。

    JBPM4_VAR表存放流程臨時變量,當流程實例結束后,表中內容清除。

    JBPM4_HIST_VAR表存放歷史臨時變量,但是jbpm4好像還沒有對這張表進行利用。

    JBPM4_HIST_DETAIL表保存變量變更記錄。



    了解jbpm4.3以上這18張表后,我們應該在流程運行中,詳細觀察jbpm是如何對這些表進行操作,以及進行什么樣的操作的。

    發布一個流程定義后:

    JBPM4_DEPLOYMENT新增一條記錄

    JBPM4_DEPLOYPROP新增三條記錄

    JBPM4_LOB新增兩條記錄



    開始一個流程startProcessInstanceByKey后:

    JBPM4_EXECUTION新增一條記錄

    JBPM4_TASK新增一條記錄

    JBPM4_HIST_PROCINSTJBPM4_HIST_ACTINST分別新增一條記錄

    JBPM4_HIST_TASK新增一條記錄



    當執行taskService.setVariables(task.getId(), map);時,JBPM4_VARIABLES中添加變量記錄
     
    轉載人員:Nicholas
    posted @ 2010-09-16 19:51 obpm 閱讀(1264) | 評論 (0)編輯 收藏

    權限分析文檔

    基于RBAC的權限設計模型:

    1 RBAC 介紹

    RBAC 模型作為目前最為廣泛接受的權限模型。

    NIST (The National Institute of Standards and Technology,美國國家標準與技術研究院)標準RBAC模型由4個部件模型組成,這4個部件模型分別是基本模型RBAC0(Core RBAC)、角色分級模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和統一模型RBAC3(Combines RBAC)[1]。RBAC0模型如圖1所示。

    clip_image001.jpg
    圖表 1 RBAC 0 模型

    l RBAC0 定義了能構成一個RBAC控制系統的最小的元素集合

    在RBAC之中,包含用戶users(USERS)、角色roles(ROLES)、目標objects(OBS)、操作operations(OPS)、許可權permissions(PRMS)五個基本數據元素,權限被賦予角色,而不是用戶,當一個角色被指定給一個用戶時,此用戶就擁有了該角色所包含的權限。會話sessions是用戶與激活的角色集合之間的映射。RBAC0與傳統訪問控制的差別在于增加一層間接性帶來了靈活性,RBAC1、RBAC2、RBAC3都是先后在RBAC0上的擴展。

    l RBAC1 引入角色間的繼承關系

    角色間的繼承關系可分為一般繼承關系和受限繼承關系。一般繼承關系僅要求角色繼承關系是一個絕對偏序關系,允許角色間的多繼承。而受限繼承關系則進一步要求角色繼承關系是一個樹結構。

    l RBAC2 模型中添加了責任分離關系

    RBAC2 的約束規定了權限被賦予角色時,或角色被賦予用戶時,以及當用戶在某一時刻激活一個角色時所應遵循的強制性規則。責任分離包括靜態責任分離和動態責任分離。約束與用戶-角色-權限關系一起決定了RBAC2模型中用戶的訪問許可。

    l RBAC3 包含了RBAC1和RBAC2

    既提供了角色間的繼承關系,又提供了責任分離關系。

    建立角色定義表。定出當前系統中角色。

    因為有繼承的問題,所以角色體現出的是一個樹形結構。

    test.bmp

    2 權限設計:

    配置資源以及資源的操作 : 這里資源可以定義為一個通用的資源模型。提供通用的資源統一接口。

    數據庫 ER 圖:

    clip_image002.gif

    關系圖:

    clip_image003.gif

    未命名.bmp

    3 分析:

    根據以上的類關系圖和ER圖可以看出。整個權限可以抽象為五個對象組成。

    OrgBean : 用于描述org模型。

    Role : 用于描述角色。

    Permission : 用于描述權限。

    Resource : 用于描述資源。

    Operation : 用于描述操作。

    其中Permission中有Resource , Operation 的聚合,資源和操作組成權限。

    Role 和 Permission 都有自包含。因為設計到權限的繼承。

    資源Resource 也可能出現一顆樹形結構,那資源也要有自包含。

    思想 :

    權限系統的核心由以下三部分構成: 1. 創造權限, 2. 分配權限, 3. 使用權限,然后,系統各部分的主要參與者對照如下: 1. 創造權限 -Creator 創造, 2. 分配權限 - Administrator 分配, 3. 使用權限 - User :

    1. Creator 創造 Privilege , Creator 在設計和實現系統時會劃分,一個子系統或稱為模塊,應該有哪些權限。這里完成的是 Privilege 與Resource 的對象聲明,并沒有真正將 Privilege 與具體 Resource 實例聯系在一起,形成 Operator 。

    2. Administrator 指定 Privilege 與 Resource Instance 的關聯 。在這一步, 權限真正與資源實例聯系到了一起, 產生了 Operator (Privilege Instance )。 Administrator 利用 Operator 這個基本元素,來創造他理想中的權限模型。如,創建角色,創建用戶組,給用戶組分配用戶,將用戶組與角色關聯等等 ... 這些操作都是由 Administrator 來完成的。

    3. User 使用 Administrator 分配給的權限去使用各個子系統。 Administrator 是用戶,在他的心目中有一個比較適合他管理和維護的權限模型。于是,程序員只要回答一個問題,就是什么權限可以訪問什么資源,也就是前面說的 Operator 。程序員提供 Operator 就意味著給系統穿上了盔甲。 Administrator 就可以按照他的意愿來建立他所希望的權限框架 可以自行增加,刪除,管理 Resource 和 Privilege 之間關系。可以自行設定用戶 User 和角色 Role 的對應關系。 ( 如果將 Creator 看作是 Basic 的發明者, Administrator 就是 Basic 的使用者,他可以做一些腳本式的編程 ) Operator 是這個系統中最關鍵的部分,它是一個紐帶,一個系在 Programmer , Administrator , User 之間的紐帶。

    4 權限API

    getPermissionByOrgGuid(String orgGuid )

    通過傳入一個org的Guid , 拿到當前這個org對象都具有那些訪問權限。

    getSourcePermissionByOrgGuid(String orgGuid , String resouceGuid)

    通過傳入一個org的Guid 和 一個資源的Guid , 返回改Org對當前這個資源的訪問權限。

    getPermissionByResourceGuid(String resource)

    通過傳入一個資源的Guid , 得到當前資源下都有那些權限定義。

    havingHeritPermission(String orgGuid , String resouceGuid) : Boolean

    傳入一個orgGuid, 資源GUID ,查看改OrgGuid下對資源是否有向下繼承的權限。這里繼承是資源的繼承。即對父欄目有權限,可以繼承下去對父欄目下的子欄目同樣有權限。

    havingPermission(String orgGuid , String resourceGuid) : Boolean

    判斷某Org對某一資源是否用權限。

    以上是粗粒度的權限API 。 以下為細粒度的權限:

    getOperationByPermission(String permissionGuid)

    通過permission 的Guid 得到該permission 的所有有效操作。

    getOperationByGuid(String permissionGuid , String resourceGuid)

    通過permision的Guid , 資源的Guid 得到該資源下所有的有效操作。

    screeningOpreationByGuid (String permissionGuid , String resourceGuid , String orgGuid)

    通過permission , resource , org的Guid 得到改Org對這一資源的有效操作。

    hasOperation(String operationGuid) : boolean

    通過傳入的operationGuid 返回是否具有操作權限。

    5 權限的實現:

    1 .表單式認證,這是常用的,但用戶到達一個不被授權訪問的資源時, Web 容器就發

    出一個 html 頁面,要求輸入用戶名和密碼。

    2 .用 Filter 防止用戶訪問一些未被授權的資源, Filter 會截取所有 Request/Response ,

    然后放置一個驗證通過的標識在用戶的 Session 中,然后 Filter 每次依靠這個標識來決定是否放行 Response 。

    這個模式分為:

    Gatekeeper :采取 Filter 或統一 Servlet 的方式。

    Authenticator : 在 Web 中使用 JAAS 自己來實現。

    Filter 攔截只是攔截該用戶是否有訪問這個頁面,或這一資源的權限。真正做到顯示后攔截是在應用程序內部去做。

    做顯示攔截提供API , 標簽這兩種方式

     

    轉載人員:Happy

    原文地址 http://blog.csdn.net/huanghanzzz2006/archive/2006/12/04/1429666.aspx

    posted @ 2010-09-14 13:30 obpm 閱讀(940) | 評論 (0)編輯 收藏

    flex4幫助文檔大小有34M(網頁版),上傳不了。需要該文檔的,請留下你的郵箱地址。
    115共享地址:
    http://u.115.com/file/f8c22d4e48
    flex4api.zip   提取碼:f8c22d4e48


    原創人員:denny

    posted @ 2010-09-03 08:50 obpm 閱讀(4601) | 評論 (104)編輯 收藏
    圖片剪切功能:

    效果圖:






    flex代碼:

     

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()" xmlns:local="astion.*">
     
    <mx:Script>
      
    <![CDATA[
       import mx.controls.Image;
       import mx.graphics.ImageSnapshot;
       import flash.net.FileReference;
       import mx.graphics.codec.JPEGEncoder;
       import mx.managers.PopUpManager;
       import mx.containers.TitleWindow;
       import mx.controls.Alert;
       import mx.events.CloseEvent;
       import mx.core.IFlexDisplayObject;
       import mx.utils.*;
       import mx.core.Application;
       import astion.Dot;
       import astion.ScaleBox;
       
       public static const LINE_WIDTH:Number = 1;//縮放邊框寬度
       private var file:FileReference;
       public var IMAGE_URL:String="http://localhost:8080/cutPicuter/aa/aa.jpg";
       private var loader:Loader;
       private var bmp:Bitmap;
                private var stream:URLStream;
                public var realPath:String="D:\myWorkSpace\cutPicuter\WebRoot\aa\aa.jpg";
       
       //初始化數據
       private function init():void{
        this.loader = new Loader();
                    this.stream = new URLStream();
                    this.loader.contentLoaderInfo.addEventListener(Event.COMPLETE,this.onComplete);
                    this.loader.load(new URLRequest(encodeURI(this.IMAGE_URL)));//解決中文亂碼
                    this.stream.load(new URLRequest(encodeURI(this.IMAGE_URL)));
                    this.stream.addEventListener(Event.COMPLETE,this.onLoaded);
       }
       private function onLoaded(e:Event):void
                {                                
                    var bytearray:ByteArray = new ByteArray();    
                    this.stream.readBytes(bytearray);
                    
                    if(this.stream.connected)
                        this.stream.close();
                        
                    this.loader.loadBytes(bytearray);
                }
                private function onComplete(e:Event):void
                {
                    try
                    {
                        this.bmp = this.loader.content as Bitmap;
                        var showImage:Image= new Image();
                        showImage.source=this.loader.content;
                        canvas.addChild(showImage);
                        canvas.setChildIndex(box,1);
                        canvas.setChildIndex(showImage,0);
                    }
                    catch(e:Error)
                    {
                        
                    }
                }
       
       //截圖,顯示縮放選擇框
       private function doCapture():void{
        box.x = 100;
        box.y = 100;
        box.visible = true;
       }
       
       //獲取縮放選擇框內的圖像
       private function getImg():BitmapData{
        //截取整個區域
        box.scaleEnable = false;
        var bmp:BitmapData = ImageSnapshot.captureBitmapData(canvas);
        box.scaleEnable = true;
        
        //矩形為要截取區域                
                    var re:Rectangle = new Rectangle(box.x+LINE_WIDTH,box.y+LINE_WIDTH,box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH); 
                    var bytearray:ByteArray = new ByteArray();   
                    //截取出所選區域的像素集合                        
                    bytearray = bmp.getPixels(re); 
                    
                    
                    var imgBD:BitmapData = new BitmapData(box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH);       
                    //當前的bytearray.position為最大長度,要設為從0開始讀取       
                    bytearray.position=0;            
                    var fillre:Rectangle = new Rectangle(0,0,box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH);
                    //將截取出的像素集合存在新的bitmapdata里,大小和截取區域一樣
                    imgBD.setPixels(fillre,bytearray);
                    
                    return imgBD;
       }
       
       //預覽圖片
       private function doScan():void{
        var t:TitleWindow = new TitleWindow();
        t.showCloseButton=true;
        t.addEventListener(CloseEvent.CLOSE,closeWindow);
        t.width = box.boxWidth+t.getStyle("borderThickness");
        t.height =box.boxHeight+t.getStyle("borderThickness")+t.getStyle("headerHeight");
        var img:Image = new Image();
        img.width = box.boxWidth;
        img.height = box.boxHeight; 
        img.source = new Bitmap(getImg());
        t.addChild(img);
        PopUpManager.addPopUp(t,this,true);
        PopUpManager.centerPopUp(t);
       }
       
       private function closeWindow(e:CloseEvent):void{            
                    var t:TitleWindow = e.currentTarget as TitleWindow;                    
                    PopUpManager.removePopUp(t);                
                }
                
                //保存圖片到本地
       private function downloadPicture():void{
        file=new FileReference();
        file.addEventListener(Event.COMPLETE,downloadComplete);
        file.save(new JPEGEncoder(80).encode(getImg()),"default.jpg");
       }
       
       private function downloadComplete(event:Event):void{
        Alert.show("成功保存圖片到本地!","提示");
       }
       
       //保存圖片到服務器即覆蓋原來的圖片
       private function save():void{
        Alert.show("是否保存剪切圖片?","提示",3, this, function(event:CloseEvent):void {
              if (event.detail==Alert.YES){
               var request:URLRequest = new URLRequest("http://localhost:8080/cutPicuter/servlet/FileManagerSaveFileServlet?realPath="+encodeURIComponent(StringUtil.trim(realPath)));
         request.method=URLRequestMethod.POST;
         request.contentType = "application/octet-stream";
         request.data = new JPEGEncoder(80).encode(getImg());
         var loader:URLLoader = new URLLoader();
         loader.load(request);
         loader.addEventListener(Event.COMPLETE,saveResult);

              }});
       }
       
       private function saveResult(event:Event):void{
        Application.application.reLoadFolderFiles(realPath.substr(0,realPath.lastIndexOf("\\")));
        Alert.show("保存剪切圖片成功","提示");
       }
      
    ]]>
     
    </mx:Script>
     
    <mx:HBox x="0" y="0">
            
    <mx:LinkButton label="剪裁" click="doCapture();" icon="@Embed('assets/cut.png')"/>
            
    <mx:LinkButton label="預覽" click="doScan();" icon="@Embed('assets/ok.png')"/>
            
    <mx:VRule height="22"/>
            
    <mx:LinkButton label="保存"  click="save()"  icon="@Embed('assets/save.png')"/>
            
    <mx:LinkButton label="另存為" click="downloadPicture();" icon="@Embed('assets/saveAs.png')"/>
        
    </mx:HBox>
     
    <mx:Canvas id="canvas" y="23" x="1">
     
    <local:ScaleBox id="box" visible="false" y="0" x="0" width="100" height="100"/>
     
    </mx:Canvas>
    </mx:Application>



    java代碼:

     

    package com;


    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    /**
     * Servlet implementation class FileManagerSaveFileServlet
     
    */
    public class FileManagerSaveFileServlet extends HttpServlet {
     
     
    private int len=0;//處理流
     private int mm=0;//重命名
     private String fileName="";//文件原名
     private String extName="";//文件擴展名
     private String tempFileName="";//文件名加擴展名
     
     
    public void doGet(HttpServletRequest request, HttpServletResponse response)    
     
    throws ServletException, IOException {    
     processRequest(request, response);    
     }    
       
     
    public void doPost(HttpServletRequest request, HttpServletResponse response)    
      
    throws ServletException, IOException {    
     processRequest(request, response);    
     }    
     
     
    public void processRequest(HttpServletRequest request, HttpServletResponse response)

        
    throws ServletException, IOException {
      request.setCharacterEncoding(
    "utf-8");
      String realPath
    =request.getParameter("realPath");
      
    //System.out.println("FMSFS-->realPath:"+realPath);
      response.setContentType("application/octet-stream");
      InputStream is 
    = request.getInputStream();
      
    try {
      
    int size = 0;
      
    byte[] tmp = new byte[100000];
      
      tempFileName
    =realPath.substring(realPath.lastIndexOf("\\")+1);//切割獲得文件名加擴展名
      fileName=tempFileName.substring(0,tempFileName.lastIndexOf("."));//切割獲得文件名
      
    //確保獲得真實的文件名如:1(1)可以獲得真實為1,
      if(fileName.indexOf("(")!=-1){
       fileName
    =fileName.substring(0,fileName.indexOf("("));
      }
      
      extName
    =tempFileName.substring(tempFileName.lastIndexOf("."));//切割獲得擴展名
      
      
    //調用遞歸方法
      fileName+=reNameFile(realPath.substring(0,realPath.lastIndexOf("\\")+1),fileName,extName);
      
    // 創建一個文件夾用來保存發過來的圖片;
      File f = new File(realPath.substring(0,realPath.lastIndexOf("\\")+1)+fileName+extName);
      DataOutputStream dos 
    = new DataOutputStream(new FileOutputStream(f));
      
    while ((len = is.read(tmp)) != -1) {
      dos.write(tmp, 
    0, len);
      size 
    += len;
      }
      dos.flush();
      dos.close();
      } 
    catch (IOException e) {
      e.printStackTrace();
      }
     }
     
     
    //遞歸來重命名文件名
     String str="";
     
    public String reNameFile(String realPath,String filename,String extName){
      File file 
    =new File(realPath+"\\"+filename+extName);
      str
    ="";
            
    if(file.exists()){
             mm
    ++;
             str
    ="_"+mm;
             reNameFile(realPath,fileName
    +str,extName);
            }
    else{
             
    if(mm!=0){
          str
    ="_"+mm;
             }
            }
      
    return str;
     }
    }

     


     

    源碼: flex圖片剪切示例


    原創人員:Denny

    posted @ 2010-09-01 09:55 obpm 閱讀(8607) | 評論 (6)編輯 收藏

    James Gosling : Java之父
    文/陶文

    作為Java之父,James Gosling的名字可謂是耳熟能詳。當人們評論一種編程語言時,總喜歡捎帶著把下蛋的母雞一起帶上。Java做為中國的編程語言學習者餐桌上有限的那么幾樣餐點中的流行款式,自然是讓James Gosling風光不已。雖然James Gosling現在已經不是領導Java發展潮流的領軍人物了,做為Sun的開發者產品組的CTO,怎么算來也是身居高位了,俗事纏身吧,但是這并不妨礙其對于Java一如既往的愛護,表達著各式各樣鮮明的觀點,引發一場又一場的爭論。
    James Gosling是很愛Java的——是啊,哪有當父母的不愛自己的孩子的呢。James Gosling也是很愛Sun的——是啊,哪有當領導的不愛自己的公司的呢。于是我們在批評.NET的安全性的隊伍前頭,在褒揚Java性能的隊伍前頭,在抨擊SWT開倒車的隊伍前頭,在給NetBeans大唱贊歌的隊伍前頭,我們都看到了James Gosling的身影。無論對錯、偏見或者固執,至少說明了Gosling的鮮明個性絲毫沒有受到年齡的影響。也許也只有這種天才而偏執的人物才能創造出Java這般偉大的語言來吧。

    Bill Joy : 軟件業的愛迪生
    文/徐昊

    Joy生于1954年,1982年與Vinod Khosla, Scott McNealy和Andy Bechtolsheim一起創建了Sun Microsystems,并從那時起擔任首席科學家,直到2003年離開。他是一位令人崇敬的軟件天才,他在軟件和硬件的歷史上留下了無數令人仰止的傳奇。
    在上個世紀80年代早期,DARPA與BBN達成協議,準備將Vinton Cerf和Bob Kahn設計的TCP/IP協議添加到Berkeley UNIX中。Bill Joy被委派來完成這項任務,然而他卻拒絕將BBN的TCP/IP協議棧添加到BSD中,因為在他的眼中BBN的TCP/IP實現還遠不夠好,于是他就寫了一個高性能的TCP/IP協議棧。John Gage回憶道,“BBN和DARPA簽署了巨額合同來實現TCP/IP協議,然而他們的員工所編寫的代碼遠沒有一個研究生所做的好。于是他們邀請Bill Joy參加他們的一個會議,這位研究生穿著一件T-Shirt就出現了,他們詢問他,‘你是如何做到的呢?’Bill回答說,‘這是非常簡單的一件事,你讀一下協議然后就可以編碼了’”。除了TCP/IP協議,基于分頁的虛擬內存系統最早也是由Bill Joy添加到Berkeley UNIX內核當中的。同時他還是vi、csh、早期Pascal編譯器的作者。
    關于Bill Joy驚人的軟件才能流傳最廣的一個傳奇是,據說他在上研究生的時候,想看看自己能不能寫一個操作系統出來,于是就在三天里寫了一個非常簡陋,但是可以使用的Unix系統, 傳說就是BSD的前身。雖然如此夸張的才情令人難以置信,但是考慮到主角是Bill Joy,還是有一定的可信度的。Bill Joy碩士畢業之后,決定到工業界發展,于是就到了當時只有一間辦公室的Sun, 他作為主要設計者參與了SPARC微處理器的設計,負責設計最為關鍵的一部分電路。這樣兼精軟硬件的天才實在是讓人不得不佩服啊。1995年,Sun發布了轟動世界的Java語言。當然,Bill Joy對Java也作出了不少的貢獻,首先是JINI——一種針對分布式服務的基礎連接技術。任何可以內嵌JVM的電子設備都可以通過JINI相互連接;JXTA是基于Java的P2P協議,允許互聯網上的軟件進行點對點交流和協作。
    這個其貌不揚的瘦高個,有著凌亂的亞麻色頭發,被《財富》雜志譽為“網絡時代的愛迪生”的技術狂人,在短短的二十年間,創造了無數令人心動的軟件。在MIT的BBS上曾有一個帖子,說微軟電話面試有一道題,問“Who do you think is the best coder, and why?”雖然回復的帖子中大家都聲明列舉的best coder排名不分先后,然而大多數人仍把Bill Joy列在第一位,或許可以從一個側面驗證Bill Joy在廣大Programmer心目中的地位吧。

    Joshua Bloch : Java 2 元勛

    早在1996年,適逢Java剛剛嶄露頭角,年內好事連連。先是1月份發布JDK 1.0,然后是5月底在舊金山召開首屆JavaOne大會,年末又是JDK 1.1緊跟其后。正是在Java技術如火如荼、大展拳腳的背景之下,Joshua Bloch來到了Sun,開始了他帶領Java社區步入“迦南美地”的漫長歷程。
    很快,他被從安全組調入核心平臺組,從事底層API設計。至此以后,每逢JDK的重大版本發布,總能在其中見到Joshua的“妙筆”。JDK 1.1中的java.math、1.4中的assertions,還有大家所熟識的Collections Framework皆是Joshua一手打造。其中的Collections Framework還獲得了當年的Jolt大獎。到了J2SE 5.0研發階段,身為平臺組構架師的Joshua接掌了Tiger大旗,其核心地位已然無人可以替代。作為Tiger的代言人和領路人,沒有誰比Joshua更清楚Tiger。相信大家一定還記得Joshua當年仿效英國詩人William Blake所做的詠Tiger詩八首,優雅的筆調,透出大師深厚底蘊的同時,也道出了Tiger的幾大重要特性,這些特性是自JDK 1.1引入Inner Class以來,Java最大的語法改進。
    Java風雨十年,從JDK 1.1到J2SE 5.0,Joshua實在功不可沒。難怪有人戲言,假如將James Gosling比作Java之父,那么Joshua就是一手將Java “哺育”成人的Java之母。Joshua對Java的貢獻還不止于JDK,提起他的大作《Effective Java》(Addison Wesley, 2001),相信Java粉絲們一定耳熟能詳。該書榮膺2002年度Jolt大獎,且備受James Gosling推崇。書中57條頗具實用價值的經驗規則,來自Joshua多年來在JDK開發工作中,尤其是Collections Framework設計中的實踐心得,各個有理有據,剖析深入,也足見其深厚功力。該書對Java社群的影響,猶如C++社群中的《Effective C++》。Joshua對JCP的貢獻也不小。他是JSR201和JSR175的領導者,前者包含了Tiger四大語言特性,后者則為Java提供了元數據支持。此外,他還是JSR166的發起人之一(該JSR由Doug Lea領導),并且是許多其他JSR的參與者。Joshua目前是JCP為數不多的幾個執行委員會成員之一。
    Joshua Bloch給人的印象是謙遜平和,行事低調而不喜拋頭露面,一個典型的技術人員和實干家。不過即便如此,也絲毫不會減弱他對Java技術的卓越貢獻和對Java社區的絕對影響力。有人說,如果他能更彰顯一些,就很有可能成為Java開發者中的領軍人物,就有如Don Box之于微軟社群。
    2004年7月初,就在Tiger發布在即之時,就在Jusha Bloch剛剛榮獲Sun“杰出工程師(Distinguished Engineer)”的稱號之時,他突然離開Sun而去了正值發展態勢迅猛的Google。當他離開Sun的消息在TSS發布之后,眾多擁躉表達了懷念與不舍之情。一年過去了,我們還沒有獲知Joshua的任何近聞,似乎又是他行事低調的一貫作風所致,不知他在Google狀況如何。希望Joshua依然能繼續“摩西未盡的事業”,以他的影響力推動Java社群繼續前行。據稱,《Effective Java》的下一版會加入Java 5.0的部分,讓我們翹首以待吧。


    Bruce Eckel : 功勛卓著的機會主義分子

    Bruce Eckel原本是一位普通的匯編程序員。不知道是什么因緣際會,他轉行去寫計算機技術圖書,卻在此大紅大紫。他成功的秘訣不外乎兩點:超人的表達能力和捕捉機會的能力。他最早的一本書是1990年代初期的《C++ Inside & Out》,隨后,在1995年他寫出了改變自己命運的《Thinking in C++》。如果說這本書充分表現了他作為優秀技術作家的一面,那么隨后他寫作《Thinking in Java》并因此步入頂級技術作家行列,則體現了他作為優秀的機會主義分子善于捕捉機會的另一面。寫作中擅長舉淺顯直接的小例子來說明問題,語言生動,娓娓道來,特別適合于缺乏實踐經驗的初學者。因此《Thinking in Java》儼然成為天字第一號的Java教科書,對Java的普及與發展發揮著不可忽略的作用。不過公允地說,Bruce Eckel的書欠深刻。比如在“Thinking in…”系列中對設計模式的解說就有失大師水準。這一方面是因為書的定位非常清晰,另一方面也是因為Bruce太過分心趕潮流,未能深入之故。TIJ之后,他預言Python將火,就匆匆跑去寫了半本《Thinking in Python》。后來Python并未如期而旺,于是他也就把書稿撂在那里不過問了,機會主義的一面暴露無遺。我們也可以善意的猜測一下,他的下一個投機對象會是什么呢?Ruby?.NET?MDA?總之,是什么我都不奇怪。


    Rickard Oberg :J2EE奇才

    Oberg的作品很多,流行的代碼生成工具XDoclet和MVC框架WebWork都出自他的手筆。這兩個框架有一個共同的特點,即它們的功能雖然簡單,但設計都非常優雅靈活,能夠很方便地擴展新功能甚至移植到新環境下使用。優雅的設計源自Oberg的過人才華,簡單的功能則折射出他玩世不恭的人生態度。正是這兩種特質的融合,才造就了這個不世出的奇才。
    1999年,JDK 1.3發布,其中帶來了一個重要的新特性:動態代理(Dynamic Proxy)。當所有人都還在對這項新技術的用途感到迷惑時,Oberg發現用它便可以輕松攻克EJB容器實現中的一些難關。這一發現的產物就是一本《Mastering RMI》,以及大名鼎鼎的JBoss應用服務器。但Oberg很快又讓世人見識了他的玩世不恭。由于和總經理Marc Fleury在經營理念上不合,Oberg抱怨“法國的天空總讓我感到壓抑”,甩手離開了自己一手打造的JBoss。此后的幾年里,他和老友Hani Suleiman不斷地對JBoss的“專業開源”模式和Marc Fleury的商人味道冷嘲熱諷,讓眾人為他的孩子氣扼腕嘆息。
    2002年10月,微軟推出Petstore示例應用的.NET版本,并宣稱其性能比Java Petstore高出數倍。正是Oberg深入分析這個示例應用的源代碼,在第一時間指出它大量運用了SQL Server專有的特性,性能對比根本不具參考價值。后來Oberg又先后關注了AOP和IoC容器,兩者都成為了J2EE架構的新寵。

    Doug Lea : 世界上對Java影響力最大的個人
    文/KIT

    如果IT的歷史,是以人為主體串接起來的話,那么肯定少不了Doug Lea。這個鼻梁掛著眼鏡,留著德王威廉二世的胡子,臉上永遠掛著謙遜靦腆笑容,服務于紐約州立大學Oswego分校計算器科學系的老大爺。
    說他是這個世界上對Java影響力最大的個人,一點也不為過。因為兩次Java歷史上的大變革,他都間接或直接的扮演了舉足輕重的腳色。一次是由JDK 1.1到JDK 1.2,JDK1.2很重要的一項新創舉就是Collections,其Collection的概念可以說承襲自Doug Lea于1995年發布的第一個被廣泛應用的collections;一次是2004年所推出的Tiger。Tiger廣納了15項JSRs(Java Specification Requests)的語法及標準,其中一項便是JSR-166。JSR-166是來自于Doug編寫的util.concurrent包。
    值得一提的是: Doug Lea也是JCP (Java小區項目)中的一員。
    Doug是一個無私的人,他深知分享知識和分享蘋果是不一樣的,蘋果會越分越少,而自己的知識并不會因為給了別人就減少了,知識的分享更能激蕩出不一樣的火花。《Effective JAVA》這本Java經典之作的作者Joshua Blosh便在書中特別感謝Doug是此書中許多構想的共鳴板,感謝Doug大方分享豐富而又寶貴的知識。這位并發編程的大師級人物的下一步,將會帶給Java怎樣的沖擊,不禁令人屏息以待。

    Scott McNealy :SUN十年來的掌舵者
    文/KIT

    McNealy,Sun的CEO、總裁兼董事長。他曾經狂傲的說:“摧毀微軟是我們每個人的任務。”這位英勇的硅谷英雄,似乎帶頭起義,試圖組織一個反微軟陣線聯盟,以對抗微軟這股龐大的托拉斯惡勢力。他時常口出驚人之語,在公開場合大肆的批評微軟,并曾經說微軟的.NET是.NOT。
    Scott McNealy先后畢業于哈佛大學及史丹佛大學,分別持有經濟學學士學位及企管碩士。1982年MBA畢業的他和三個同學共同合伙創建了Sun,并于1984年成為Sun的執行官。“要么吞了別人,不然就被別人吞了”是Scott McNealy的名言錄之一。他擅長以信念帶動員工,鼓舞士氣。極富自信的他,對于認定的事,總是堅持自己的想法,因此有人形容他是一個剛愎自用的決策者。
    身為Sun這艘船的掌舵者,Scott McNealy能夠看多遠,Sun就能走多遠。Scott McNealy認為將來軟件界是一個只有服務,沒有產品的世代。他希望打造出Sun不是一個純靠硬件賺錢的公司。從Open Source到Open Solaris,Sun希望可以成為提供整合性解決方案的服務廠商。Solaris 10 + UltraSPARC是否可以像Scott McNealy希望的是下一匹世紀黑馬呢?Sun是否能以股價來證明華爾街分析師及普羅大眾的誹短流長?Scott McNealy是否能帶領著Sun成為繼微軟之后的下一個巨人,一場場IT界的爭霸戰值得我們拭目以待。


    Rod Johnson : 用一本書改變了Java世界的人

    Rod在悉尼大學不僅獲得了計算機學位,同時還獲得了音樂學位。更令人吃驚的是在回到軟件開發領域之前,他還獲得了音樂學的博士學位。有著相當豐富的C/C++技術背景的Rod早在1996年就開始了對Java服務器端技術的研究。他是一個在保險、電子商務和金融行業有著豐富經驗的技術顧問,同時也是JSR-154(Servlet 2.4)和JDO 2.0的規范專家、JCP的積極成員。
    真正引起了人們的注意的,是在2002年Rod Johnson根據多年經驗撰寫的《Expert One-on-One J2EE Design and Development》。其中對正統J2EE架構的臃腫、低效的質疑,引發了人們對正統J2EE的反思。這本書也體現了Rod Johnson對技術的態度,技術的選擇應該基于實證或是自身的經驗,而不是任何形式的偶像崇拜或者門戶之見。正是這本書真正地改變了Java世界。基于這本書的代碼,Rod Johnson創建了輕量級的容器Spring。Spring的出現,使得正統J2EE架構一統天下的局面被打破。基于Struts+Hibernate+Spring的J2EE架構也逐漸得到人們的認可,甚至在大型的項目架構中也逐漸開始應用。
    Rod Johnson的新作《Expert One-on-one J2EE Development without JEB》則更讓人吃驚,單單“Without EJB”一詞就會讓大多數J2EE架構師大跌眼鏡了。不過Rod Johnson可能僅僅是想通過“Without EJB”一詞表明應該放開門戶之見。這也是Rod Johnson一貫的作風,。也許正是這種思想,促使得Rod Johnson創建了Spring,真正改變了Java世界。

     

    Alan Kay :Java的精神先鋒

    Sun的官方Java教材中有一句話,說Java是“C++的語法與Smalltalk語義的結合”。而Smalltalk的創造者就是Alan Kay。
    Alan Kay于1970年加入Xerox公司的Palo Alto研究中心。早在70年代初期,Alan Kay等人開發了世界上第二個面向對象語言Smalltalk,因此,Alan Kay被譽為Smalltalk之父。2003年,Alan Key因為在面向對象程序設計上的杰出貢獻,獲得了有計算機界的諾貝爾獎之稱的ACM Turing Award。
    Alan Kay成名于Smapltalk和OOP,而Java雖然在語言上類似于C,但是在語義上非常接近Smalltalk,很多Java中的設計思想在Alan Kay的文獻中找到根源,也有些人將Alan Kay尊為Java思想的先驅。不過遺憾的是似乎Alan Kay老先生對Java并不買賬,反倒攻擊說Java是存在致命缺陷的編程語言,Java的成功不是由于Java本身的內在價值,而是其商業化的成功。Alan Kay欣賞的是Lisp,他認為Lisp是軟件的麥克斯韋方程,其中的許多想法是軟件工程和計算機科學的一部分。看來擁有Alan Kay這樣一位重量級的Java先驅仍是我們Java一廂情愿的單戀吧。


    Kent Beck : 領導的敏捷潮

    Beck全家似乎都彌漫著技術的味道。生長在硅谷, 有著一個對無線電癡迷的祖父,以及一個電器工程師父親。從小就引導Kent Beck成為了業余無線電愛好者。
    在俄勒岡州大學讀本科期間,Kent Beck就開始研究起模式。然而在他最終拿到計算機學位之前,他卻是在計算機和音樂中交替學習。似乎Java大師都能夠有這樣的能耐,另一Java大牛Rod Johnson同樣也擁有音樂學的博士學位。
    Kent Beck一直倡導軟件開發的模式定義。早在1993年,他就和Grady Booch(UML之父)發起了一個團隊進行這個方面的研究。雖然著有了《Smalltalk Best Practice Patterns》一書,但這可能并不是Kent Beck最大的貢獻。他于1996年在DaimlerChrysler啟動的關于軟件開發的項目,才真正地影響后來的軟件開發。這次的杰作就是XP(極限編程)的方法學。
    和軟件開發大師Martin Fowler合著的《Planning Extreme Programming》可謂是關于XP的奠基之作。從此,一系列的作品如《Test Driven Development: By Example》,《Extreme Programming Explained: Embrace Change》讓更多的人領略到了極限編程的精髓,也逐步導致了極限編程的流行。
    Kent Beck的貢獻遠不僅如此。對于眾多的Java程序員來說,他和Erich Gamma共同打造的JUnit,意義更加重大。也許正式這個簡單而又強大的工具,讓眾多的程序員更加認可和信賴極限編程,從而引起了Java敏捷開發的狂潮吧。



    轉載人員:Nicholas
    posted @ 2010-08-30 11:27 obpm 閱讀(196) | 評論 (0)編輯 收藏

    功能:在線拍照
    簡介:用flex與java結合實現在線拍照
    需求:為了滿足希望通過攝像頭拍照的圖片,然后通過服務器來展示需要
    效果:
                后臺: 

                前臺:


    實現代碼:
    flex:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="388" height="222" creationComplete="initApp()" backgroundColor="#A6C9E2">
         
    <mx:Style>
             Alert{font-size:12px;}
         
    </mx:Style>
         
    <mx:Script>
             
    <![CDATA[
                 import mx.events.CloseEvent;
                 import mx.rpc.events.FaultEvent;
                 import mx.rpc.events.ResultEvent;
                 import mx.controls.Alert;
                 import mx.core.Application;
                
                 private static const DEFAULT_CAMERA_WIDTH:Number = 160; //攝像頭顯示寬度
                 private static const DEFAULT_CAMERA_HEIGHT:Number = 120; //攝像頭顯示高度
                 private var DEFAULT_WEBSERVICE_URL:String = ""; //WebService地址
                 private var str:String;
                
                 private var m_camera:Camera; //定義一個攝像頭
                 private var m_localVideo:Video; //定義一個本地視頻
                 private var m_pictureBitmapData:BitmapData //定義視頻截圖
                 [Bindable]
                 private var m_pictureData:String;
                
                 private function initApp():void
                 {
                     t_btn_Shooting.enabled = false;
                     t_ban_Save.enabled = false;
                     initCamera();
                     DEFAULT_WEBSERVICE_URL = Application.application.parameters.contextPath+"/onLineTakePhotoServlet";
                     t_ws_SavePicture.url=DEFAULT_WEBSERVICE_URL;
                 }
                
                 //初始化攝像頭
                 private function initCamera():void
                 {
                     m_camera = Camera.getCamera();
                     if(m_camera != null)
                     {
                         m_camera.addEventListener(StatusEvent.STATUS,__onCameraStatusHandler);
                        
                         m_camera.setMode(DEFAULT_CAMERA_WIDTH,DEFAULT_CAMERA_HEIGHT,30);
                         m_localVideo = new Video();
                         m_localVideo.width = DEFAULT_CAMERA_WIDTH;
                         m_localVideo.height = DEFAULT_CAMERA_HEIGHT;
                         m_localVideo.attachCamera(m_camera);
                         t_vd_Video.addChild(m_localVideo);
                     }
                     else
                     {
                         Alert.show("沒有找到攝像頭,是否重新查找。","提示:",Alert.OK|Alert.NO,this,__InitCamera);
                         return;
                     }
                 }
                
                 //拍照按鈕事件,進行視頻截圖
                 private function SnapshotPicture():void
                 {
                     m_pictureBitmapData = new BitmapData(DEFAULT_CAMERA_WIDTH,DEFAULT_CAMERA_HEIGHT);
                     m_pictureBitmapData.draw(t_vd_Video,new Matrix());
                    
                     var m_pictureBitmap:Bitmap = new Bitmap(m_pictureBitmapData);
                     t_img_Picture.addChild(m_pictureBitmap);
                    
                     t_panel_Picture.visible = true;
                     t_ban_Save.enabled = true;
                 }
                
                 //保存按鈕事件,保存視頻截圖
                 //通過WebService保存
                 private function SavePicture():void
                 {
                     m_pictureData = "";
                     for(var i:int = 0; i < DEFAULT_CAMERA_WIDTH; i++)
                     {
                         for(var j:int = 0; j < DEFAULT_CAMERA_HEIGHT; j++)
                         {
                             if(m_pictureData.length > 0)
                             {
                                 m_pictureData += "," + m_pictureBitmapData.getPixel32(i,j).toString();
                             }
                             else
                             {
                                 m_pictureData = m_pictureBitmapData.getPixel32(i,j).toString();
                             }
                         }
                     }
                     
                     var params:URLVariables = new URLVariables();
         params.width = DEFAULT_CAMERA_WIDTH;
         params.height = DEFAULT_CAMERA_HEIGHT;
         params.bitmap_data = m_pictureData;
         t_ws_SavePicture.send(params);
                 }
                
                 //檢測攝像頭權限事件
                 private function __onCameraStatusHandler(event:StatusEvent):void
                 {
                     if(!m_camera.muted)
                     {
                         t_btn_Shooting.enabled = true;
                     }
                     else
                     {
                         Alert.show("無法鏈接到活動攝像頭,是否重新檢測。","提示:",Alert.OK|Alert.NO,this,__InitCamera);
                     }
                     m_camera.removeEventListener(StatusEvent.STATUS,__onCameraStatusHandler);
                 }
                
                 //當攝像頭不存在,或連接不正常時重新獲取
                 private function __InitCamera(event:CloseEvent):void
                 {
                     if(event.detail == Alert.OK)
                     {
                         initApp();
                     }
                 }
                
                 //WebService保存圖片成功事件
                 private function __onSavePictureResult(event:ResultEvent):void
                 {
                     //trace(event.result);
                     if(event.result.toString() != "保存失敗")
                     {
                       str = event.result.toString();
                       
                         Alert.show("保存成功,是否關閉窗口?","提示",3,this,__onAlertCloseHandler);
                     }
                     else
                     {
                         Alert.show(event.result.toString(),"提示",Alert.OK);
                     }
                 }
                
                 //連接WebService失敗事件
                 private function __onSavePictureFault(event:FaultEvent):void
                 {
                     //Alert.show(event.fault.toString(),"提示",Alert.OK);
                     Alert.show("連接服務器失敗。","提示",Alert.OK);
                 }
                
                 //保存圖片成功后的彈出窗口確認事件
                 private function __onAlertCloseHandler(event:CloseEvent):void
                 {
                     if(event.detail == Alert.YES)
                     {
                        ExternalInterface.call("setValueToField",str);
                     }
                 }
             
    ]]>
         
    </mx:Script>
         
    <mx:HTTPService id="t_ws_SavePicture" showBusyCursor="true" method="POST" useProxy="false" result="__onSavePictureResult(event)" fault="__onSavePictureFault(event)"/>
         
    <mx:Panel x="10" y="10" width="180" height="200" layout="absolute" title="視頻拍照" fontSize="12">
             
    <mx:VideoDisplay id="t_vd_Video" width="160" height="120"/>
             
    <mx:ControlBar horizontalAlign="right">
                 
    <mx:Button id="t_btn_Shooting" label="拍照" click="SnapshotPicture()"/>
             
    </mx:ControlBar>
         
    </mx:Panel>
         
    <mx:Panel id="t_panel_Picture" x="198" y="10" width="180" height="200" layout="absolute" title="拍照圖片" fontSize="12" visible="false">
             
    <mx:Image id="t_img_Picture" x="0" y="0" width="160" height="120"/>
             
    <mx:ControlBar   horizontalAlign="right">
                 
    <mx:Button id="t_ban_Save" label="保存" click="SavePicture()" />
             
    </mx:ControlBar>
         
    </mx:Panel>
    </mx:Application>



    java:

    package cn.myapps.core.onlinetakephoto;

    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;

    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import cn.myapps.constans.Environment;
    import cn.myapps.util.sequence.Sequence;

    /**
     * Servlet implementation class onLineTakePhotoServlet
     
    */
    public class onLineTakePhotoServlet extends HttpServlet {
     
    private static final long serialVersionUID = 1L;
        
     
    private Environment env = Environment.getInstance();
     
     
    public void doGet(HttpServletRequest request, HttpServletResponse response)    
     
    throws ServletException, IOException {    
     processRequest(request, response);    
     }    
       
     
    public void doPost(HttpServletRequest request, HttpServletResponse response)    
      
    throws ServletException, IOException {    
     processRequest(request, response);    
     }    
     
     
    public void processRequest(HttpServletRequest request, HttpServletResponse response)

        
    throws ServletException, IOException {
      response.setContentType(
    "text/html;charset=UTF-8");   
            response.setHeader(
    "Pragma""No-cache");   
            response.setHeader(
    "Cache-Control""no-cache");   
            response.setDateHeader(
    "Expires"0);   
      
            String bitmap_data 
    = request.getParameter("bitmap_data");   
            
    int width = Integer.parseInt(request.getParameter("width"));   
            
    int height = Integer.parseInt(request.getParameter("height"));   
            BufferedImage img 
    = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);   
      
    try {   
                
    int w = width;   
                
    int h = height;   
                
    int[] pixels = new int[w * h];   
                String[] m_tempPics 
    = bitmap_data.split(",");   
                
    for (int x = 0; x < w; x++) {   
                    
    for (int y = 0; y < h; y++) {   
                        Long pic_argb 
    = Long.parseLong(m_tempPics[x * h + y]);   
                        
    int a = (int) (pic_argb >> 24 & 0xFF);   
                        
    int r = (int) (pic_argb >> 16 & 0xFF);   
                        
    int g = (int) (pic_argb >> 8 & 0xFF);   
                        
    int b = (int) (pic_argb & 0xFF);   
                        pixels[y 
    * w + x] = new Color(r, g, b, a).getRGB();   
                    }   
                }   
                img.setRGB(
    00, w, h, pixels, 0, w);   
                img.flush();   
                ByteArrayOutputStream bao 
    = new ByteArrayOutputStream();   
                ImageIO.write(img, 
    "jpg", bao);   
                
    byte[] data = bao.toByteArray();  
                String filePath 
    = env.getRealPath("/uploads/photo");
                
    //判斷路徑是否存在,若不存在則創建路徑
                File upDir = new File(filePath);
                
    if (!upDir.exists())
                {
                    upDir.mkdir();
                }
                
    //生成隨機文件名
                String saveName = Sequence.getSequence();
                String fileName 
    = saveName + ".jpg";
                
    //寫圖片
                File f = new File(filePath+"\\" + fileName);
          DataOutputStream dos 
    = new DataOutputStream(new FileOutputStream(f));
          dos.write(data);
          dos.flush();
          dos.close();
          response.setContentType(
    "text/xml");   
                response.getWriter().write(
    "/uploads/photo/" + fileName);   
            }
            
    catch(Exception ex)
            {
             response.setContentType(
    "text/xml");   
                response.getWriter().write(
    "保存失敗");   
            }
     }

    }

     


    源碼:/Files/obpm/onlinetakephoto.rar

     原創人員:Denny

    posted @ 2010-08-29 21:52 obpm 閱讀(5517) | 評論 (5)編輯 收藏

    LDAP快速入門

    1. LDAP簡介

      LDAP(輕量級目錄訪問協議,Lightweight Directory Access Protocol)是實現提供被稱為目錄服務的信息服務。目錄服務是一種特殊的數據庫系統,其專門針對讀取,瀏覽和搜索操作進行了特定的優化。目錄一般用來包含描述性的,基于屬性的信息并支持精細復雜的過濾能力。目錄一般不支持通用數據庫針對大量更新操作操作需要的復雜的事務管理或回卷策略。而目錄服務的更新則一般都非常簡單。這種目錄可以存儲包括個人信息、web鏈結、jpeg圖像等各種信息。為了訪問存儲在目錄中的信息,就需要使用運行在TCP/IP 之上的訪問協議—LDAP。

     

      LDAP目錄中的信息是是按照樹型結構組織,具體信息存儲在條目(entry)的數據結構中。條目相當于關系數據庫中表的記錄;條目是具有區別名DN (Distinguished Name)的屬性(Attribute),DN是用來引用條目的,DN相當于關系數據庫表中的關鍵字(Primary Key)。屬性由類型(Type)和一個或多個值(Values)組成,相當于關系數據庫中的字段(Field)由字段名和數據類型組成,只是為了方便檢索的需要,LDAP中的Type可以有多個Value,而不是關系數據庫中為降低數據的冗余性要求實現的各個域必須是不相關的。LDAP中條目的組織一般按照地理位置和組織關系進行組織,非常的直觀。LDAP把數據存放在文件中,為提高效率可以使用基于索引的文件數據庫,而不是關系數據庫。類型的一個例子就是mail,其值將是一個電子郵件地址。

     

    LDAP的信息是以樹型結構存儲的,在樹根一般定義國家(c=CN)或域名(dc=com),在其下則往往定義一個或多個組織 (organization)(o=Acme)或組織單元(organizational units) (ou=People)。一個組織單元可能包含諸如所有雇員、大樓內的所有打印機等信息。此外,LDAP支持對條目能夠和必須支持哪些屬性進行控制,這是有一個特殊的稱為對象類別(objectClass)的屬性來實現的。該屬性的值決定了該條目必須遵循的一些規則,其規定了該條目能夠及至少應該包含哪些屬性。例如:inetorgPerson對象類需要支持sn(surname)和cn(common name)屬性,但也可以包含可選的如郵件,電話號碼等屬性。

     

    2. LDAP簡稱對應

    1. o– organization(組織-公司)
    2. ou – organization unit(組織單元-部門)
    3. c - countryName(國家)
    4. dc - domainComponent(域名)
    5. sn – suer name(真實名稱)
    6. cn - common name(常用名稱)

     

    3. 目錄設計

    設計目錄結構是LDAP最重要的方面之一。下面我們將通過一個簡單的例子來說明如何設計合理的目錄結構。該例子將通過Netscape地址薄來訪文。假設有一個位于美國US(c=US)而且跨越多個州的名為Acme(o=Acme)的公司。Acme希望為所有的雇員實現一個小型的地址薄服務器。

     

      我們從一個簡單的組織DN開始: 

        dn: o=Acme, c=US

     

      Acme所有的組織分類和屬性將存儲在該DN之下,這個DN在該存儲在該服務器的目錄是唯一的。Acme希望將其雇員的信息分為兩類:管理者(ou= Managers)和普通雇員(ou=Employees),這種分類產生的相對區別名(RDN,relative distinguished names。表示相對于頂點DN)就shi :

     

        dn: ou=Managers, o=Acme, c=US

        dn: ou=Employees, o=Acme, c=US

     

      在下面我們將會看到分層結構的組成:頂點是US的Acme,下面是管理者組織單元和雇員組織單元。因此包括Managers和Employees的DN組成為:

        dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US

        dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US

        dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US

     

      為了引用Jason H. Smith的通用名(common name )條目,LDAP將采用cn=Jason H. Smith的RDN。然后將前面的父條目結合在一起就形成如下的樹型結構:

     

        cn=Jason H. Smith

            + ou=Managers

                + o=Acme

                    + c=US

                                   -> dn: cn=Jason H. Smith,ou=Managers,o=Acme,c=US

     

     

      現在已經定義好了目錄結構,下一步就需要導入目錄信息數據。目錄信息數據將被存放在LDIF文件中,其是導入目錄信息數據的默認存放文件。用戶可以方便的編寫Perl腳本來從例如/etc/passwd、NIS等系統文件中自動創建LDIF文件。

     

      下面的實例保存目錄信息數據為testdate.ldif文件,該文件的格式說明將可以在man ldif中得到。

      在添加任何組織單元以前,必須首先定義Acme DN: 

        dn: o=Acme, c=US

        objectClass: organization

     

      這里o屬性是必須的

        o: Acme

     

      下面是管理組單元的DN,在添加任何管理者信息以前,必須先定義該條目。

        dn: ou=Managers, o=Acme, c=US

        objectClass: organizationalUnit

    這里ou屬性是必須的。

     

    ou: Managers

      第一個管理者DN:

        dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US

        objectClass: inetOrgPerson

      cn和sn都是必須的屬性:

        cn: Jason H. Smith

        sn: Smith

      但是還可以定義一些可選的屬性:

        telephoneNumber: 111-222-9999

        mail: headhauncho@acme.com

        localityName: Houston

     

      可以定義另外一個組織單元:

        dn: ou=Employees, o=Acme, c=US

        objectClass: organizationalUnit

        ou: Employees

     

      并添加雇員信息如下:

        dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US

        objectClass: inetOrgPerson

        cn: Ray D. Jones

        sn: Jones

        telephoneNumber: 444-555-6767

        mail: jonesrd@acme.com

        localityName: Houston

        dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US

        objectClass: inetOrgPerson

        cn: Eric S. Woods

        sn: Woods

        telephoneNumber: 444-555-6768

        mail: woodses@acme.com

        localityName: Houston

     

     

    4. 配置OpenLDAP

    本文實踐了在 Windows 下安裝配 openldap,并添加一個條目,LdapBrowser 瀏覽,及 Java 程序連接 openldap 的全過程。

     

    1. 下載安裝 openldap for windows,當前版本2.2.29下載地址:http://download.bergmans.us/openldap/openldap-2.2.29/openldap-2.2.29-db-4.3.29-openssl-0.9.8a-win32_Setup.exe

        相關鏈接:http://lucas.bergmans.us/hacks/openldap/

       安裝很簡單,一路 next 即可,假設我們安裝在 c:\openldap

     

    2. 配置 openldap,編輯 sldap.conf 文件

       1) 打開 c:\openldap\sldap.conf,找到

        include  C:/openldap/etc/schema/core.schema,在它后面添加

        include  C:/openldap/etc/schema/cosine.schema

        include  C:/openldap/etc/schema/inetorgperson.schema

     

        接下來的例子只需要用到以上三個 schema,當然,如果你覺得需要的話,你可以把其他的 schema 全部添加進來

        include  C:/openldap/etc/schema/corba.schema

        include  C:/openldap/etc/schema/dyngroup.schema

        include  C:/openldap/etc/schema/java.schema

        include  C:/openldap/etc/schema/misc.schema

        include  C:/openldap/etc/schema/nis.schema

        include  C:/openldap/etc/schema/openldap.schema

     

       2) 還是在 sldap.conf 文件中,找到

        suffix  "dc=my-domain,dc=com"

        rootdn  "cn=Manager,dc=my-domain,dc=com"

        把這兩行改為

        suffix "o=teemlink,c=cn" 

        rootdn "cn=Manager,o=teemlink,dc=cn"

     

        suffix 就是看自己如何定義了,后面步驟的 ldif 文件就必須與它定義了。還要注意到這個配置文件中有一個 rootpw  secret,這個 secret 是 cn=Manager 的密碼,以后會用到,不過這里是明文密碼,你可以用命令: slappasswd -h {MD5} -s secret 算出加密的密碼 {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== 取代配置中的 secret。

     

    3. 啟動 openldap

        CMD 進入到 c:\openldap 下,運行命令 sldapd -d 1

        用可以看到控制臺下打印一片信息,openldap 默認是用的 Berkeley DB 數據庫存儲目錄數據的。

     

    4. 建立條目,編輯導入 ldif 文件

       1) 新建一個 ldif(LDAP Data Interchanged Format) 文件(純文本格式),例如 test.ldif,文件內容如下:

       

    dn: o=teemlink

    objectclass: top

    objectclass: organization

    o: develop

     

       2) 執行命令:ldapadd -l test.ldif

     

    5. 使用LDAP Browser進行訪問

           5.1安裝LDAP Browser2.6軟件,進行如下操作:

       

      

     

    5.2顯示效果

     

     

    5. Java操作LDAP

     

    5.1 用JNDI進訪問

    package cn.myapps.test;

    import java.util.Hashtable;
    import javax.naming.Context;
    import javax.naming.NamingException;
    import javax.naming.directory.Attributes;
    import javax.naming.directory.DirContext;
    import javax.naming.directory.InitialDirContext;

    public class LdapTest {
    public void JNDILookup() {
    String root
    = "o=teemlink,c=cn";
    Hashtable env
    = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL,
    "ldap://192.168.0.30/" + root);
    env.put(Context.SECURITY_AUTHENTICATION,
    "simple");
    env.put(Context.SECURITY_PRINCIPAL,
    "cn=Nicholas,ou=develop,o=teemlink,c=cn");
    env.put(Context.SECURITY_CREDENTIALS,
    "123456");
    DirContext ctx
    = null;

    try {
    ctx
    = new InitialDirContext(env);
    Attributes attrs
    = ctx.getAttributes("cn=Nicholas,ou=develop");
    System.out.println(
    "Last Name: " + attrs.get("sn").get());
    System.out.println(
    "認證成功");
    }
    catch (javax.naming.AuthenticationException e) {
    e.printStackTrace();
    System.out.println(
    "認證失敗");
    }
    catch (Exception e) {
    System.out.println(
    "認證出錯:");
    e.printStackTrace();
    }
    if (ctx != null) {
    try {
    ctx.close();
    }
    catch (NamingException e) {
    // ignore
    }
    }
    }

    public static void main(String[] args) {
    LdapTest LDAPTest
    = new LdapTest();
    LDAPTest.JNDILookup();
    }
    }

     

    5.2 用JLDAP進訪問

    訪問地址:http://www.openldap.org/jldap/ 并下載相關lib

     

    import com.novell.ldap.*;

    import java.io.UnsupportedEncodingException;

    public class List

    {

    public static void main(String[] args)

    {
    int ldapPort = LDAPConnection.DEFAULT_PORT;
    int searchScope = LDAPConnection.SCOPE_ONE;
    int ldapVersion = LDAPConnection.LDAP_V3;
    boolean attributeOnly = false;
    String attrs[]
    = null;
    String ldapHost
    = "192.168.0.30";
    String loginDN
    = "cn=Manager,o=teemlink,c=cn";
    String password
    = "secret";
    String searchBase
    = "ou=develop,o=teemlink,c=cn";
    String searchFilter
    = "objectClass=*";

    LDAPConnection lc
    = new LDAPConnection();
    try {
    // connect to the server
    lc.connect(ldapHost, ldapPort);

    // bind to the server
    lc.bind(ldapVersion, loginDN, password.getBytes("UTF8"));

    LDAPSearchResults searchResults
    =

    lc.search(searchBase,
    // container to search
    searchScope, // search scope
    searchFilter, // search filter
    attrs, // "1.1" returns entry name only
    attributeOnly); // no attributes are returned

    // print out all the objects
    while (searchResults.hasMore()) {
    LDAPEntry nextEntry
    = null;
    try {
    nextEntry
    = searchResults.next();
    System.out.println(
    "\n" + nextEntry.getDN());
    System.out.println(nextEntry.getAttributeSet());
    }
    catch (LDAPException e) {
    System.out.println(
    "Error: " + e.toString());
    // Exception is thrown, go for next entry
    continue;
    }
    }

    // disconnect with the server
    lc.disconnect();

    }
    catch (LDAPException e) {
    System.out.println(
    "Error: " + e.toString());
    }
    catch (UnsupportedEncodingException e) {
    System.out.println(
    "Error: " + e.toString());
    }
    System.exit(
    0);
    }
    }

     

    5.3 用JDBC-LDAP進訪問

    訪問地址:http://www.openldap.org/jdbcldap/ 并下載相關lib

     

    package jdbcldap;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;

    public class JdbcLdap {

    /**
    *
    @param args
    *
    @throws Exception
    */
    public static void main(String[] args) throws Exception {
    Class.forName(
    "com.octetstring.jdbcLdap.sql.JdbcLdapDriver");
    String ldapConnectString
    = "jdbc:ldap://192.168.0.30/o=teemlink,c=cn?SEARCH_SCOPE:=subTreeScope";
    Connection con
    = DriverManager.getConnection(ldapConnectString, "cn=Manager,o=teemlink,c=cn", "secret");

    String sql
    = "SELECT * FROM ou=develop,o=teemlink,c=cn";

    Statement sat
    = con.createStatement();
    ResultSet rs
    = sta.executeQuery(sql);
    while (rs.next()) {
    System.out.println(rs.getString(
    1));
    }

    if (con != null)
    con.close();
    }
    }

     

    原創人員:Nicholas

     

     


    文章來源:http://www.cnblogs.com/obpm/archive/2010/08/28/1811065.html
    posted @ 2010-08-28 14:38 obpm 閱讀(1931) | 評論 (0)編輯 收藏

    以子類取代類型編碼

     Replace Type Code with Subclasses

    1. 何謂重構

     

    1.1名詞解釋

      對軟件內部結構的一種調整,目的是在不改變「軟件之可察行為」前提下,提高其可理解性,降低其修改成本。

      

    1.2動詞解釋

      使用一系列重構準則(手法),在不改變「軟件之可察行為」前提下,調整其結構。

     

    2. 為何重構

     

    2.1「重構」改進軟件設計

      同樣完成一件事,設計不良的程序往往需要更多代碼,這常常是因為代碼在不同的方使用完全相同的語句做同樣的事。因此改進設計的一個重要方向就是消除重復代碼(Duplicate Code)

     

    2.2「重構」使軟件更易被理解

      你的源碼還有其它讀者:數個月之后可能會有另一位程序員嘗試讀懂你的代碼并做一些修改。我們很容易忘記這第二位讀者,但他才是最重要的。計算器是否多花了數個鐘頭進行編譯,又有什么關系呢?如果一個程序員花費一周時間來修改某段代碼,那才關系重大— 如果他理解你的代碼,這個修改原本只需一小時

     

    2.3「重構」助你找到臭蟲 ( bugs)

      Kent Beck 經常形容自己的一句話:『我不是個偉大的程序員;我只是個有著些優秀習慣的好程序員而已。』重構能夠幫助我更有效地寫出強固穩健(robust)的代碼。 

     

    2.4「重構」助你提高編程速度

      終于,前面的一切都歸結到了這最后一點:重構幫助你更快速地開發程序。聽起來有違反直覺。當我談到重構,人們很容易看出它能夠提高質量。改善設計、提升可讀性、減少錯誤,這些都是提高質量。但這難道不會降低開發速度嗎?我強烈相信:良好設計是快速軟件開發的根本。事實上擁有良好設計才可能達成快速的開發。如果沒有良好設計,或許某段時間內你的進展迅速,但惡劣的設計很快就讓你的速度慢來。你會把時間花在調試面,無法添加新功能。修改時間愈來愈長,因為你必須花愈來愈多的時間去理解系統、尋找重復代碼。隨著你給最初程序打上一個又一個的補丁(patch),新特性需要更多代碼才能實現。真是個惡性循環。

     

    3.何時重構?

      重構本來就不是一件「特別撥出時間做」的事情,重構應該隨時隨地進行。你不應該為重構而重構,你之所以重構,是因為你想做別的什么事,而重構可以幫助你把那些事做好

     

    3.1三次法則(The Rule of Three)

      Don Roberts 給了我一條準則:第一次做某件事時只管去做;第二次做類似的事會產生反感,但無論如何還是做了;第三次再做類似的事,你就應該重構。

      ☆ 事不過則重構。(Three strikes and you refactor.

     

    3.2重構時機

      添加功能時一并重構

      修補錯誤時一并重構

      復審代碼時一并重構

     

    -以上章節摘抄自《重構-改善既有代碼的設計

     

    4.平臺重構案例

     

    4.1重構動機

      1. 實例模塊為View,重構元素為ViewAction、ViewProcessBean、View,以下為關系圖。

      

      2. 由于View存在多種editMode(編輯模式),而每個調用的地方都需要進行type code(類型碼)判斷,然后再進行相應的業務邏輯處理,最終在每個調用的地方都形成了大量的if-else代碼,大大減弱了代碼的可讀性,和邏輯清晰度。

     

      3. 調用的地方:

      

    4.2重構作法

      

     

    如上圖所示,將每種type code重構成subclass,加強了每種類型處理業務邏輯的能力。

     

    View-版本1566代碼片段:

     

    public EditMode getEditModeType() {
    if (EDIT_MODE_CODE_DQL.equals(getEditMode())) {
    return new DQLEditMode(this);
    }
    else if (EDIT_MODE_CODE_SQL.equals(getEditMode())) {
    return new SQLEditMode(this);
    }
    else if (EDIT_MODE_DESIGN.equals(getEditMode())) {
    return new DesignEditMode(this);
    }

    return new NullEditMode(this);
    }

    說明:調用者無需了解具體的類型,由View自身作判斷,返回EditMode接口,從而實現多態調用。

     

     

    ViewProcessBean代碼片段:

    重構前-版本1503:

     

    public String expDocToExcel(String viewid, WebUser user, ParamsTable params) throws Exception {
    if (view.getEditMode().equals(View.EDIT_MODE_DESIGN)) {
    datas
    = dp.queryBySQLPage(sql, params, tempPage, LINES, user.getDomainid());
    }
    else if (view.getEditMode().equals(View.EDIT_MODE_CODE_DQL)) {
    datas
    = dp.queryByDQLPage(dql, params, tempPage, LINES, user.getDomainid());
    }
    else if (view.getEditMode().endsWith(View.EDIT_MODE_CODE_SQL)) {
    datas
    = dp.queryBySQLPage(sql, params, tempPage, LINES, user.getDomainid());
    }
    }

     

    重構后-版本1566:

     

    public String expDocToExcel(String viewid, WebUser user, ParamsTable params) throws Exception {
    datas
    = view.getEditModeType().getDataPackage(params, tempPage, LINES, user, currdoc);
    //其他業務邏輯
    }

     

     

    5.結語

      由上述案例可看到,引入subclass代替type code可以大大減少if-else判斷,而且可以把責任內聚到每種type中,使代碼結構更清晰易懂。

     

    6.其他

           在本案例中引入了空類型概念,即NullEditMode,代碼如下:

      

    /**
    *
    *
    @author nicholas zhen
    *
    */
    public class NullEditMode extends AbstractEditMode implements EditMode {

    public NullEditMode(View view) {
    super(view);
    }

    public String getQueryString(ParamsTable params, WebUser user, Document sDoc) {
    return "";
    }

    public DataPackage getDataPackage(ParamsTable params, WebUser user, Document doc) throws Exception {
    return new DataPackage();
    }

    public DataPackage getDataPackage(ParamsTable params, int page, int lines, WebUser user, Document doc) throws Exception {
    return new DataPackage();
    }

    public long count(ParamsTable params, WebUser user, Document doc) throws Exception {
    return 0;
    }
    }

    說明:空類型保證了調用每個方法都有默認值返回,而不需要進行非空判斷,當View沒有類型時,即返回默認的空類型

     

    原創人員:Nicholas


    文章來源:http://www.cnblogs.com/obpm/archive/2010/07/13/1776856.html
    posted @ 2010-07-13 23:22 obpm 閱讀(231) | 評論 (0)編輯 收藏

    不會畫流程圖的,看了這個就懂了,絕對經典!

     

     

     

     

    轉載人員:Nicholas


    文章來源:http://www.cnblogs.com/obpm/archive/2010/07/12/1776058.html
    posted @ 2010-07-12 21:34 obpm 閱讀(269) | 評論 (0)編輯 收藏
    創建型模式

    1、FACTORY —追MM少不了請吃飯了,麥當勞的雞翅和肯德基的雞翅都是MM愛吃的東西,雖然口味有所不同,但不管你帶MM去麥當勞或肯德基,只管向服務員說“來四個雞翅”就行了。麥當勞和肯德基就是生產雞翅的Factory

    工廠模式:客戶類和工廠類分開。消費者任何時候需要某種產品,只需向工廠請求即可。消費者無須修改就可以接納新產品。缺點是當產品修改時,工廠類也要做相應的修改。如:如何創建及如何向客戶端提供。

    2、BUILDER  —MM最愛聽的就是“我愛你”這句話了,見到不同地方的MM,要能夠用她們的方言跟她說這句話哦,我有一個多種語言翻譯機,上面每種語言都有一個按鍵,見到MM我只要按對應的鍵,它就能夠用相應的語言說出“我愛你”這句話了,國外的MM也可以輕松搞掂,這就是我的“我愛你”builder。(這一定比美軍在伊拉克用的翻譯機好賣)

    建造模式:將產品的內部表象和產品的生成過程分割開來,從而使一個建造過程生成具有不同的內部表象的產品對象。建造模式使得產品內部表象可以獨立的變化,客戶不必知道產品內部組成的細節。建造模式可以強制實行一種分步驟進行的建造過程。

    3、FACTORY METHOD —請MM去麥當勞吃漢堡,不同的MM有不同的口味,要每個都記住是一件煩人的事情,我一般采用Factory Method模式,帶著MM到服務員那兒,說“要一個漢堡”,具體要什么樣的漢堡呢,讓MM直接跟服務員說就行了。

    工廠方法模式:核心工廠類不再負責所有產品的創建,而是將具體創建的工作交給子類去做,成為一個抽象工廠角色,僅負責給出具體工廠類必須實現的接口,而不接觸哪一個產品類應當被實例化這種細節。

    4、PROTOTYPE —跟MM用QQ聊天,一定要說些深情的話語了,我搜集了好多肉麻的情話,需要時只要copy出來放到QQ里面就行了,這就是我的情話prototype了。(100塊錢一份,你要不要)

    原始模型模式:通過給出一個原型對象來指明所要創建的對象的類型,然后用復制這個原型對象的方法創建出更多同類型的對象。原始模型模式允許動態的增加或減少產品類,產品類不需要非得有任何事先確定的等級結構,原始模型模式適用于任何的等級結構。缺點是每一個類都必須配備一個克隆方法。

    5、SINGLETON —俺有6個漂亮的老婆,她們的老公都是我,我就是我們家里的老公Sigleton,她們只要說道“老公”,都是指的同一個人,那就是我(剛才做了個夢啦,哪有這么好的事)

    單例模式:單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例單例模式。單例模式只應在有真正的“單一實例”的需求時才可使用。

    結構型模式

    6、ADAPTER —在朋友聚會上碰到了一個美女Sarah,從香港來的,可我不會說粵語,她不會說普通話,只好求助于我的朋友kent了,他作為我和Sarah之間的Adapter,讓我和Sarah可以相互交談了(也不知道他會不會耍我)

    適配器模式:把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口原因不匹配而無法一起工作的兩個類能夠一起工作。適配類可以根據參數返還一個合適的實例給客戶端。

    7、BRIDGE —早上碰到MM,要說早上好,晚上碰到MM,要說晚上好;碰到MM穿了件新衣服,要說你的衣服好漂亮哦,碰到MM新做的發型,要說你的頭發好漂亮哦。不要問我“早上碰到MM新做了個發型怎么說”這種問題,自己用BRIDGE組合一下不就行了

    橋梁模式:將抽象化與實現化脫耦,使得二者可以獨立的變化,也就是說將他們之間的強關聯變成弱關聯,也就是指在一個軟件系統的抽象化和實現化之間使用組合/聚合關系而不是繼承關系,從而使兩者可以獨立的變化。

    8、COMPOSITE —Mary今天過生日。“我過生日,你要送我一件禮物。”“嗯,好吧,去商店,你自己挑。”“這件T恤挺漂亮,買,這條裙子好看,買,這個包也不錯,買。”“喂,買了三件了呀,我只答應送一件禮物的哦。”“什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻煩你包起來。”“……”,MM都會用Composite模式了,你會了沒有?

    合成模式:合成模式將對象組織到樹結構中,可以用來描述整體與部分的關系。合成模式就是一個處理對象的樹結構的模式。合成模式把部分與整體的關系用樹結構表示出來。合成模式使得客戶端把一個個單獨的成分對象和由他們復合而成的合成對象同等看待。

    9、DECORATOR —Mary過完輪到Sarly過生日,還是不要叫她自己挑了,不然這個月伙食費肯定玩完,拿出我去年在華山頂上照的照片,在背面寫上“最好的的禮物,就是愛你的Fita”,再到街上禮品店買了個像框(賣禮品的MM也很漂亮哦),再找隔壁搞美術設計的Mike設計了一個漂亮的盒子裝起來……,我們都是Decorator,最終都在修飾我這個人呀,怎么樣,看懂了嗎?

    裝飾模式:裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案,提供比繼承更多的靈活性。動態給一個對象增加功能,這些功能可以再動態的撤消。增加由一些基本功能的排列組合而產生的非常大量的功能。

    10、FAÇADE —我有一個專業的Nikon相機,我就喜歡自己手動調光圈、快門,這樣照出來的照片才專業,但MM可不懂這些,教了半天也不會。幸好相機有Facade設計模式,把相機調整到自動檔,只要對準目標按快門就行了,一切由相機自動調整,這樣MM也可以用這個相機給我拍張照片了。

    門面模式:外部與一個子系統的通信必須通過一個統一的門面對象進行。門面模式提供一個高層次的接口,使得子系統更易于使用。每一個子系統只有一個門面類,而且此門面類只有一個實例,也就是說它是一個單例模式。但整個系統可以有多個門面類。

    11、FLYWEIGHT —每天跟MM發短信,手指都累死了,最近買了個新手機,可以把一些常用的句子存在手機里,要用的時候,直接拿出來,在前面加上MM的名字就可以發送了,再不用一個字一個字敲了。共享的句子就是Flyweight,MM的名字就是提取出來的外部特征,根據上下文情況使用。

    享元模式:FLYWEIGHT在拳擊比賽中指最輕量級。享元模式以共享的方式高效的支持大量的細粒度對象。享元模式能做到共享的關鍵是區分內蘊狀態和外蘊狀態。內蘊狀態存儲在享元內部,不會隨環境的改變而有所不同。外蘊狀態是隨環境的改變而改變的。外蘊狀態不能影響內蘊狀態,它們是相互獨立的。將可以共享的狀態和不可以共享的狀態從常規類中區分開來,將不可以共享的狀態從類里剔除出去。客戶端不可以直接創建被共享的對象,而應當使用一個工廠對象負責創建被共享的對象。享元模式大幅度的降低內存中對象的數量。

    12、PROXY —跟MM在網上聊天,一開頭總是“hi,你好”,“你從哪兒來呀?”“你多大了?”“身高多少呀?”這些話,真煩人,寫個程序做為我的Proxy吧,凡是接收到這些話都設置好了自動的回答,接收到其他的話時再通知我回答,怎么樣,酷吧。

    代理模式:代理模式給某一個對象提供一個代理對象,并由代理對象控制對源對象的引用。代理就是一個人或一個機構代表另一個人或者一個機構采取行動。某些情況下,客戶不想或者不能夠直接引用一個對象,代理對象可以在客戶和目標對象直接起到中介的作用。客戶端分辨不出代理主題對象與真實主題對象。代理模式可以并不知道真正的被代理對象,而僅僅持有一個被代理對象的接口,這時候代理對象不能夠創建被代理對象,被代理對象必須有系統的其他角色代為創建并傳入。

    行為模式

    13、CHAIN OF RESPONSIBLEITY —晚上去上英語課,為了好開溜坐到了最后一排,哇,前面坐了好幾個漂亮的MM哎,找張紙條,寫上“Hi,可以做我的女朋友嗎?如果不愿意請向前傳”,紙條就一個接一個的傳上去了,糟糕,傳到第一排的MM把紙條傳給老師了,聽說是個老處女呀,快跑!

    責任鏈模式:在責任鏈模式中,很多對象由每一個對象對其下家的引用而接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。客戶并不知道鏈上的哪一個對象最終處理這個請求,系統可以在不影響客戶端的情況下動態的重新組織鏈和分配責任。處理者有兩個選擇:承擔責任或者把責任推給下家。一個請求可以最終不被任何接收端對象所接受。

    14、COMMAND —俺有一個MM家里管得特別嚴,沒法見面,只好借助于她弟弟在我們倆之間傳送信息,她對我有什么指示,就寫一張紙條讓她弟弟帶給我。這不,她弟弟又傳送過來一個COMMAND,為了感謝他,我請他吃了碗雜醬面,哪知道他說:“我同時給我姐姐三個男朋友送COMMAND,就數你最小氣,才請我吃面。”,

    命令模式:命令模式把一個請求或者操作封裝到一個對象中。命令模式把發出命令的責任和執行命令的責任分割開,委派給不同的對象。命令模式允許請求的一方和發送的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎么被接收,以及操作是否執行,何時被執行以及是怎么被執行的。系統支持命令的撤消。

    15、INTERPRETER —俺有一個《泡MM真經》,上面有各種泡MM的攻略,比如說去吃西餐的步驟、去看電影的方法等等,跟MM約會時,只要做一個Interpreter,照著上面的腳本執行就可以了。

    解釋器模式:給定一個語言后,解釋器模式可以定義出其文法的一種表示,并同時提供一個解釋器。客戶端可以使用這個解釋器來解釋這個語言中的句子。解釋器模式將描述怎樣在有了一個簡單的文法后,使用模式設計解釋這些語句。在解釋器模式里面提到的語言是指任何解釋器對象能夠解釋的任何組合。在解釋器模式中需要定義一個代表文法的命令類的等級結構,也就是一系列的組合規則。每一個命令對象都有一個解釋方法,代表對命令對象的解釋。命令對象的等級結構中的對象的任何排列組合都是一個語言。

    16、ITERATOR —我愛上了Mary,不顧一切的向她求婚。
       Mary:“想要我跟你結婚,得答應我的條件”
       我:“什么條件我都答應,你說吧”
       Mary:“我看上了那個一克拉的鉆石”
       我:“我買,我買,還有嗎?”
       Mary:“我看上了湖邊的那棟別墅”
       我:“我買,我買,還有嗎?”
       Mary:“你的小弟弟必須要有50cm長”
       我腦袋嗡的一聲,坐在椅子上,一咬牙:“我剪,我剪,還有嗎?”
       ……

    迭代子模式:迭代子模式可以順序訪問一個聚集中的元素而不必暴露聚集的內部表象。多個對象聚在一起形成的總體稱之為聚集,聚集對象是能夠包容一組對象的容器對象。迭代子模式將迭代邏輯封裝到一個獨立的子對象中,從而與聚集本身隔開。迭代子模式簡化了聚集的界面。每一個聚集對象都可以有一個或一個以上的迭代子對象,每一個迭代子的迭代狀態可以是彼此獨立的。迭代算法可以獨立于聚集角色變化。

    17、MEDIATOR —四個MM打麻將,相互之間誰應該給誰多少錢算不清楚了,幸虧當時我在旁邊,按照各自的籌碼數算錢,賺了錢的從我這里拿,賠了錢的也付給我,一切就OK啦,俺得到了四個MM的電話。

    調停者模式:調停者模式包裝了一系列對象相互作用的方式,使得這些對象不必相互明顯作用。從而使他們可以松散偶合。當某些對象之間的作用發生改變時,不會立即影響其他的一些對象之間的作用。保證這些作用可以彼此獨立的變化。調停者模式將多對多的相互作用轉化為一對多的相互作用。調停者模式將對象的行為和協作抽象化,把對象在小尺度的行為上與其他對象的相互作用分開處理。

    18、MEMENTO —同時跟幾個MM聊天時,一定要記清楚剛才跟MM說了些什么話,不然MM發現了會不高興的哦,幸虧我有個備忘錄,剛才與哪個MM說了什么話我都拷貝一份放到備忘錄里面保存,這樣可以隨時察看以前的記錄啦。

    備忘錄模式:備忘錄對象是一個用來存儲另外一個對象內部狀態的快照的對象。備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態捉住,并外部化,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態。

    19、OBSERVER  —想知道咱們公司最新MM情報嗎?加入公司的MM情報郵件組就行了,tom負責搜集情報,他發現的新情報不用一個一個通知我們,直接發布給郵件組,我們作為訂閱者(觀察者)就可以及時收到情報啦

    觀察者模式:觀察者模式定義了一種一隊多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使他們能夠自動更新自己。

    20、STATE —跟MM交往時,一定要注意她的狀態哦,在不同的狀態時她的行為會有不同,比如你約她今天晚上去看電影,對你沒興趣的MM就會說“有事情啦”,對你不討厭但還沒喜歡上的MM就會說“好啊,不過可以帶上我同事么?”,已經喜歡上你的MM就會說“幾點鐘?看完電影再去泡吧怎么樣?”,當然你看電影過程中表現良好的話,也可以把MM的狀態從不討厭不喜歡變成喜歡哦。

    狀態模式:狀態模式允許一個對象在其內部狀態改變的時候改變行為。這個對象看上去象是改變了它的類一樣。狀態模式把所研究的對象的行為包裝在不同的狀態對象里,每一個狀態對象都屬于一個抽象狀態類的一個子類。狀態模式的意圖是讓一個對象在其內部狀態改變的時候,其行為也隨之改變。狀態模式需要對每一個系統可能取得的狀態創立一個狀態類的子類。當系統的狀態變化時,系統便改變所選的子類。

    21、STRATEGY —跟不同類型的MM約會,要用不同的策略,有的請電影比較好,有的則去吃小吃效果不錯,有的去海邊浪漫最合適,單目的都是為了得到MM的芳心,我的追MM錦囊中有好多Strategy哦。

    策略模式:策略模式針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。策略模式把行為和環境分開。環境類負責維持和查詢行為類,各種算法在具體的策略類中提供。由于算法和環境獨立開來,算法的增減,修改都不會影響到環境和客戶端。

    22、TEMPLATE METHOD ——看過《如何說服女生上床》這部經典文章嗎?女生從認識到上床的不變的步驟分為巧遇、打破僵局、展開追求、接吻、前戲、動手、愛撫、進去八大步驟(Template method),但每個步驟針對不同的情況,都有不一樣的做法,這就要看你隨機應變啦(具體實現);

    模板方法模式:模板方法模式準備一個抽象類,將部分邏輯以具體方法以及具體構造子的形式實現,然后聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的子類可以以不同的方式實現這些抽象方法,從而對剩余的邏輯有不同的實現。先制定一個頂級邏輯框架,而將邏輯的細節留給具體的子類去實現。

    23、VISITOR —情人節到了,要給每個MM送一束鮮花和一張卡片,可是每個MM送的花都要針對她個人的特點,每張卡片也要根據個人的特點來挑,我一個人哪搞得清楚,還是找花店老板和禮品店老板做一下Visitor,讓花店老板根據MM的特點選一束花,讓禮品店老板也根據每個人特點選一張卡,這樣就輕松多了;

    訪問者模式:訪問者模式的目的是封裝一些施加于某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構可以保持不變。訪問者模式適用于數據結構相對未定的系統,它把數據結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由的演化。訪問者模式使得增加新的操作變的很容易,就是增加一個新的訪問者類。訪問者模式將有關的行為集中到一個訪問者對象中,而不是分散到一個個的節點類中。當使用訪問者模式時,要將盡可能多的對象瀏覽邏輯放在訪問者類中,而不是放到它的子類中。訪問者模式可以跨過幾個類的等級結構訪問屬于不同的等級結構的成員類。
    轉載人員:Nicholas

    文章來源:http://www.cnblogs.com/obpm/archive/2010/07/12/1776045.html
    posted @ 2010-07-12 21:10 obpm 閱讀(129) | 評論 (0)編輯 收藏

    obpm一鍵生成視圖功能原理

    在obpm系統后臺表單右上角有一個“一鍵生成視圖”功能。實現它的真正目的是為了后臺管理人員方便從實現好的表單中快速生成所有帶值的列的視圖。這樣管理人員就不需要手工新建視圖,然后再添加視圖中的帶值的列。

    實現原理圖:

    在實現原理圖中,我們發現沒有視圖中并沒有不帶值Field4相應的Column4在視圖中,這是因為在視圖中是要根據不同Column顯示不同的值的。如果Column是不帶值的話,那么視圖中就不應該要這個Column,即使是要了,在視圖中沒有意義了。

    實現原理代碼:

    其中代碼路徑是:src-java-cn-myapps-core-dynaform-form-ejb-FormProcessBean.java

    /**

         * 根據表單編號來生成視圖

         * @param formid 表單編號

         * @throws Exception

         */

        public Form oneKeyCreateView(String formid) throws Exception {

               FormProcess formPross = (FormProcess) ProcessFactory.createProcess(FormProcess.class);

               ViewProcess viewPross = (ViewProcess) ProcessFactory.createProcess(ViewProcess.class);

              

               Form form = (Form) formPross.doView(formid);//獲得form

               Collection formfield=form.getValueStoreFields();//獲得form存儲值的field

              

               //新建視圖

               View view = new View();

               if (view.getId() == null || view.getId().trim().length() <= 0) {

                  view.setId(Sequence.getSequence());//設置視圖的ID

                  view.setSortId(Sequence.getTimeSequence());//設置視圖的排序ID     }

                view.setName(form.getName());//把表單的名字賦給視圖

                view.setOpenType(view.OPEN_TYPE_NORMAL); //設置視圖打開類型-普通類型

                view.setLastmodifytime(new Date());//最后修改日期

                view.setApplicationid(form.getApplicationid());//把表單應用程序Id賦給視圖的應用程序Id

                view.setModule(form.getModule());//把表單模塊Id賦給視圖的模塊ID

                view.setPagelines("10");//設置視圖的分頁每頁顯示10條數據

                view.setShowTotalRow(true); //是否顯示總共條數數據

                view.setPagination(true); //是否分頁顯示

                view.setRelatedForm(form.getId());//把表單ID賦給視圖的映射表單,從而映射了該表單

              

               

                //將表單中對應有值的列轉換為視圖的列

                int i=0;

               for(Iterator iterator=formfield.iterator();iterator.hasNext();){

                  FormField field=(FormField)iterator.next();

                 

                  Column column = new Column();

                  if (column.getId() == null || column.getId().trim().length() <= 0) {

                  column.setId(Sequence.getSequence());

                  column.setOrderno(i);

                  }

                  if(field.getDiscript()!=null && !field.getDiscript().equals("")){//如果該表單中帶值Field有描述的話,就作為視圖Column,否則的用Field名稱

                  column.setName(field.getDiscript());

                      }else{

                  column.setName(field.getName());

                      }

                  column.setFormid(form.getId());//把表單中的ID賦給Column的表單ID

                  column.setApplicationid(form.getApplicationid());//把表單中應用程序的ID賦給Column的表單應用程序ID

     

                  column.setFieldName(field.getName());  //把表單中的名稱賦給Column的表單名稱

     

                  column.setParentView(view.getId());//將視圖ID賦給Column的父視圖

     

                 

                  view.getColumns().add(column); //將視圖和Column關聯

                  i++;

               }

              

              

               //分別創建兩個按鈕  新建,刪除

               Activity activityCreate = new Activity();

               if (activityCreate.getId() == null || activityCreate.getId().trim().length() <= 0) {

                  activityCreate.setId(Sequence.getSequence());

                  activityCreate.setOrderno(0);

               }

               activityCreate.setApplicationid(form.getApplicationid());

               activityCreate.setName("新建");

               activityCreate.setParentView(view.getId());

               activityCreate.setType(ActivityType.DOCUMENT_CREATE);

               activityCreate.setOnActionForm(form.getId());

              

               view.getActivitys().add(activityCreate); //將視圖和新建按鈕關聯

              

              

               Activity activityDelete = new Activity();

               if (activityDelete.getId() == null || activityDelete.getId().trim().length() <= 0) {

                  activityDelete.setId(Sequence.getSequence());

                  activityDelete.setOrderno(1);

               }

               activityDelete.setApplicationid(form.getApplicationid());

               activityDelete.setName("刪除");

               activityDelete.setParentView(view.getId());

               activityDelete.setType(ActivityType.DOCUMENT_DELETE);

              

               view.getActivitys().add(activityDelete); //將視圖和刪除按鈕關聯

              

              

               viewPross.doCreate(view); //創建視圖

                return form;

        }

     

    后臺效果圖:

    表單:

    視圖:

    視圖列:

    視圖按鈕:

    前臺效果:

    視圖:

     

    表單:

     

     

    原創人員:Denny


    文章來源:http://www.cnblogs.com/obpm/archive/2010/07/12/1775453.html
    posted @ 2010-07-12 02:08 obpm 閱讀(417) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 在线免费观看国产视频| 国产黄色免费观看| 中日韩亚洲人成无码网站| 亚洲日韩中文字幕天堂不卡| 亚洲色偷偷偷网站色偷一区| 亚洲成人动漫在线| 亚洲黄网站wwwwww| 亚洲一区二区三区免费在线观看| 亚洲av无码一区二区三区天堂古代| 亚洲福利一区二区三区| 亚洲另类视频在线观看| 久久精品私人影院免费看| 精品一区二区三区免费| 日韩精品内射视频免费观看| 亚洲精品无码久久久久| 国产亚洲日韩一区二区三区| 久久精品国产亚洲AV麻豆王友容| 亚洲国产一区在线| 久久精品国产亚洲AV久| 亚洲精品乱码久久久久久V| 美女18毛片免费视频| 久久国产精品免费| 一级毛片免费毛片一级毛片免费 | 亚洲福利在线视频| 亚洲无线一二三四区| 亚洲色无码国产精品网站可下载| 毛片基地免费观看| 免费大黄网站在线看| 久久久久久久综合日本亚洲| 亚洲精品视频专区| 亚洲国产精品无码第一区二区三区| 免费人成在线观看播放a| 香蕉视频在线免费看| 曰批视频免费40分钟试看天天| 最近中文字幕免费mv视频7| 亚洲国产天堂久久综合| 亚洲AV乱码久久精品蜜桃| 亚洲综合av一区二区三区不卡| 色老头综合免费视频| 50岁老女人的毛片免费观看| 国产免费变态视频网址网站|