使用S2SH整合EXT的步骤如下:
1):创建表exttree,表结构如下:
drop table if exists exttree;
CREATE TABLE exttree(
id bigint(11) auto_increment primary key,
parentId bigint(11) NOT NULL,
title varchar(255) default NULL,
number bigint(11) default NULL,
leaf int(4) default NULL,
url varchar(255) default NULL
);
insert into `exttree` values(null,-1,'Root',0,0,null);
insert into `exttree` values(null,1,'音乐',0,0,null);
insert into `exttree` values(null,2,'轻金属',1,1,null);
insert into `exttree` values(null,2,'重金属',2,1,null);
insert into `exttree` values(null,2,'R&B',3,1,null);
insert into `exttree` values(null,1,'体育',0,0,null);
insert into `exttree` values(null,6,'篮球',1,1,null);
insert into `exttree` values(null,6,'足球',2,1,null);
insert into `exttree` values(null,6,'体操',3,1,null);
insert into `exttree` values(null,1,'美食',0,0,null);
insert into `exttree` values(null,10,'中国菜',0,0,null);
insert into `exttree` values(null,11,'青椒找肉',0,1,null);
insert into `exttree` values(null,10,'日本菜',0,0,null);
insert into `exttree` values(null,13,'河夫烤鱼',0,1,null);
insert into `exttree` values(null,10,'法国菜',0,0,null);
insert into `exttree` values(null,15,'爆炒蜗牛',0,1,null);
PS:NUMBER为节点之间的排序,ParentID和leaf为父节点和子节点的代码。
2)后台数据处理接口:
package com.exttree.dao;
import java.util.List;
import com.exttree.pojo.Exttree;
/**
* Ext访问数据库接口封装
*
* @author BruceLeey
*
*/
public interface IExtTreeDemo {
/**
* 根据ID查找对象
*
* @param id
* @return
* @throws Exception
*/
public Exttree findById(Long id) throws Exception;
/**
* 根据父节点查询所有子节点列表
*
* @param parentId
* @return
* @throws Exception
*/
public List<Exttree> findChildById(Long parentId) throws Exception;
/**
* 保存节点
*
* @param node
* @throws Exception
*/
public void save(Exttree node) throws Exception;
/**
* 根据ID删除子节点
*
* @param node
* @throws Exception
*/
public void removeChildById(Exttree node) throws Exception;
/**
* 修改节点
*
* @param node
* @throws Exception
*/
public void modify(Exttree node) throws Exception;
/**
* 执行繁杂的修改语句
*
* @param hql
* @throws Exception
*/
public void modifyBySQL(String hql) throws Exception;
/**
* 移除节点
*
* @param id
* @throws Exception
*/
public void ajaxRemoveNode(Long id) throws Exception;
实现类如下:
package com.exttree.dao;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.exttree.pojo.Exttree;
public class ExtTreeDemoImpl extends HibernateDaoSupport implements IExtTreeDemo {
public Exttree findById(Long id) throws Exception {
List<Exttree> list = this.getHibernateTemplate().find(
"from Exttree ext where ext.id=?", id);
return list.size() >= 1 ? list.get(0) : null;
}
public List<Exttree> findChildById(Long parentId) throws Exception {
return this.getHibernateTemplate().find(
"from Exttree ext where ext.parentId=?", parentId);
}
public void modify(Exttree node) throws Exception {
this.getHibernateTemplate().merge(node); //相当于SaveOrUpdate
}
public void removeChildById(Exttree node) throws Exception {
String hql = "delete from Exttree tree where tree.id="+node.getId();
Session session = this.getHibernateTemplate().getSessionFactory()
.openSession();
Transaction tm = session.beginTransaction();
tm.begin();
Query query = session.createQuery(hql);
query.executeUpdate();
tm.commit();
}
public void save(Exttree node) throws Exception {
this.getHibernateTemplate().save(node);
}
public void modifyBySQL(String hql) throws Exception {
Session session = this.getHibernateTemplate().getSessionFactory()
.openSession();
Transaction tm = session.beginTransaction();
tm.begin();
Query query = session.createSQLQuery(hql);
query.executeUpdate();
tm.commit();
}
public void ajaxRemoveNode(Long id) throws Exception {
List<Exttree> list = this.findChildById(id);
for (Exttree object : list) { // 移除子节点
ajaxRemoveNode(object.getId());
}
Exttree tree = new Exttree(); // 需改进
tree.setId(id);
this.removeChildById(tree); // 父节点始终会移除
}
}
需要注意的是,如果将removeChildById改成这样:
public void removeChildById(Exttree node) throws Exception {
this.getHibernateTemplate().delete(node);
}
将会报此异常:a different object with the same identifier value was already associated with the session
内存中存在两个实例,但是不是同一个对象,因此Hibernate不知道该删除哪一个,因为在删除之前已构建一个实例,删除时再传递需要删除的对象,因为内存地址不一样,因此报这样的错误,解决办法是重新打开一个Session或者清空当前Session。
修改时也是如此,可使用Hibernate的getHibernateTemplate().merge(node);
业务层接口如下:
package com.exttree.service;
import java.util.List;
import com.exttree.pojo.Exttree;
/**
* EXTTree 业务逻辑接口封装
*
* @author BruceLeey
*
*/
public interface IExtTreeDemoService {
/**
* 异步修改标题
*
* @param id
* @param title
* @throws Exception
*/
public void ajaxModifyTitle(Long id, String title) throws Exception;
/**
* 异步移除父节点
*
* @param parentId
* @throws Exception
*/
public void ajaxRemoveParentById(Long parentId) throws Exception;
/**
* 异步移动节点
*
* @param id
* @param oldParentId
* @param newParentId
* @param nodeIndex
* @throws Exception
*/
public void ajaxMoveNode(Long id, Long oldParentId, Long newParentId,
Long nodeIndex) throws Exception;
/**
* 节点向上
*
* @param parentId
* @param minIndex
* @param maxIndex
* @throws Exception
*/
public void upNode(int parentId, int minIndex, int maxIndex)
throws Exception;
/**
* 节点向下
*
* @param parentId
* @param minIndex
* @param maxIndex
* @throws Exception
*/
public void downNode(int parentId, int minIndex, int maxIndex)
throws Exception;
/**
* 根据ID查找对象
*
* @param id
* @return
* @throws Exception
*/
public Exttree findById(Long id) throws Exception;
/**
* 根据父节点查询所有子节点列表
*
* @param parentId
* @return
* @throws Exception
*/
public List<Exttree> findChildById(Long parentId) throws Exception;
/**
* 修改节点
*
* @param node
* @throws Exception
*/
public void modify(Exttree node) throws Exception;
/**
* 保存节点
*
* @param node
* @throws Exception
*/
public void save(Exttree node) throws Exception;
}
实现:
package com.exttree.service.impl;
import java.util.List;
import com.exttree.dao.IExtTreeDemo;
import com.exttree.pojo.Exttree;
import com.exttree.service.IExtTreeDemoService;
public class ExtTreeDemoServiceImpl implements IExtTreeDemoService {
private IExtTreeDemo treeDAO = null;
public IExtTreeDemo getTreeDAO() {
return treeDAO;
}
public void setTreeDAO(IExtTreeDemo treeDAO) {
this.treeDAO = treeDAO;
}
public void ajaxModifyTitle(Long id, String title) throws Exception {
Exttree node = treeDAO.findById(id);
if (!title.equals(node.getTitle())) { // 当节点标题确认修改了后调用
node.setTitle(title);
treeDAO.modify(node);
}
}
public void ajaxRemoveParentById(Long parentId) throws Exception {
Exttree obj = treeDAO.findById(parentId);
this.downNode(obj.getParentId().intValue(), obj.getNumber().intValue(),
-1);
treeDAO.ajaxRemoveNode(obj.getId()); // 移除父节点
}
public void ajaxMoveNode(Long id, Long oldParentId, Long newParentId,
Long nodeIndex) throws Exception {
Exttree node = treeDAO.findById(id);
int minIndex = node.getNumber().intValue();
int maxIndex = nodeIndex.intValue();
if (oldParentId == newParentId && minIndex != maxIndex) {
if (minIndex < maxIndex) {
this.downNode(oldParentId.intValue(), minIndex, maxIndex);
} else if (minIndex > maxIndex) {
maxIndex = minIndex;
minIndex = nodeIndex.intValue();
this.upNode(oldParentId.intValue(), minIndex, maxIndex);
}
node.setNumber(nodeIndex);
treeDAO.modify(node);
}
if (oldParentId != newParentId) {
this.downNode(oldParentId.intValue(), minIndex, -1);
this.upNode(newParentId.intValue(), maxIndex, -1);
node.setNumber(nodeIndex);
node.setParentId(newParentId);
treeDAO.modify(node);
}
}
public void downNode(int parentId, int minIndex, int maxIndex)
throws Exception {
StringBuffer hql = new StringBuffer(
"update exttree set number=number-1 where parentId = ");
hql.append(parentId);
if (maxIndex != -1) {
hql.append(" and number <= ");
hql.append(maxIndex);
}
if (minIndex != -1) {
hql.append(" and number > ");
hql.append(minIndex);
}
treeDAO.modifyBySQL(hql.toString());
}
public void upNode(int parentId, int minIndex, int maxIndex)
throws Exception {
StringBuffer hql = new StringBuffer(
"update exttree set number=number+1 where parentId = ");
hql.append(parentId);
if (maxIndex != -1) {
hql.append(" and number < ");
hql.append(maxIndex);
}
if (minIndex != -1) {
hql.append(" and number >= ");
hql.append(minIndex);
}
treeDAO.modifyBySQL(hql.toString());
}
public Exttree findById(Long id) throws Exception {
return treeDAO.findById(id);
}
public List<Exttree> findChildById(Long parentId) throws Exception {
return treeDAO.findChildById(parentId);
}
public void modify(Exttree node) throws Exception {
treeDAO.modify(node);
}
public void save(Exttree node) throws Exception {
treeDAO.save(node);
}
}
主要的数据访问与业务写好之后,接下来将Web的访问控制写好:
package com.exttree.web;
import org.apache.struts2.ServletActionContext;
import com.exttree.pojo.Exttree;
import com.exttree.service.IExtTreeDemoService;
/**
* Web后端控制器
*
* @author BruceLeey
*
*/
public class ExtTreeAction {
private Exttree extTree = null;
private IExtTreeDemoService service = null;
/**
* 添加节点
*
* @return
*/
public String saveNode() throws Exception {
if (!"".equals(extTree.getId()) && null != extTree.getId()) {
if (service.findById(extTree.getId()) == null) {
return "ERROR";
} else {
service.modify(extTree);
return "SUCCESS";
}
}
service.save(extTree);
return "SUCCESS";
}
/**
* 修改节点
*
* @return
*/
public String modifyNode() throws Exception {
if (null != extTree.getId()) {
ServletActionContext.getRequest().setAttribute("obj",
service.findById(extTree.getId()));
} else {
ServletActionContext.getRequest().setAttribute("obj", extTree);
}
return "EDIT";
}
/**
* 异步获取数据
*
* @return
*/
public String jsonData() throws Exception {
ServletActionContext.getRequest().setAttribute(
"list",
service.findChildById(Long.valueOf(ServletActionContext
.getRequest().getParameter("id"))));
return "JSON";
}
public IExtTreeDemoService getService() {
return service;
}
public void setService(IExtTreeDemoService service) {
this.service = service;
}
public Exttree getExtTree() {
return extTree;
}
public void setExtTree(Exttree extTree) {
this.extTree = extTree;
}
}
Spring配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 配置SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 配置事务的传播属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="ajax*" propagation="REQUIRED" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置事务的切入点 -->
<aop:config>
<aop:pointcut id="allMethod"
expression="execution(* com.exttree.dao.*.*(..))" />
<aop:advisor pointcut-ref="allMethod" advice-ref="txAdvice" />
</aop:config>
<bean id="treeDAO" class="com.exttree.dao.ExtTreeDemoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="treeService"
class="com.exttree.service.impl.ExtTreeDemoServiceImpl">
<property name="treeDAO" ref="treeDAO"></property>
</bean>
<bean id="treeAction" class="com.exttree.web.ExtTreeAction"
scope="prototype">
<property name="service" ref="treeService"></property>
</bean>
</beans>
本例子中使用了DWR作为异步调用服务器方法,DWR框架配置比较简单,因为例子中的对象由Spring托管,因此需要配置DWR与Spring的交互,首先先看Web.xml中的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Spring托管Hibernate的Session -->
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Struts2的前端控制器 -->
<filter>
<filter-name>struts2.x</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2.x</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring配置文件的读取 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- DWR的配置 -->
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>
allowGetForSafariButMakeForgeryEasier
</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
dwr.xml配置与Spring的交互:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr//dwr20.dtd">
<dwr>
<allow>
<!-- javascript属性为用户调研DWR的实例,这里creator交由Spring监管 -->
<create javascript="TreeDWR" creator="spring">
<!-- beanName为DWR配置Spring时特定,value值为在applicationContext.xml中配置的bean -->
<param name="beanName" value="treeService"></param>
<!-- 提供访问的方法 -->
<include method="ajaxModifyTitle" />
<include method="ajaxRemoveParentById" />
<include method="ajaxMoveNode" />
</create>
</allow>
</dwr>
将EXTJS的核心JS导入后,需要手动编写JS的业务,代码如下:
// 全局路径
var basePath = "http://localhost:8080/ext_treedemo";
if(typeof(glbRootPath) != "undefined") {
basePath = glbRootPath;
}
// 扩展窗体
FormEditWin = function() {
var curFormWin;
return {
width : 600,
height : 400,
showAddDirWin : function(parentNode) {
// 显示添加子目录窗口
var number = parentNode.indexOf(parentNode.lastChild) + 1;
var editpage = basePath
+ "/treeAction!modifyNode.action?extTree.parentId="
+ parentNode.id + "&extTree.leaf=0&extTree.number=" + number;
var window = this.createWin("windirnew", "新建目录节点", editpage, function() {
parentNode.reload();
});
window.show();
},
showAddLeafWin : function(parentNode) {
// 显示添加子叶子节点窗口
var number = parentNode.indexOf(parentNode.lastChild) + 1;
var editpage = basePath
+ "/treeAction!modifyNode.action?extTree.parentId="
+ parentNode.id + "&extTree.leaf=1&extTree.number=" + number;
var window = this.createWin("winleafnew", "新建叶子节点", editpage, function() {
parentNode.reload();
});
window.show();
},
showEditDirWin : function(node) {
// 显示目录编辑窗口
var editpage = basePath
+ "/treeAction!modifyNode.action?extTree.id=" + node.id;
var window = this.createWin("win" + node.id, node.text, editpage, function() {
var nodeparent = node.parentNode;
var tree = node.getOwnerTree();
nodeparent.on("expand", function(pnode) {
tree.getNodeById(node.id).select();
}, this, {
single : true
});
node.parentNode.reload();
});
window.show();
},
showEditLeafWin : function(node) {
// 显示叶子节点编辑窗口
var editpage = basePath
+ "/treeAction!modifyNode.action?extTree.id=" + node.id;
var window = this.createWin("win" + node.id, node.text, editpage, function() {
var nodeparent = node.parentNode;
var tree = node.getOwnerTree();
nodeparent.on("expand", function(pnode) {
tree.getNodeById(node.id).select();
}, this, {
single : true
});
node.parentNode.reload();
});
window.show();
},
createWin : function(winId, winTitle, iframePage, closeFun) {
// 供各类型窗口创建时调用
var win = Ext.getCmp(winId);
if (!win) {
win = new Ext.Window( {
id : winId,
title : "菜单编辑窗口-" + winTitle,
width : this.width,
height : this.height,
maximizable : true,
modal : true,
html : "<iframe width='100%' height='100%' frameborder='0' src='"
+ iframePage + "'></iframe>"
});
this.reloadNavNode = closeFun;
}
curFormWin = win;
return win;
},
reloadNavNode : function() {
},
close : function() {
if(curFormWin) {
curFormWin.close();
}
}
}
}();
// 导航树
NavTree = function() {
var nav;
var navEditor;
var leafMenu;
var dirMenu;
var loader;
var root;
var removeFlag = false;
var titleChangeFlag = false;
var nodeSelected;
var mgr;
return {
init : function() {
if(!mgr) {
Ext.Msg.alert("警告提示","请先通过NavTree.setMgr()设置mgr");
return;
}
if(!loader) {
loader = new Ext.tree.TreeLoader( {
url : basePath + '/treeAction!jsonData.action'
});
loader.on('beforeload', function(treeloader, node) {
treeloader.baseParams = {
id : node.id,
method : 'tree'
};
}, this);
}
if(!root) {
root = new Ext.tree.AsyncTreeNode( {
id : '1',
text : "BruceLeey's ExtTree"
});
}
if(!nav) {
nav = new Ext.tree.TreePanel( {
title : "左部导航",
width : 232,
autoScroll : true,
animate : true,
loader : loader,
root : root,
enableDD : true,
listeners : {
'click' : function(node, event) {
if (node.isLeaf()) {
// 为叶子节点时,点击不进入链接
//event.stopEvent();
//alert(node.url);
//window.open('http://www.google.com');
}
}
}
});
// 添加右键菜单
nav.on("contextmenu", this.showTreeMenu);
// 当节点文本改变时触发事件
nav.on("textchange", function(node, newText, oldText) {
if (!titleChangeFlag && newText != oldText) {
mgr.ajaxModifyTitle(node.id, newText, function(success) {
});
}
});
// 当节点移动时触发事件
nav.on("movenode", function(tree, node, oldParent, newParent, index) {
mgr.ajaxMoveNode(node.id, oldParent.id, newParent.id, index);
});
// 当节点删除时触发事件
nav.on("remove", function(tree, parentNode, node) {
if (removeFlag) {
mgr.ajaxRemoveParentById(node.id);
}
});
}
if(!navEditor) {
navEditor = new Ext.tree.TreeEditor(nav, {
allowBlank : false,
ignoreNoChange : true,
blankText : '标题不能为空',
selectOnFocus : true
});
}
this.setLeafMenu();
this.setDirMenu();
},
setMgr : function(manager) {
mgr = manager;
},
getMgr : function() {
return mgr;
},
setLeafMenu: function() {
// 设置叶子菜单
if(!leafMenu) {
leafMenu = new Ext.menu.Menu( {
items : [ {
text : "修改标题",
handler : function() {
navEditor.triggerEdit(nodeSelected);
}
}, "-", {
text : "编辑",
handler : function() {
FormEditWin.showEditLeafWin(nodeSelected);
}
}, "-", {
text : "删除",
handler : this.delTreeItemComfirm
}]
});
}
},
setDirMenu: function() {
// 设置目录菜单
if(!dirMenu) {
dirMenu = new Ext.menu.Menu( {
items : [ {
text : "修改标题",
handler : function() {
navEditor.triggerEdit(nodeSelected);
}
}, "-", {
text : "编辑",
handler : function() {
FormEditWin.showEditDirWin(nodeSelected);
}
}, "-", {
text : "添加叶子节点",
handler : function() {
FormEditWin.showAddLeafWin(nodeSelected);
}
}, "-", {
text : "添加目录节点",
handler : function() {
FormEditWin.showAddDirWin(nodeSelected);
}
}, "-", {
text : "删除",
handler : this.delTreeItemComfirm
}]
});
}
},
showTreeMenu : function(node, e) {
nodeSelected = node;
nodeSelected.select();
if (node.isLeaf()) {
// 显示叶子节点菜单
leafMenu.showAt(e.getPoint());
} else {
// 显示目录节点菜单
dirMenu.showAt(e.getPoint());
}
},
delTreeItemComfirm : function() {
Ext.Msg.confirm("确认删除", "确定要删除所选节点吗?", function(btn) {
if (btn == "yes") {
NavTree.delTreeItem();
}
});
},
delTreeItem : function() {
if (nodeSelected != nav.getRootNode()) {
removeFlag = true;
nodeSelected.remove();
removeFlag = false;
} else {
Ext.Msg.alert("警告", "不能删除树的根节点!");
}
},
show : function() {
nav.render(Ext.getBody());
nav.getRootNode().toggle();
}
}
}();
// 文档加载完毕执行
Ext.onReady(function() {
Ext.BLANK_IMAGE_URL = "../scripts/ext/resources/images/default/s.gif";
if(typeof(TreeDWR)=="undefined") {
Ext.Msg.alert("警告提示","请先设置DWR, Spring加载错误!");
}else {
NavTree.setMgr(TreeDWR);
NavTree.init();
NavTree.show();
}
});
展示代码:
<% @ page contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>导航控制</title>
<link rel="stylesheet" type="text/css"
href="../scripts/ext/resources/css/ext-all.css">
<script type="text/javascript"
src="../scripts/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../scripts/ext/ext-all.js"></script>
<script type="text/javascript" src="../dwr/engine.js"></script>
<script type="text/javascript" src="../dwr/util.js"></script>
<script type="text/javascript" src="../dwr/interface/TreeDWR.js"></script>
<script type="text/javascript"
src="../scripts/treedemo/console-index.js"></script>
</head>
<body>
</body>
</html>