使用 Servlet 或 JFinal 异步请求加载 zTree 教程

最近在完善后台,要做一个树结构,当然第一个想到的就是 ztree 插件,因为这个文档比较完善,功能强大,最最重要的是,作为一个颜控,它有 Metro 风格可选。

那什么是 ztree?zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。专门适合项目开发,尤其是 树状菜单、树状数据的Web显示、权限管理等等。

zTree 是开源免费的软件(MIT 许可证)。在开源的作用下,zTree 越来越完善,目前已经拥有了不少粉丝,并且今后还会推出更多的 zTree 扩展功能库,让 zTree 更加强大。

还是很值得一用的,它的官网地址:http://www.ztree.me/

servlet 配合 ztree

因为也是第一次用,所以在网上找了一些例子,有一个基于 servlet 的例子还不错,作为入门级别的代码,在这里整理一下抄过来了。原来博客的地址:http://zx527291227.iteye.com/blog/1704310

UserServlet.java

package com.servlet.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import com.servlet.bean.User;
import com.servlet.main.JSONMain;
import com.servlet.util.TreeView;

public class UserServlet extends HttpServlet
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse respone) 
        throws ServletException, IOException
    {

        List<User> list = new ArrayList<User>();

        List<TreeView> treeList = new ArrayList<TreeView>();

        User u1 = new User();
        u1.setUserID(1);
        u1.setPreID(0);
        u1.setUrl("");
        u1.setName("祥");
        u1.setPassword("zl123456");
        u1.setSex("男");

        User u2 = new User();
        u2.setUserID(2);
        u2.setPreID(1);
        u2.setUrl("login.jsp");
        u2.setName("夏娟");
        u2.setPassword("zl98765");
        u2.setSex("女");

        User u3 = new User();
        u3.setUserID(3);
        u3.setPreID(1);
        u3.setUrl("login.jsp"); 
        u3.setName("琳琳");
        u3.setPassword("zl98765");
        u3.setSex("女");

        User u4 = new User();
        u4.setUserID(3);
        u4.setPreID(1);
        u4.setUrl("login.jsp"); 
        u4.setName("曼雪");
        u4.setPassword("zl98765");
        u4.setSex("女");

        list.add(u1);
        list.add(u2);
        list.add(u3);
        list.add(u4);

        for(User u : list)
        {
            TreeView treeView = new TreeView();
            treeView.setId(u.getUserID());
            treeView.setName(u.getName());
            treeView.setpId(u.getPreID());
            treeView.setUrl(u.getUrl());
            //treeView.setIsParent(true);
            treeList.add(treeView);
        }

        //JSONObject jObject = JSONMain.getJsonFromList(treeList);
        JSONArray jObject = JSONArray.fromObject(treeList);
        System.out.println(jObject);
        respone.setContentType("text/plain; charset=UTF-8");
        respone.setCharacterEncoding("UTF-8");
        respone.getWriter().write(jObject.toString());
        //respone.encodeUrl("UTF-8");
        //respone.getWriter().write("[{\"demoData\":\"This Is The JSON Data\"}]");
        //respone.sendRedirect("index.jsp");
        //request.getRequestDispatcher(request.getContextPath()+"/index.jsp").forward(request, respone);
    }

    @Override
    /**
     * 销毁
     */
    public void destroy()
    {

        super.destroy();
    }

    @Override
    /**
     * 初始化
     */
    public void init() throws ServletException
    {
        // TODO Auto-generated method stub
        super.init();
    }   
}

TreeView.java

TreeView工具类

package com.servlet.util;

import java.util.List;

public class TreeView
{
    private Integer id;
    private Integer pId;
    private String url;
    private String name;
    //private Boolean isParent;
    private List<TreeView> nodes;

    public Integer getId()
    {
        return id;
    }
    public void setId(Integer id)
    {
        this.id = id;
    }
    public Integer getpId()
    {
        return pId;
    }
    public void setpId(Integer id)
    {
        pId = id;
    }
    public String getUrl()
    {
        return url;
    }
    public void setUrl(String url)
    {
        this.url = url;
    }
    public List<TreeView> getNodes()
    {
        return nodes;
    }
    public void setNodes(List<TreeView> nodes)
    {
        this.nodes = nodes;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    /*public Boolean getIsParent()
    {
        return isParent;
    }
    public void setIsParent(Boolean isParent)
    {
        this.isParent = isParent;
    }*/ 
}

发起请求页面获取

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'index.jsp' starting page</title>

    <script src="<%=path%>/js/jquery-1.4.4.min.js" type="text/javascript"></script> 
    <script src="<%=path%>/js/jquery.ztree.core-3.4.js" type="text/javascript"></script>    
    <link rel="stylesheet" type="text/css" href="<%=path%>/css/zTreeStyle/zTreeStyle.css"></link>
    <link rel="stylesheet" type="text/css" href="<%=path%>/css/demo.css"></link>
    <script type="text/javascript" src="<%=path%>/js/jquery.ztree.excheck-3.4.js" ></script>

    <script type="text/javascript">

        function setFontCss(treeId, treeNode) {
            return treeNode.level == 1 ? {color:"red"} : {};
        };

