使用 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。