看了“使用hibernate实现树形结构无限级分类”这篇文章后,我也想将自己在所有开发的项目中使用的功能模块树的实现方法以及完整DEMO(含源码)贴出来和大家分享。其实在我的博客里是老早贴出来的,由于时间关系没好好整理。
功能模块树是几乎在每个项目里都要用到的东西,利用Dojo的好处就是可以实现树的子节点的动态加载,这在树节点很多的情况下是很有用的。
下载附件二dojotree.rar,解压后将distdojotree.war部署到应用服务器即可浏览DEMO,DEMO中内置HSQLDB数据库,启动时自动加载。DEMO运行截图见附件一。
一、tree.jsp主要代码
1、首先在head中导入Dojo库(dojo.js)和TreeWidget
<script>"text/javascript"src="ajax/dojo/dojo.js">
<script>"text/javascript">
dojo.require("dojo.widget.Tree");
dojo.require("dojo.widget.TreeNode");
dojo.require("dojo.widget.TreeSelector");
dojo.require("dojo.widget.TreeRPCController");
dojo.require("dojo.widget.TreeLoadingController");
dojo.require("dojo.widget.TreeContextMenu");
</script>
2、在body中放置TreeWidget,TreeLoadingController中的RPCUrl="treeServlet"为从后台获取数据的servlet名称,TreeNode中的expandLevel表示树初始张开级别
<divdojoType="TreeLoadingController"RPCUrl="treeServlet"widgetId="treeController"DNDController="create"><>div>
<divdojoType="TreeSelector"widgetId="treeSelector"><>div>
<divdojoType="Tree"DNDMode="between"selector="treeSelector"widgetId="bandTree"controller="treeController">
<divdojoType="TreeNode"title="root"widgetId="root"objectId="root"isFolder="true"childIconSrc="images/comm.gif"expandLevel="1"/>
3、建立TreeSelector事件处理函数
functiontreeSelectFired(){
//getareferencetothetreeSelectorandgettheselectednode
vartreeSelector=dojo.widget.manager.getWidgetById('treeSelector');
vartreeNode=treeSelector.selectedNode;
//getareferencetothesongDisplaydiv
varhostDiv=document.getElementById("songDisplay");
varisFolder=treeNode['isFolder'];
//alert(isFolder);
if(!isFolder){
varsong=treeNode['title'];
varurl=treeNode['url'];
link(url);
}else{
}
}
4、将select事件处理函数关联到treeSelector
functioninit(){
//getareferencetothetreeSelector
vartreeSelector=dojo.widget.manager.getWidgetById('treeSelector');
//connecttheselecteventtothefunctiontreeSelectFired()
dojo.event.connect(treeSelector,'select','treeSelectFired');
}
dojo.addOnLoad(init);
二、主要java代码及数据结构
1、Gnmk.java中tree的属性
privateStringid;
privateStringgnmkdm;//功能模块代码
privateStringgnmksm;//功能模块说明
privateStringgnmktb;//功能模块图标
privateStringgnmklj;//功能模块路径
privateStringgnmkmc;//功能模块名称
privateStringgnmksj;//功能模块上级代码
privateStringgnmkbz;//功能模块标志(‘N'为叶节点)
2、HSQLDB内存数据库加载SQL(db.sql)
CREATETABLEGNMK(IDVARCHAR,GNMKDMVARCHAR,GNMKMCVARCHAR,GNMKLJVARCHAR,GNMKTBVARCHAR,GNMKBZVARCHAR,GNMKSJVARCHAR);
INSERTINTOGNMKVALUES('d098a59f0b765c30010b765d6b780001','01','一级目录1',null,'system.gif','Y','');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830001','0101','二级目录1','cxtjAction.do','system.gif','N','01');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830001','0102','二级目录2','cxtjAction.do','system.gif','N','01');
INSERTINTOGNMKVALUES('d098a59f0b765c30010b765d6b780002','02','一级目录2',null,'system.gif','Y','');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830002','0201','二级目录1','cxtjAction.do','system.gif','N','02');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830002','0202','二级目录2','cxtjAction.do','system.gif','Y','02');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830002','020201','三级目录1','cxtjAction.do','system.gif','N','0202');
INSERTINTOGNMKVALUES('d098a59f0b765e68010b765fda830002','020202','三级目录2','cxtjAction.do','system.gif','N','0202');
3、TreeServlet.java主要代码,在getGnmkByParent(Stringgnmksj)方法中可以实现自己的业务,DEMO中使用GnmkDAO
publicclassTreeServletextendsHttpServlet{
privatestaticfinallongserialVersionUID=1L;
protectedvoiddoGet(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException{
Stringaction=request.getParameter("action");
System.out.println("actionb=>"+action);
System.out.println("actionb=>"+action);
Stringdata=request.getParameter("data");
if(action.equalsIgnoreCase("getChildren")){
JSONTokenerjsonTokener=newJSONTokener(data);
JSONObjectjsonObject=(JSONObject)jsonTokener.nextValue();
JSONObjectparentNodeObject=(JSONObject)jsonObject.get("node");
response.setContentType("text/json;charset=gb2312");
PrintWriterout=response.getWriter();
out.write(getChildren(parentNodeObject));
}else{
}
}
privateStringgetChildren(JSONObjectparentNodeObject){
JSONArrayresult=newJSONArray();
StringparentObjectId=parentNodeObject.getString("objectId");//id唯一
//StringparentWidgetId=parentNodeObject.getString("widgetId");//dm
parentObjectId=parentObjectId.equalsIgnoreCase("root")?""
:parentObjectId;
System.out.println("parentObjectId=>"+parentObjectId);
//获取子功能模块
ListlistGnmk=this.getGnmkByParent(parentObjectId);
System.out.println("listGnmk=>"+listGnmk.size());
if(listGnmk!=null){
IteratoritGnmk=listGnmk.iterator();
while(itGnmk.hasNext()){
Gnmkqxgnmk=(Gnmk)itGnmk.next();
try{
JSONObjectjsonGnmkObject=newJSONObject();
Stringgnmkbz=qxgnmk.getGnmkbz();
booleanisFolder=gnmkbz.equalsIgnoreCase("Y")?true
:false;
jsonGnmkObject.put("title",qxgnmk.getGnmkmc());
jsonGnmkObject.put("isFolder",isFolder);
jsonGnmkObject.put("widgetId",qxgnmk.getGnmkdm());
jsonGnmkObject.put("objectId",qxgnmk.getGnmkdm());
jsonGnmkObject.put("childIconSrc","images/"
+qxgnmk.getGnmktb());
jsonGnmkObject.put("url",qxgnmk.getGnmklj());
result.put(jsonGnmkObject);
}catch(JSONExceptione){
e.printStackTrace();
}
}
}
returnresult.toString();
}
privateListgetGnmkByParent(Stringgnmksj){
GnmkDAOgnmkDao=newGnmkDAO();
returngnmkDao.getGnmkByParent(gnmksj);
}
}
三、关于DEMO的其它配置说明
1、实现javax.servlet.ServletContextListener接口的contextInitialized方法来加载HSQLDB及其数据,ContextListener.java主要代码
publicvoidcontextInitialized(ServletContextEventevent){
try{
//loadthedriver
Class.forName("org.hsqldb.jdbcDriver");
//createthetableandaddsampledata
InputStreamReaderin=newInputStreamReader(getClass().getClassLoader().getResourceAsStream("db.sql"));
BufferedReaderreader=newBufferedReader(in);
DBUtils.setupDatabase(reader);
}catch(ClassNotFoundExceptione){
e.printStackTrace();
}
}
2、web.xml相关配置
<listener>
<listener-class>
dojo.sample.ContextListener
<><>listener-class>
<>>
下载