Extjs Tree + JSON + Struts2
最近尝试用extjs来展示树状菜单。着实花了一番功夫。树状菜单的菜单项需要动态加载,而目前版本的extjs中只支持JSON格式的数据。查了一些资料,决定使用struts2的json-plugin。首先按照例子做了一个,但是结果就是不成功,界面上只出来了一个js中生成的root节点,不能加载从后台生成的数据。研究后发现是数据格式有问题。使用json-plugin生成的数据格式如下:
{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}
而extjs需要的数据格式如下:
[{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}]
区别很小,就只相差最外面的两个方括号。但是少了这两个方括号,在json中,含义迥然不同,前者表示一个对象,而后者表示一个数组。而extjs中 tree的dataloader需要的数据必须是一个数组。而这样的数据格式是json-plugin自动生成的,无法改变。所以,我最后放弃了json -plugin,转而使用json-lib来解决这个问题。
1. 下载json-lib, http://json-lib.sourceforge.net/
2. lib目录下的jar文件清单:
commons-beanutils-1.7.0.jar
commons-collections-3.2.jar
commons-digester-1.6.jar
commons-lang-2.3.jar
commons-logging-1.1.jar
dom4j-1.6.1.jar
ezmorph-1.0.4.jar
freemarker-2.3.8.jar
json-lib-2.2.1-jdk15.jar
log4j-1.2.13.jar
ognl-2.6.11.jar
struts2-core-2.0.11.jar
xml-apis-1.0.b2.jar
xwork-2.0.4.jar
首先配置web.xml
<?
xml version="1.0" encoding="UTF-8"
?>
< web-app version ="2.4" xmlns ="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
< welcome-file-list >
< welcome-file > index.jsp </ welcome-file >
</ welcome-file-list >
< filter >
< filter-name > struts2 </ filter-name >
< filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class >
</ filter >
< filter-mapping >
< filter-name > struts2 </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
</ web-app >
< web-app version ="2.4" xmlns ="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
< welcome-file-list >
< welcome-file > index.jsp </ welcome-file >
</ welcome-file-list >
< filter >
< filter-name > struts2 </ filter-name >
< filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class >
</ filter >
< filter-mapping >
< filter-name > struts2 </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
</ web-app >
然后是struts.xml
<?
xml version="1.0" encoding="UTF-8"
?>
<! DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
< constant name ="struts.devMode" value ="true" />
< constant name ="struts.i18n.encoding" value ="UTF-8" />
< package name ="person" extends ="struts-default" >
< action name ="menus" method ="execute" class ="com.lab.MenuAction" >
< result > /menu.jsp </ result >
</ action >
</ package >
</ struts >
<! DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
< constant name ="struts.devMode" value ="true" />
< constant name ="struts.i18n.encoding" value ="UTF-8" />
< package name ="person" extends ="struts-default" >
< action name ="menus" method ="execute" class ="com.lab.MenuAction" >
< result > /menu.jsp </ result >
</ action >
</ package >
</ struts >
3. 树的节点模型(省略了getter,setter)
public
class
Menu {
private int id;
private String text;
private boolean leaf;
private String cls;
private List < Menu > children;
}
private int id;
private String text;
private boolean leaf;
private String cls;
private List < Menu > children;
}
4. action
package
com.lab;
import java.util.ArrayList;
import java.util.List;
import net.sf.json.JSONArray;
public class MenuAction {
private String menuString;
private List < Menu > menus;
public String execute() {
menus = new ArrayList < Menu > ();
Menu benz = new Menu();
benz.setText( " Benz " );
benz.setCls( " folder " );
benz.setLeaf( false );
benz.setId( 10 );
menus.add(benz);
List < Menu > benzList = new ArrayList < Menu > ();
benz.setChildren(benzList);
Menu menu;
menu = new Menu();
menu.setText( " S600 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 11 );
benzList.add(menu);
menu = new Menu();
menu.setText( " SLK200 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 12 );
benzList.add(menu);
Menu bmw = new Menu();
bmw.setText( " BMW " );
bmw.setCls( " folder " );
bmw.setLeaf( false );
bmw.setId( 20 );
menus.add(bmw);
List < Menu > bmwList = new ArrayList < Menu > ();
bmw.setChildren(bmwList);
menu = new Menu();
menu.setText( " 325i " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 21 );
bmwList.add(menu);
menu = new Menu();
menu.setText( " X5 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 22 );
bmwList.add(menu);
JSONArray jsonObject = JSONArray.fromObject(menus);
try {
menuString = jsonObject.toString();
} catch (Exception e) {
menuString = " ss " ;
}
return " success " ;
}
public String getMenuString() {
return menuString;
}
public void setMenuString(String menuString) {
this .menuString = menuString;
}
}
import java.util.ArrayList;
import java.util.List;
import net.sf.json.JSONArray;
public class MenuAction {
private String menuString;
private List < Menu > menus;
public String execute() {
menus = new ArrayList < Menu > ();
Menu benz = new Menu();
benz.setText( " Benz " );
benz.setCls( " folder " );
benz.setLeaf( false );
benz.setId( 10 );
menus.add(benz);
List < Menu > benzList = new ArrayList < Menu > ();
benz.setChildren(benzList);
Menu menu;
menu = new Menu();
menu.setText( " S600 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 11 );
benzList.add(menu);
menu = new Menu();
menu.setText( " SLK200 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 12 );
benzList.add(menu);
Menu bmw = new Menu();
bmw.setText( " BMW " );
bmw.setCls( " folder " );
bmw.setLeaf( false );
bmw.setId( 20 );
menus.add(bmw);
List < Menu > bmwList = new ArrayList < Menu > ();
bmw.setChildren(bmwList);
menu = new Menu();
menu.setText( " 325i " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 21 );
bmwList.add(menu);
menu = new Menu();
menu.setText( " X5 " );
menu.setCls( " file " );
menu.setLeaf( true );
menu.setId( 22 );
bmwList.add(menu);
JSONArray jsonObject = JSONArray.fromObject(menus);
try {
menuString = jsonObject.toString();
} catch (Exception e) {
menuString = " ss " ;
}
return " success " ;
}
public String getMenuString() {
return menuString;
}
public void setMenuString(String menuString) {
this .menuString = menuString;
}
}
5. menu.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:property value="menuString" escape="false"/>
6. html页面和js
我使用的就是extjs的example中的reorder.html和reorder.js,更改了reorder.js中treeloader的dataurl: menus.action
<
html
>
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=iso-8859-1" >
< title > Reorder TreePanel </ title >
< link rel ="stylesheet" type ="text/css" href ="extjs/resources/css/ext-all.css" />
<!-- GC -->
<!-- LIBS -->
< script type ="text/javascript" src ="extjs/adapter/ext/ext-base.js" ></ script >
<!-- ENDLIBS -->
< script type ="text/javascript" src ="extjs/ext-all.js" ></ script >
< script type ="text/javascript" src ="reorder.js" ></ script >
<!-- Common Styles for the examples -->
< link rel ="stylesheet" type ="text/css" href ="extjs/resources/css/example.css" />
</ head >
< body >
< script type ="text/javascript" src ="../examples.js" ></ script > <!-- EXAMPLES -->
< h1 > Drag and Drop ordering in a TreePanel </ h1 >
< p > This example shows basic drag and drop node moving in a tree. In this implementation there are no restrictions and
anything can be dropped anywhere except appending to nodes marked " leaf " (the files). < br ></ p >
< p > Drag along the edge of the tree to trigger auto scrolling while performing a drag and drop. </ p >
< p > In order to demonstrate drag and drop insertion points, sorting was < b > not </ b > enabled. </ p >
< p > The data for this tree is asynchronously loaded with a JSON TreeLoader. </ p >
< p > The js is not minified so it is readable. See < a href ="reorder.js" > reorder.js </ a > . </ p >
< div id ="tree-div" style ="overflow:auto; height:300px;width:250px;border:1px solid #c3daf9;" ></ div >
</ body >
</ html >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=iso-8859-1" >
< title > Reorder TreePanel </ title >
< link rel ="stylesheet" type ="text/css" href ="extjs/resources/css/ext-all.css" />
<!-- GC -->
<!-- LIBS -->
< script type ="text/javascript" src ="extjs/adapter/ext/ext-base.js" ></ script >
<!-- ENDLIBS -->
< script type ="text/javascript" src ="extjs/ext-all.js" ></ script >
< script type ="text/javascript" src ="reorder.js" ></ script >
<!-- Common Styles for the examples -->
< link rel ="stylesheet" type ="text/css" href ="extjs/resources/css/example.css" />
</ head >
< body >
< script type ="text/javascript" src ="../examples.js" ></ script > <!-- EXAMPLES -->
< h1 > Drag and Drop ordering in a TreePanel </ h1 >
< p > This example shows basic drag and drop node moving in a tree. In this implementation there are no restrictions and
anything can be dropped anywhere except appending to nodes marked " leaf " (the files). < br ></ p >
< p > Drag along the edge of the tree to trigger auto scrolling while performing a drag and drop. </ p >
< p > In order to demonstrate drag and drop insertion points, sorting was < b > not </ b > enabled. </ p >
< p > The data for this tree is asynchronously loaded with a JSON TreeLoader. </ p >
< p > The js is not minified so it is readable. See < a href ="reorder.js" > reorder.js </ a > . </ p >
< div id ="tree-div" style ="overflow:auto; height:300px;width:250px;border:1px solid #c3daf9;" ></ div >
</ body >
</ html >
js:
/*
* Ext JS Library 2.0.1
* Copyright(c) 2006-2008, Ext JS, LLC.
* [email protected]
*
* http://extjs.com/license
*/
Ext.onReady( function (){
// shorthand
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
el:'tree - div',
autoScroll: true ,
animate: true ,
enableDD: true ,
containerScroll: true ,
loader: new Tree.TreeLoader({
dataUrl:'http: // localhost:8080/lab/menus.action'
})
});
// set the root node
var root = new Tree.AsyncTreeNode({
text: 'Ext JS',
draggable: false ,
id:'source'
});
tree.setRootNode(root);
// render the tree
tree.render();
root.expand();
});
* Ext JS Library 2.0.1
* Copyright(c) 2006-2008, Ext JS, LLC.
* [email protected]
*
* http://extjs.com/license
*/
Ext.onReady( function (){
// shorthand
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
el:'tree - div',
autoScroll: true ,
animate: true ,
enableDD: true ,
containerScroll: true ,
loader: new Tree.TreeLoader({
dataUrl:'http: // localhost:8080/lab/menus.action'
})
});
// set the root node
var root = new Tree.AsyncTreeNode({
text: 'Ext JS',
draggable: false ,
id:'source'
});
tree.setRootNode(root);
// render the tree
tree.render();
root.expand();
});