References: 《Struts 2与AJAX(第二部分)》[1],《STRUTS2树状菜单实现》[2],《Dojo入门教程之dojo.io.bind详解》[3]
关键的标签:<sx:tree />,其实这是一个dojo plugin 的标签,Struts2 提供了对于dojo的支持。
部分属性参数说明:完全版请移步这里
参数名 | 参数类型 | 是否必须 | 说明 |
id | String | flase | The id to use for the element |
rootNode | String | false | 树的根节点 |
nodeIdProperty | String | false | 节点的id |
nodeTitleProperty | String | false | 节点的名字 |
childCollectionProperty | String | false | 子节点集合 |
这个标签的通常用法:静态树,动态数和Ajax树。静态树很简单,掠过;重点记录一下动态树的构造和使用;Ajax树以后再试。严格意义上来说静态和动态树都不是Ajax数,他们都是在输出页面时将全部节点加载到其中,而不是在父节点展开时通过XHR(XMLHttpRequest)获取节点数据[1]。
构造动态树所需要的属性参数:
<s:treeid="..."rootNode="..."nodeIdProperty="..."nodeTitleProperty="..."childCollectionProperty="..." />
实例:左边是一个树状结构(菜单),点击叶子节点在右边DIV输出对应的id和name
@Struts.xml片段:
<action name="DynamicTree" class="tree.DynamicTreeAction"><result name="success">/tree/tree.jsp</result></action><action name="dynamicTreeSelect" class="tree.DynamicTreeSelectAction"><result name="success">/tree/dynamicTreeSelect.jsp</result></action>
tree.DynamicTreeAction.java代码:
package tree;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
public class DynamicTreeAction extends ActionSupport {private static final long serialVersionUID = -8382165565102144980L;private StrutsTreeNode root;
public StrutsTreeNode getRoot() {
return StrutsTreeNode.getById("1");}@Overridepublic String execute() {
return SUCCESS;
}}
这个Action里面最关键的是要定义返回根节点的方法(getRoot),对应于<sx:tree />中rootNode的取值
@StrutsTreeNode.java的代码:
这是节点实体的类,关键在实现了方法 getId(),getName()和getChildren(),对应于<sx:tree />中nodeIdProperty,nodeTitleProperty和childCollectionProperty的取值。package tree;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StrutsTreeNode {private String name;
private List<StrutsTreeNode> children;
private String id;
private static Map<String, StrutsTreeNode> nodeMap = new HashMap<String, StrutsTreeNode>();static {
new StrutsTreeNode(1, "省总公司",new StrutsTreeNode(2, "地市1分公司",new StrutsTreeNode(3, "桥东区办事处",new StrutsTreeNode(4, "市场组"),new StrutsTreeNode(7, "客服组"),new StrutsTreeNode(8, "技术组")),new StrutsTreeNode(9, "开发区办事处",new StrutsTreeNode(10, "市场组"),new StrutsTreeNode(11, "客服组"),new StrutsTreeNode(12, "技术组"),new StrutsTreeNode(13, "后勤组"))),new StrutsTreeNode(14, "地市2分公司",new StrutsTreeNode(15, "软件开发组"),new StrutsTreeNode(16, "软件测试组"),new StrutsTreeNode(17, "售后服务组"),new StrutsTreeNode(18, "市场拓展组"),new StrutsTreeNode(19, "财物组")));}public static StrutsTreeNode getById(String id) {return nodeMap.get(id);
}public StrutsTreeNode(int id,String name,StrutsTreeNode...children) {setName(name);setId(Integer.toString(id));this.children=new ArrayList<StrutsTreeNode>();for(StrutsTreeNode child:children){
this.children.add(child);
}nodeMap.put(Integer.toString(id), this);
}public void setId(String id) {this.id = id;
}public String getId() {
return id;
}public void setName(String name) {this.name = name;
}public String getName() {
return name;
}public List<StrutsTreeNode> getChildren() {
return this.children;}public boolean addChildren(StrutsTreeNode node) {return children.add(node);
}public void setChildren(List<StrutsTreeNode> children) {this.children = children;
}}
@展示Tree的JSP页面代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sx" uri="/struts-dojo-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>My Tree Test</title>
<sx:head />
<script language="JavaScript" type="text/javascript">1: function treeNodeSelected(node) {2: /*判断被选中节点是否是叶子节点,不是则展开*/3: if (node.node.children.length > 0) {4: node.node.expand();
5: return;6: }
7: dojo.io.bind({
8: url : "<s:url value='dynamicTreeSelect.action'/>?nodeId="9: + node.node.widgetId,
10: load : function(type, data, evt) {11: var divDisplay = dojo.byId("showDiv");12: divDisplay.innerHTML = data;
13: },
14: mimeType : "text/html"15: });
16: }
17: /*订阅选择节点后发布的主题*/18: dojo.event.topic.subscribe("treeSelected", treeNodeSelected);</script>
</head>
<body>
<h2>Dynamic Tree Example</h2>
<div style="float: left; margin-right: 100px; width: 20%;">
<sx:tree id="ServiceList" rootNode="root" nodeTitleProperty="name"
nodeIdProperty="id" childCollectionProperty="children"
treeSelectedTopic="treeSelected" />
<!--最后一个属性是在选择节点之后publish一个主题-->
</div>
<div style="float: left" id="showDiv"></div><!--用于回显返回的页面-->
</body>
</html>
这里的核心除了<sx:tree>标签之外,就是那一段js代码了,这段基于DOJO的JS代码完成了点击/选择一个节点之后要做的动作,其中dojo.io.bind是AJAX中最为重要和有用的函数,dojo.io.bind这个类是用来处理客户端与服务器间通讯[3],本例中完成了将AJAX请求发到dynamicTreeSelectAction,运行结果显示在showDiv内的工作。至于被选择的节点有什么样的属性,给个截图看看:
这些节点有什么样的方法呢……我只找到了expand()方法,至于其他的应该能在源码里看到,可惜不太明白JS……
***************8下面就是处理选择的节点的Action和JSP*********************
tree.DynamicTreeSelectAction.java
package tree;
import com.opensymphony.xwork2.ActionSupport;
public class DynamicTreeSelectAction extends ActionSupport {private static final long serialVersionUID = -8085539924385164713L;private String nodeId;
private StrutsTreeNode currentNode;
public void setNodeId(String nodeId) {this.nodeId = nodeId;
}public String getNodeId() {
return nodeId;
}public String execute() throws Exception {currentNode = StrutsTreeNode.getById(nodeId);return SUCCESS;
}public String getNodeName() {
return currentNode != null ? currentNode.getName(): "Node not found";
}}
dynamicTreeSelect.jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
Id:<s:property value="%{nodeId}" /><br/>
Name:<s:property value="%{nodeName}" /><br/>
OK了 这样就可以完成测试了
结果图: