随笔-211  评论-26  文章-8  trackbacks-0
SECTION 01 TreeControlNode 简介

每一个树状节点都是一个 TreeControlNode, 主要可以设置


  • name: 这个节点的名称
  • icon: 这个节点的图片
  • label: 这个节点的说明
  • action: 是否具有连结
  • target: 点选后的目标位置 ( frame )
  • expanded: 是否展开
TreeBuilder , 就是产生 TreeControlNode 的集合, 我们可以查看产生 ROOT 的方法.
TreeControlNode root =
  new TreeControlNode("ROOT-NODE",null, 
rootnodeName,"setUpTree.do?select=ROOT-NODE","content", true, domain);
不难发现, 就是这么产生每一个树状节点.


SECTION 02 TreeControl 简介

org.apache.webapp.admin.SetUpTreeAction 是整个 Tree 初始化的重要 action, 第一次取得所有网页资料, 将在这里产生将所有的数据放入 session 之中, 你会看到 servlet.getServletConfig().getInitParameter("...") 将会去采用 web.xml 中的 init-parameter 设置值, 接下来的操作就比较重要, 牵扯也比较广泛, 我们会把 root 放到 TreeControl 之中,
TreeControl control = new TreeControl(root);
简单来说, 先建立一个 Root 的 TreeNode, 我们将根据这个 Root 去设置 TreeControl, 就是整个树状结构的根. 请注意, 最后我们放入 session 的是 treeControl 但是这时候, treeControl 只有 root 这个根节点.


接着, 我们将把整个树状结构放到 treeControl, 该怎么办, 怎么处理 ?


我们利用到 TreeBuilder ( Builder Pattern ) 你会看到一些复杂的代码, 没关系, 他将建立很多 tree 可以在 web.xml 的 treebuilders 之 init-param 中看到 -org.apache.webapp.admin.TomcatTreeBuilder, -org.apache.webapp.admin.resources.ResourcesTreeBuilder, -org.apache.webapp.admin.users.UsersTreeBuilder 这几个 TreeBuilder, 不过我只说明 UsersTreeBuilder 就足够让大家了解了. 基本上,我们将 org.apache.webapp.admin.users.UsersTreeBuilder newInstance() 产生对象,接着使用 buildTree() 就能够产生整个树状结构放到 treeControl 之中 ~


SECTION 03 TreeBuilder 简介

TreeBuilder 是一个 interface, 我们前端的程序就是调用 TreeBuilder 来产生 Tree 放入 Session 之中,
public interface TreeBuilder {

    public void buildTree(TreeControl treeControl,
                          ApplicationServlet servlet,
                          HttpServletRequest request);
}

例如 org.apache.webapp.admin.users.UsersTreeBuilder 中,我们可以看到他实现 buildTree(), 最重要的是 addSubtree()中, 产生所有的子节点, 接着,由 root 开始 add 所有的节点, 此时, 所有的树状资料就是放在 treeControl 这个 session 之中.
protected void addSubtree(TreeControlNode root,
                      MessageResources resources) {

        String databaseName = URLEncoder.encode
          ("Users:type=UserDatabase,database=UserDatabase");
        
        TreeControlNode subtree = new TreeControlNode
            ("Global User and Group Administration",
             "folder_16_pad.gif",
             resources.getMessage("users.treeBuilder.subtreeNode"),
             null,
             "content",
             true);
        TreeControlNode groups = new TreeControlNode
            ("Global Administer Groups",
             "Groups.gif",
             resources.getMessage("users.treeBuilder.groupsNode"),
             "users/listGroups.do?databaseName=" +
             URLEncoder.encode(databaseName) +
             "&forward=" +
             URLEncoder.encode("Groups List Setup"),
             "content",
             false);
        TreeControlNode roles = new TreeControlNode
            ("Global Administer Roles",
             "Roles.gif",
             resources.getMessage("users.treeBuilder.rolesNode"),
             "users/listRoles.do?databaseName=" +
             URLEncoder.encode(databaseName) +
             "&forward=" +
             URLEncoder.encode("Roles List Setup"),
             "content",
             false);
        TreeControlNode users = new TreeControlNode
            ("Global Administer Users",
             "Users.gif",
             resources.getMessage("users.treeBuilder.usersNode"),
             "users/listUsers.do?databaseName=" +
             URLEncoder.encode(databaseName) +
             "&forward=" +
             URLEncoder.encode("Users List Setup"),
             "content",
             false);
        
        root.addChild(subtree);
        subtree.addChild(users);
        subtree.addChild(groups);
        subtree.addChild(roles);

}
很明显的, 我们可以知道, 这个 UsersTreeBuilder 产生的就是 Tomcat Admin 的 User Definition. 下面具有 Users, Groups 以及 Roles 的子节点, 当你选择任何一个子节点的时候, 他将会有一个 action 的动作送到 server, 并且修改相关的树状设置产生应该显示的树状模块, 及管理画面.


