在研究ExtJS Tree动态构建时,按照ExtJS推进的方法是通过TreeLoader加载数据,加载的数据的格式是JSON。在ExtJS的例子check-tree.html中,直接利用后端的check-nodes.json来构建,但是在实际的工程中,有很多是根据不确定的数据内容来构建Tree的。
在Java开发的Web中利用Struts实现后端的servlet,可以提供相应的json格式,实现ExtJS Tree的动态构建。在网上搜索相应的技术文章是,发现利用jsp作为中间转换的例子,url:http://www.blogjava.net/usherlight/archive/2008/02/19/180590.html,觉得不是很理想,在struts2中引入了plugin的机制,有现成的struts-json-plugin包,如何利用action直接通过Ext.Tree.TreeLoader直接加载Tree的数据,在上述文章中,指出:
"最近尝试用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来解决这个问题。"
在struts-json-plugin中返回的数据的确有这个问题,经过仔细分析,在struts-json-plugin的配置中是可以解决这个问题的,通过wrapPrefix和wrapSuffix设置,可以解决上面的问题,struts config文件中的设置如下:
- <package name="test" extends="json-default" >
- <action name="menu" class="com.struts2.action.Menu">
- <result name="success" type="json">
- <param name="excludeNullProperties">true</param>
- <param name="noCache">true</param>
- <param name="wrapPrefix">[</param>
- <param name="wrapSuffix">]</param>
- </result>
- </action>
- </package>
<package name="test" extends="json-default" >
<action name="menu" class="com.struts2.action.Menu">
<result name="success" type="json">
<param name="excludeNullProperties">true</param>
<param name="noCache">true</param>
<param name="wrapPrefix">[</param>
<param name="wrapSuffix">]</param>
</result>
</action>
</package>
action的实现类Menu的代码如下:
- package com.struts2.action;
-
- import java.util.ArrayList;
- import java.util.List;
-
- public class Menu {
- private int id;
- private String text;
- private boolean leaf;
- private String cls;
- private List<Menu> children;
-
- public String execute() throws Exception {
-
- this.id =1;
- this.text="text";
- this.leaf=false;
- this.cls ="cls";
- this.children = new ArrayList<Menu>();
- Menu benz = new Menu();
- benz.setText("Benz");
- benz.setCls("folder");
- benz.setLeaf(true);
- benz.setId(10);
-
- this.children.add(benz);
-
- return "success";
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getText() {
- return text;
- }
- public void setText(String text) {
- this.text = text;
- }
- public boolean isLeaf() {
- return leaf;
- }
- public void setLeaf(boolean leaf) {
- this.leaf = leaf;
- }
- public String getCls() {
- return cls;
- }
- public void setCls(String cls) {
- this.cls = cls;
- }
- public List<Menu> getChildren() {
- return children;
- }
- public void setChildren(List<Menu> children) {
- this.children = children;
- }
- }
package com.struts2.action;
import java.util.ArrayList;
import java.util.List;
public class Menu {
private int id;
private String text;
private boolean leaf;
private String cls;
private List<Menu> children;
public String execute() throws Exception {
// TODO Auto-generated method stub
this.id =1;
this.text="text";
this.leaf=false;
this.cls ="cls";
this.children = new ArrayList<Menu>();
Menu benz = new Menu();
benz.setText("Benz");
benz.setCls("folder");
benz.setLeaf(true);
benz.setId(10);
this.children.add(benz);
return "success";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public boolean isLeaf() {
return leaf;
}
public void setLeaf(boolean leaf) {
this.leaf = leaf;
}
public String getCls() {
return cls;
}
public void setCls(String cls) {
this.cls = cls;
}
public List<Menu> getChildren() {
return children;
}
public void setChildren(List<Menu> children) {
this.children = children;
}
}
利用ExtJS自带的例子check-tree.js,把原来的dataUrl修改为自己实现的struts的Url:
-
-
-
-
-
-
-
- Ext.onReady(function(){
- var tree = new Ext.tree.TreePanel({
- renderTo:'tree-div',
- title: 'My Task List',
- height: 300,
- width: 400,
- useArrows:true,
- autoScroll:true,
- animate:true,
- enableDD:true,
- containerScroll: true,
- rootVisible: false,
- frame: true,
- root: {
- nodeType: 'async'
- },
-
-
- dataUrl: 'http://localhost:8080/Stock3th/menu.action',
-
- listeners: {
- 'checkchange': function(node, checked){
- if(checked){
- node.getUI().addClass('complete');
- }else{
- node.getUI().removeClass('complete');
- }
- }
- },
-
- buttons: [{
- text: 'Get Completed Tasks',
- handler: function(){
- var msg = '', selNodes = tree.getChecked();
- Ext.each(selNodes, function(node){
- if(msg.length > 0){
- msg += ', ';
- }
- msg += node.text;
- });
- Ext.Msg.show({
- title: 'Completed Tasks',
- msg: msg.length > 0 ? msg : 'None',
- icon: Ext.Msg.INFO,
- minWidth: 200,
- buttons: Ext.Msg.OK
- });
- }
- }]
- });
-
- tree.getRootNode().expand(true);
- });
/*!
* Ext JS Library 3.2.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* [email protected]
* http://www.extjs.com/license
*/
Ext.onReady(function(){
var tree = new Ext.tree.TreePanel({
renderTo:'tree-div',
title: 'My Task List',
height: 300,
width: 400,
useArrows:true,
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
rootVisible: false,
frame: true,
root: {
nodeType: 'async'
},
// auto create TreeLoader
dataUrl: 'http://localhost:8080/Stock3th/menu.action',
listeners: {
'checkchange': function(node, checked){
if(checked){
node.getUI().addClass('complete');
}else{
node.getUI().removeClass('complete');
}
}
},
buttons: [{
text: 'Get Completed Tasks',
handler: function(){
var msg = '', selNodes = tree.getChecked();
Ext.each(selNodes, function(node){
if(msg.length > 0){
msg += ', ';
}
msg += node.text;
});
Ext.Msg.show({
title: 'Completed Tasks',
msg: msg.length > 0 ? msg : 'None',
icon: Ext.Msg.INFO,
minWidth: 200,
buttons: Ext.Msg.OK
});
}
}]
});
tree.getRootNode().expand(true);
});
则可以生成所需要的Tree了。我用的各种资源的版本为:ExtJS3.2.0,Struts2.2.1,所需要的支持jar配置文件pom.xml如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- /* * $Id: pom.xml 821140 2009-10-02 19:46:07Z wesw $ * * Licensed to
- the Apache Software Foundation (ASF) under one * or more contributor
- license agreements. See the NOTICE file * distributed with this work
- for additional information * regarding copyright ownership. The ASF
- licenses this file * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance * with
- the License. You may obtain a copy of the License at * *
- http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by
- applicable law or agreed to in writing, * software distributed under
- the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES
- OR CONDITIONS OF ANY * KIND, either express or implied. See the
- License for the * specific language governing permissions and
- limitations * under the License. */
- -->
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>org.tkxing.stock</artifactId>
- <groupId>stock3th</groupId>
- <version>3.0</version>
-
- <properties>
- <struts2-version>2.2.1</struts2-version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.struts</groupId>
- <artifactId>struts2-core</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.struts</groupId>
- <artifactId>struts2-json-plugin</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.1.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache</groupId>
- <artifactId>log4j</artifactId>
- <version>2.1.8</version>
- </dependency>
- <dependency>
- <groupId>javassist</groupId>
- <artifactId>javassist</artifactId>
- <version>3.9.0.GA</version>
- </dependency>
-
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.4</version>
- </dependency>
-
- <dependency>
- <groupId>commons-collections</groupId>
- <artifactId>commons-collections</artifactId>
- <version>3.2.1</version>
- </dependency>
-
- <dependency>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils</artifactId>
- <version>1.7.0</version>
- </dependency>
-
- <dependency>
- <groupId>net.sf.ezmorph</groupId>
- <artifactId>ezmorph</artifactId>
- <version>1.0.6</version>
- </dependency>
-
- </dependencies>
- </project>