考慮到應用系統會大量使用樹形結構來表現數據,因此,提供一個通用樹形標簽供大家使用。
一、原始樹形組件
關于樹組件的實現有很多方式,此處使用著名的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
|
勾選父節點時,自動選擇所有子節點
只有當selectType為checkbox時該屬性方生效
默認為false
|
false
|
checkedId
|
標識哪些節點被選中
內容為以“ ,”分隔的nodeId串
|
false
|
treeService
|
ITreeService接口的實現類實例
|
true
|
treeSql
|
直接構造樹形sql
|
false
|
lazy
|
是否延遲加載
就是在點擊某節點的時候,才load子節點
|
false
|
selectParent
|
對checkbox或者radio而言
當選擇的子,是否自動勾選對應的所有的父
|
False
|
1. 點擊某一個節點時,觸發函數selectNode()。
atree.getSelected()返回當前點擊的節點對象node,node.value和node.text為對應的節點ID和節點名。
自行在javascript中重寫selectNode函數。
2. 當使用勾選時,atree.getSelectedChildNodes()返回當前勾選的節點集合。
3. 在頁面中雙擊鼠標左鍵(ondblclick)時,會自動展開或收縮當前樹。
七、直接使用SQL語句構造樹
實現ITreeService和ItreeNode接口來構造樹,相對有點麻煩。
利用SqlTreeService可以直接通過sql語句來構造樹,以機構為例,該SQL語句寫法如下:
select orgid as nodeid,orgname as nodename,parentorgid as parentid from sysorg where deleteflag='0'
請注意紅色字符的寫法。
對某些實體,沒有對應的父ID,parentid的構造語句為:‘0’as 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;//樹顯示名
其中treeType和sql至少設置一個,分別代表兩種的典型構造樹的方式:一種屬性實現ITreeService和ItreeNode兩個接口,然后在TreeUtil.java中注冊樹組件,比較清晰,可以靈活的做一些復雜處理,但稍嫌復雜;另一種是直接傳遞SQL語句構造樹組件,使用起來比較簡單,無需實現相關結構,無需注冊樹組件,但靈活性相對欠缺。
獲取樹選擇器的返回值,可直接調用COMMON.Js的getValues(tree)方法,返回數組Array,Array[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>
|