SECTION 04 TreeControlTag 的简介

在 org.apache.webapp.admin.TreeControlTag 之中, 最重要的就是从 Session 取得 TreeControl 并且根据里面的內容产生相关的 HTML 代码.
// 取得 TreeControl
protected TreeControl getTreeControl() throws JspException {
........ 
}

// 产生 HTML 代码
protected void render(JspWriter out, TreeControlNode node,
                          int level, int width, boolean last)
	throws IOException {
.......
}
		
		
如果你对 tablib 熟悉的话, 可以看一下这个程序, 如果不熟悉, 你就当作是理所当然的代码.这个 taglib 也是整个树状结构的控制核心, 他会根据你的网页操作, 更改你的树状结构的展现方式, 如果必要的时候,例如增加 checkbox 的处理,可以修改这个程序的 render 部分, 让它具有勾选的功能.


SECTION 05 tree-control-test.jsp 的简介

你可以看到 SetUpTreeAction 最后就是 forward 到 Tree Control Test , 在 struts-config.xml 设置中 Tree Control Test 就是指到 tree-control-test.jsp 在这个 jsp 之中, 简单的 taglib 调用
<controls:tree tree="treeControlTest"
               action="treeControlTest.do?tree=${name}"
                style="tree-control"
        styleSelected="tree-control-selected"
      styleUnselected="tree-control-unselected"
  />
就可以产生所有的树状结构了. 但是, 你可以看到每个 Node 的 action 就是 treeControlTest.do. 所以最后, 就是从 struts-config.xml 中检查 treeControlTest 是指 org.apache.webapp.admin.TreeControlTest 这个程序. 基本上你会传入 tree 这个参数, 如果你现在将 expand = true 修改设置为 false, 还可以传入 select 这个参数, 代表现在是这个 treeControlNode 被选择了.


SECTION 06 结论

在 BEA Workshop 8.1 的 netui:tree 组件, 也是采用同样的解决方式来产生 Tree. 这是属于动态的树状选单产生的方法. 和一次下载到 client 端的 javascript Tree 来相比, 每一次打开关上节点的动作都必须和 Server 端沟通, 是比较耗费资源的. 当 client 端的 browser 版本不确定的时候, 使用 DHTML ( html+javascript ) 有时候会产生错误, 有时候更会因为 javascript 数据量过大会导致 client 端的内存不足, 另外, Jdon 的 wys1978 提供了 http://webfx.eae.net/dhtml/xloadtree/xloadtree.html 一个 javascript Tree, 虽然属于 javascript, 但是不同的是, 每次动作都去调用 server 取得数据, 所以, 当你使用比较小型的系统可以采用 struts-menu 一次下载的方式就可以完成你的 tree 选单, 当数据量过大或变化频繁的时候, 我不建议一次下载所有的数据到 client 端, 所以, 不论是 taglib 解决方法还是 xloadtree 都是比较好的选择.

参考文章:
http://jakarta.apache.org/struts/
http://jakarta.apache.org/tomcat/
posted on 2005-04-24 21:58 dragon 阅读(163) 评论(0)  编辑  收藏 所属分类: jsp