考慮到應用系統會大量使用樹形結構來表現數據,因此,提供一個通用樹形標簽供大家使用。

一、原始樹形組件

關于樹組件的實現有很多方式,此處使用著名的webfx-xtree實現,一個基于AJAX實現的樹形菜單。它的原理就是每次都只加載當前結點下的所有結點,而對開發人員來說,就是只需要按一定的格式,生成一段XML代碼。具體可參考http://webfx.eae.net/dhtml/xtree/index.html

本文對樹形組件做了一些別要的修改和擴充,修改后的樹組件文末提供下載,解壓后放在您的web文件夾common下面。

下文的重點是:通過提供一個jsp taglib,簡化樹結構的實現。

二、數據庫設計

       要實現數據的樹形級別關系,在數據庫設計中,某個數據實體(一條行記錄),有且只有唯一的父實體元素與之對應即可。如機構表sysorg中,字段parentOrgId(可任意命名)為父機構ID,與機構本身的orgId構成樹節點的父子關系。

       通常,我們設置根節點的ID為“0,這樣,一級節點的父ID為“0

       當節點ID無子節點(不是任何一個元素的父節點),此時此節點為最終節點,通常稱之為葉節點(葉子)。

三、實體對象(VO)實現ITreeNode接口

       ValueObject對象需要implements樹節點接口com.basic.common.taglib.tree .ITreeNode

       分別實現如下三個方法:

       //父節點ID

       public String getParentId();

       //節點ID

       public String getNodeId();

       //節點名

       public String getNodeName();

四、實現ITreeService接口

       一個任意的JAVA類,實現com.basic.common.taglib.tree.ITreeService的對象查找接口。

       接口方法:

       public List findAllRecords();

       public ITreeNode findByNodeId(String nodeId);

       實現該方法時候應注意:

1. 排除deleteFlag=’1’的記錄。

2. 當結果集非常大,考慮到性能優化,可對結果集做緩存處理。(可暫不考慮實現,以后統一處理)。

五、注冊樹組件

       com.basic.common.taglib.tree.TreeUtil類中,維護treeMap靜態變量,定義對應treeType的樹名和ITreeService實現類。      

六、jsp中引入標簽

       <%@taglib uri="/WEB-INF/tag.tld" prefix="tag"%>

       <tag:tree treeName="機構" root="<%=node%>" selectType="checkbox" selectAll="true"              treeService="<%=orgService%>"/>

       對各屬性說明如下:

Attribute

Desc

Required

treeName

樹名                           

true

root

展現的起始節點   

如不指定,從根節點展示整個樹形結構

false

selectType

選擇方式

checkbox or radio

false

selectAll

勾選父節點時,自動選擇所有子節點

只有當selectTypecheckbox時該屬性方生效 

默認為false

false

checkedId

標識哪些節點被選中

內容為以“ ,”分隔的nodeId

false

treeService

ITreeService接口的實現類實例

true

treeSql

直接構造樹形sql

false

lazy

是否延遲加載

就是在點擊某節點的時候,才load子節點

false

selectParent

checkbox或者radio而言

當選擇的子,是否自動勾選對應的所有的父

False

1. 點擊某一個節點時,觸發函數selectNode()

       atree.getSelected()返回當前點擊的節點對象nodenode.valuenode.text為對應的節點ID和節點名。

       自行在javascript中重寫selectNode函數。

2. 當使用勾選時,atree.getSelectedChildNodes()返回當前勾選的節點集合。

3. 在頁面中雙擊鼠標左鍵(ondblclick)時,會自動展開或收縮當前樹。

七、直接使用SQL語句構造樹

       實現ITreeServiceItreeNode接口來構造樹,相對有點麻煩。

       利用SqlTreeService可以直接通過sql語句來構造樹,以機構為例,該SQL語句寫法如下:

       select orgid as nodeid,orgname as nodename,parentorgid as parentid from sysorg where deleteflag='0'  
      請注意紅色字符的寫法。

       對某些實體,沒有對應的父IDparentid的構造語句為:0as parentid

       這時,標簽的引用變為:

       <hnisi:tree treeName="×××" treeService="<%=new SqlTreeService("your sql")%>"/> 

八、javascript中引用樹選擇對話框

1、 jsp中引入JS文件:

       <script src="<%=request.getContextPath()%>/js/COMMON.js"></script>

2、 javascript中,定義要引用的Tree對象

3、 Tree對象有如下屬性:

           this.treeType = null;//樹類型 sysorg 。。。

        this.rootId = null;//樹根

        this.checkedId = null;//選中的節點ID“,”分隔

        this.selectType = null;//checkbox or radio

        this.selectAll = null;//是否自動選擇所有子節點

        this.width = null;//對話框的寬度

        this.height = null;//對話框的高度

        this.params = null;//附加參數值,用于TreeService的構造函數

        this.sql = null;//根據特定sql語句直接構造樹

    this.treeName = null;//樹顯示名  

    其中treeTypesql至少設置一個,分別代表兩種的典型構造樹的方式:一種屬性實現ITreeServiceItreeNode兩個接口,然后在TreeUtil.java中注冊樹組件,比較清晰,可以靈活的做一些復雜處理,但稍嫌復雜;另一種是直接傳遞SQL語句構造樹組件,使用起來比較簡單,無需實現相關結構,無需注冊樹組件,但靈活性相對欠缺。

   

    獲取樹選擇器的返回值,可直接調用COMMON.JsgetValues(tree)方法,返回數組ArrayArray[0]為逗號分隔的ID串,Array[1]為逗號分隔的NAME串。

九、文件下載和部署

1、 修改后的webfx-xtree組件,下載,解壓后放于your web/common目錄下。

2、 Java source下載

3、 web.xml中部署一個servlet,用來生成tree xml

<servlet>

       <servlet-name>treexml</servlet-name>

       <servlet-class>

              com.basic.common.taglib.tree.TreeXmlServlet

       </servlet-class>

</servlet>

<servlet-mapping>

       <servlet-name>treexml</servlet-name>

       <url-pattern>/treexml</url-pattern>

</servlet-mapping>