        var setting = {
            check: {
                enable: true//启动多选框记得导入jquery.ztree.excheck-3.4.js 
            },

            data: {
                simpleData: {
                    enable: true,//如果设置为 true,请务必设置 setting.data.simpleData 内的其他参数: idKey / pIdKey / rootPId,并且让数据满足父子关系。
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: 1
                }
            },

            view: {
                showLine: false,//显示连接线
                showIcon: true,//显示节点图片
                //fontCss: {color:"red"}
                fontCss: setFontCss//节点颜色
            },

            async: {    //ztree异步请求数据
                enable: true,
                url: "login",//请求action方法
                autoparam:["id"]
            }
        };

        $(function($){
            /** 
            var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
            alert("treeObj  :  "+treeObj);
            var nodes = treeObj.getSelectedNodes();
            alert("nodes    :  "+nodes);
            if (nodes.length>0) {
                treeObj.reAsyncChildNodes(nodes[0], "refresh");
            }

            var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
            var nodes = treeObj.getNodes();
            if (nodes.length>0) {
                nodes[0].name = "test";
                treeObj.updateNode(nodes[0]);

            }
            */
            alert(1);
            $.fn.zTree.init($("#treeDemo"), setting);
        });

    </script>

  </head>

  <body>    
        <div class="zTreeDemoBackground left">
            <ul id="treeDemo" class="ztree">            
            </ul>
        </div>
  </body>
</html>

这个例子真的是超级简单了,其实官网文档中也是有这个例子的,而且你从上面的 servlet 可以看出来, ztree 有一个叼炸天的技能,就是不需要去递归获取树形结构的数据,你只要有id 和父类 pid,并且数据符合父子关系就行。

这,对于我们这些无良不要脸穷屌丝来说,真的是一道闪亮的光,因为我就不愿意在我那可怜的服务器上多跑一行多余的代码。当然这是开玩笑,因为 ztree 的性能也是叼炸天的,官网有个性能测试的例子,上百万的数据加载为树只需要不到 1s 的时间。

JFinal 配合 ztree

好了,现在已经熟能生巧了,该干自己的活了。

MySQL 数据库结构

这都是干货啊,乡亲们……

mysql> desc system_resource;
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | varchar(32)  | NO   | PRI | NULL    |       |
| pid         | varchar(32)  | YES  |     | NULL    |       |
| name        | varchar(255) | NO   |     | NULL    |       |
| description | varchar(255) | NO   |     | NULL    |       |
| url         | varchar(255) | NO   |     | NULL    |       |
| createDate  | datetime     | NO   |     | NULL    |       |
| modifyDate  | datetime     | NO   |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
7 rows in set (0.01 sec)

JFinal Java 代码

上面说过,ztree 不需要递归的去构造树结构数据,只要数据符合 id + pid 的父子关系就好。那,我的表是正解。

/**
 * 获取ZTree数据,检查当前是否已选
 * @return
 */
public List<Resource> getZTree(String roleId)
{
    String sql = "SELECT id,pid,name,CONCAT(url,'--',description) AS title FROM system_resource";
    List<Resource> resourceList = dao.find(sql);
    // 获取已经被选中并入库的节点
    List<String> checkedList = RoleResource.dao.getResourceIdByRoleId(roleId);
    if (checkedList.size() > 0)
    {
        for (Resource resource : resourceList)
        {
            if (checkedList.contains(resource.getId()))
            {
                // 选中要加属性 checked 为 true
                resource.put("checked", true);
            }
        }
    }
    return resourceList;
}

/**
 * 获取资源JSON
 */
public void ztree()
{
    String roleId = getPara(0);
    renderJson(Resource.dao.getZTree(roleId));
}

页面请求并展示数据

首先,页面上要有个放置树的 div,设置好 DOM id,

<div class="zTreeDemoBackground left">
    <ul id="demo" class="ztree"></ul>
</div>

然后是 ztree 请求配置,当然这个代码写在哪里,什么时候生效,由你的情况决定,要是页面加载完成就加载 ztree,那么你就写在 jQuery ready 里面;由事件触发,那就写在 function 里,这不是重点。

// 一个回调事件的例子,设置树节点文字的颜色
function setFontCss(treeId, treeNode) {
    return treeNode.level == 1 ? {color:"red"} : {};
};

// 大大的 setting
var setting = {
    async: {
        enable: true,
        url:"${base}/sys/resource/ztree/" + roleId,
        //autoParam:["id", "name=name", "level=pid"],
        type: "get"
    },
    check: {
        enable: true
    },
    data: {
        key: {
            // 节点显示名称
            name:"name",
            // 节点显示的 title 提示
            title:"title",
            // 这个是节点 a 标签的url,默认是 url
            url:""
        },
        simpleData: {
            // 如果设置为 true,请务必设置 setting.data.simpleData 内的其他参数: 
            // idKey / pIdKey / rootPId,并且让数据满足父子关系。
            enable: true,  
            // 数据表字段 id
            idKey: "id",
            // 数据表中父类 pid
            pIdKey: "pid",
            rootPId: null
        }
    },
    view: {
        showLine: true,//显示连接线 
        showIcon: true//显示节点图片
    }
};

$.fn.zTree.init($("#demo"), setting);

然后使用 var ztreeObj = $.fn.zTree.getZTreeObj("demo") 来获取 ztree 对象。 因为我设置的是 checkbox 选中节点,所有使用 ztreeObj.getCheckedNodes() 来获取选中的所有节点,返回一个节点的数组,直接已 json 的形式传回后台解析就行了。

更多配置和 API 参考请移步官网:http://www.ztree.me/v3/api.php

如果觉得这对你有用,请随意赞赏,给与作者支持
评论 0
最新评论