SSH+Easyui之TreeGrid树形展现数据

本文介绍Struts2、Spring、Hibernate与easyui的TreeGrid结合,以树的形式展现数据库中数据。在开发中会碰到很多需要以树的形式展现数据,如导航条、权限管理模块中的资源管理,通常在数据库中都是以树的形式存在。例子程序以资源管理为例,使用treegrid展现资源管理子模块的数据。最终效果如下图:

使用easyui使用树形展现很简单,只需将<table>标签的class设为easyui-treegrid即可

<body class="easyui-layout" data-options="fit:true,border:false">
<div>
<span style="white-space:pre">	</span><table id="resourcelist" class="easyui-treegrid"
        data-options="url:'privilegemgmt/resourceAction_getAll.action',idField:'id',treeField:'resourceName',toolbar:'#tb',border:false">
    <thead>
        <tr>
            <th data-options="field:'id',width:40">编号</th>
            <th data-options="field:'resourceName',width:150">资源名称</th>
            <th data-options="field:'resourceUrl',width:200">资源路径</th>
            <th data-options="field:'resourceOrder',width:50">排序</th>
            <th data-options="field:'icon',width:80">图标</th>
            <th data-options="field:'resourceType',width:80">资源类型</th>
            <th data-options="field:'parentid',width:80">上级资源ID</th>
            <th data-options="field:'enable',width:50">状态</th>
            <th data-options="field:'action',width:120">操作</th>
        </tr>
    </thead>
<span style="white-space:pre">	</span></table>
<span style="white-space:pre">	</span><div id="tb">
<span style="white-space:pre">		</span><a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-add" plain="true" onclick="onAdd()">增加</a>
<span style="white-space:pre">	</span>    <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-edit" plain="true" onclick="onUpdate()">编辑</a>
<span style="white-space:pre">		</span><a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-remove" plain="true" onclick="onDelete()">删除</a>  
<span style="white-space:pre">	</span></div>
</div>
</body>

以上就为如图所示的树形展现html代码,data-options定义的各属性值作用为:

url:定义远程获取数据的路径,数据以json格式返回

idField:为树节点的标识,该值唯一

treeField:定义节点的字段,如以上定义的节点字段为资源名称,当该节点下包含子节点时,资源名称前面显示一个可展开的图标

toolbar:工具栏,传入的参数为html标签的id值

border:是否显示边框

field:字段名,即该列所需展现的数据,easyui通过解析json字符串,循环输出到表单中,根据字段名与json字符串中字段的匹配确定哪项数据输出到哪列

formatter:单元格formatter(格式化器)函数,为该列的数据显示做格式化操作,达到自己想要的显示效果。函数包含三个参数:value(字段值),rowData(行记录数据),rowIndex(行索引)。

接下来就是访问Action从服务器端获取数据。以上调用了ResourceAction的getAll方法来获取这可资源树。

ResourceAction.java

public class ResourceAction extends BaseAction {
	private Resource resource;
	private ResourceServiceI resourceService;

	public void getAll() {
		String json = resourceService.getResourceTreeToJson();
		this.write(json);
	}

	//getter or setter
	public Resource getResource() {
		return resource;
	}
	public void setResource(Resource resource) {
		this.resource = resource;
	}
	public ResourceServiceI getResourceService() {
		return resourceService;
	}
	public void setResourceService(ResourceServiceI resourceService) {
		this.resourceService = resourceService;
	}
}

BaseAction.java

public abstract class BaseAction extends ActionSupport {

	public void write(String json) {
		try {
			ServletActionContext.getResponse().setCharacterEncoding("UTF-8");
			ServletActionContext.getResponse().setContentType("text/json");
			ServletActionContext.getResponse().getWriter().write(json);
			ServletActionContext.getResponse().getWriter().flush();
			ServletActionContext.getResponse().getWriter().close();
		} catch (Exception ex) {
			Debuger.log("BaseAction write json throw Exception!");
			ex.printStackTrace();
		}
	}

	public void write(boolean bool) {
		try {
			String json = "{\"success\":\"" + bool + "\"}";
			ServletActionContext.getResponse().getWriter().write(json);

			ServletActionContext.getResponse().getWriter().flush();
			ServletActionContext.getResponse().getWriter().close();
		} catch (Exception ex) {
			Debuger.log("BaseAction write bool throw Exception!");
			ex.printStackTrace();
		}
	}
}

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
	<package name="priviligemgmt" extends="struts-default" namespace="/privilegemgmt">
		<action name="resourceAction_*" class="com.wzh_1208.sshe.action.ResourceAction" method="{1}">
			<result name="input">/jsp/privilegemgmt/resourceinfo.jsp</result>
		</action>
	</package>
</struts>

在使用框架提供的类时,我一般将他封装成自己的一个抽象类,然后需要使用到该类的地方就直接继承自己的基类,方便拓展和代码的重用。由于可能在项目中大多数Action都需要向客户端写出json字符串,这里就在BaseAction中封装了两个write方法,其他Action继承BaseAcion即可。getAll方法其实就一个壳子供jsp页面调用,全部的逻辑丢给了业务逻辑层的getResourceTreeToJson方法,该方法将数据库中的资源封装成了一颗树,并以json字符串的形式返回。

ResourceServiceImpl.java

import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.wzh_1208.waimai.bean.Resource;
import com.wzh_1208.waimai.dao.ResourceDAOI;
import com.wzh_1208.waimai.services.ResourceServiceI;

public class ResourceServiceImpl implements ResourceServiceI {
	private ResourceDAOI resourceDao;

	@Override
	public List<Resource> getAllResource() {
		return resourceDao.findAll();
	}

	@Override
	public String getResourceTreeToJson() {
		return this.createTreeJson(getAllResource());
	}

	/**
	 * 创建一颗树,以json字符串形式返回
	 * @param list 原始数据列表
	 * @return 树
	 */
	private String createTreeJson(List<Resource> list) {
		JSONArray rootArray = new JSONArray();
		for (int i=0; i<list.size(); i++) {
			Resource resource = list.get(i);
			if (resource.getParentid() == null) {
				JSONObject rootObj = createBranch(list, resource);
				rootArray.add(rootObj);
			}
		}

		return rootArray.toString();
	}

	/**
	 * 递归创建分支节点Json对象
	 * @param list 创建树的原始数据
	 * @param currentNode 当前节点
	 * @return 当前节点与该节点的子节点json对象
	 */
	private JSONObject createBranch(List<Resource> list, Resource currentNode) {
		/*
		 * 将javabean对象解析成为JSON对象
		 */
		JSONObject currentObj = JSONObject.fromObject(currentNode);
		JSONArray childArray = new JSONArray();
		/*
		 * 循环遍历原始数据列表,判断列表中某对象的父id值是否等于当前节点的id值,
		 * 如果相等,进入递归创建新节点的子节点,直至无子节点时,返回节点,并将该
		 * 节点放入当前节点的子节点列表中
		 */
		for (int i=0; i<list.size(); i++) {
			Resource newNode = list.get(i);
			if (newNode.getParentid()!=null && newNode.getParentid().compareTo(currentNode.getId()) == 0) {
				JSONObject childObj = createBranch(list, newNode);
				childArray.add(childObj);
			}
		}

		/*
		 * 判断当前子节点数组是否为空,不为空将子节点数组加入children字段中
		 */
		if (!childArray.isEmpty()) {
			currentObj.put("children", childArray);
		}

		return currentObj;
	}

	//getter or setter
	public ResourceDAOI getResourceDao() {
		return resourceDao;
	}

	public void setResourceDao(ResourceDAOI resourceDao) {
		this.resourceDao = resourceDao;
	}
}

在使用easyui的treegrid时,最重要的一点就是服务器为easyui返回的json数据的格式。easyui在处理从服务器端返回来的json字符串时,会根据节点下面是否包含children字段及是否含有数据来确定当前节点是否包含子节点。所以在返回json数据时,需要为含有子节点的节点加上children字段,并将子节点列表赋给该值。ResourceServiceImpl为ResourceServiceI的实现类,实现了getAllResource()和getResourceToJson()方法,getAllResource()方法调用数据库访问对象ResourceDAOImpl来获取数据库中所有的资源列表并返回,getResourceToJson方法为获取所有的Resource并组织成一颗树,以json字符串的形式返回。

ResourceDAOImpl.java

import java.sql.Timestamp;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wzh_1208.waimai.BaseDAO;
import com.wzh_1208.waimai.bean.Resource;
import com.wzh_1208.waimai.dao.ResourceDAOI;

public class ResourceDAOImpl extends BaseDAO implements ResourceDAOI {
	private static final Logger log = LoggerFactory
			.getLogger(ResourceDAOImpl.class);

	protected void initDao() {
		// do nothing
	}

	public List<Resource> findAll() {
		log.debug("finding all Resource instances");
		try {
			//查询资源记录,按资源父id和序号的升序排列
			String queryString = "from Resource order by parentid,resourceOrder asc";
			return getHibernateTemplate().find(queryString);
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}
}

BaseDAO.java

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class BaseDAO extends HibernateDaoSupport {
}

ResourceDAOImpl继承了BaseDAO类和ResourceDAOI,并实现findAll方法,为业务逻辑层返回按资源父id和序号升序排列的Resource所有记录。

以上就完成了整个数据展现过程的实现,但工作还未完成,还需配置一大堆配置文件。这里就不贴出来了。

Resource.java

import java.sql.Timestamp;

/**
 * Resource entity. @author WZH
 */

public class Resource implements java.io.Serializable {
	//主键id
	private Integer id;
	//资源名称
	private String resourceName;
	//资源访问路径
	private String resourceUrl;
	//资源描述
	private String description;
	//资源的图标
	private String icon;
	//父节点id
	private Integer parentid;
	//资源的类型,菜单或按钮
	private String resourceType;
	//是否可用
	private Integer enable;
	//资源排序序号
	private Integer resourceOrder;
	//创建时间
	private Timestamp createTime;
<span style="white-space:pre">	/** default constructor */
<span style="white-space:pre">	</span>public Resource() {
<span style="white-space:pre">	</span>}</span>
	//getter or setter方法省略
                 ........
}

Resource.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wzh_1208.sshe.bean.Resource" table="resource">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native"></generator>
        </id>
        <property name="resourceName" type="java.lang.String">
            <column name="resource_name" length="20" not-null="true">
            </column>
        </property>
        <property name="resourceUrl" type="java.lang.String">
            <column name="resource_url" length="200">
            </column>
        </property>
        <property name="description" type="java.lang.String">
            <column name="description" length="200">
            </column>
        </property>
        <property name="icon" type="java.lang.String">
            <column name="icon" length="200">
            </column>
        </property>
        <property name="parentid" type="java.lang.Integer">
            <column name="parentid">
            </column>
        </property>
        <property name="resourceType" type="java.lang.String">
            <column name="resource_type" length="11" not-null="true">
            </column>
        </property>
        <property name="enable" type="java.lang.Integer">
            <column name="enable" not-null="true">
            </column>
        </property>
        <property name="resourceOrder" type="java.lang.Integer">
            <column name="resource_order">
            </column>
        </property>
        <property name="createTime" type="java.sql.Timestamp">
            <column name="create_time" length="0">
            </column>
        </property>
    </class>
</hibernate-mapping>

运行程序,数据便可以树的形式展现出来,效果图如下:

但此时只是将数据库中的数据原封不动的显示在了界面上,并未像文章开头那张图一样在节点上显示设置的图标、状态为可用或禁用以及操作栏未显示操作。此时就需为数据进行格式话处理,即用到easyui的formatter属性来定义格式化列的显示函数,来实现数据自定义的显示。修改之后的html代码如下:

<script>
/**
 *格式化资源显示名称,easyui在显示节点字段时,如果记录中有iconCls值,easyui会根据该值来相应的图标,
 *如果没有则应默认图标代替。这里在传递过来的json字符串中未含有iconCls字段,但包含icon字段,这里只需
 *将icon字段值赋给iconCls,即可显示图标。
**/
function formatName(value, row, index) {
	//在名称前面显示图标就是靠iconCls属性,iconCls属性为一个css类,easyui拿到这个属性值就能显示相应的图标了
	//由于传递过来的json字符串中未包含iconCls属性,只有icon属性,所以要想easyui显示图标只需将icon的值赋给iconCls
	row.iconCls = row.icon;
	return value;
}

/**
 *格式化父资源的显示,为0时不显示父资源
**/
function formatParentId(value, row, index) {
	if (value == 0) {
		return null;
	}
	return value;
}

/**
 *格式化状态,如果为1,显示正常,为0显示禁用
 */
function formatState(value,row,index) {
	switch (value) {
	case 1:
		return '正常';
	case 0:
		return '禁用';
	}
}

/**
 *格式化操作,在每行的操作栏显示编辑和删除操作
 */
function formatAction(value, row, index) {
	var str = '';

	if (true) {
		str += '<a href="javascript:onUpdate()" >编辑</a>';
	}
	str += ' | ';
	if (true) {
		str += '<a href="javascript:onDelete()">删除</a>';
	}

	return str;
}
</script>
</head>

<body class="easyui-layout" data-options="fit:true,border:false">
<div>
<span style="white-space:pre">	</span><table id="resourcelist" class="easyui-treegrid"
        data-options="url:'privilegemgmt/resourceAction_getAll.action',idField:'id',treeField:'resourceName',toolbar:'#tb',border:false">
    <thead>
        <tr>
            <th data-options="field:'id',width:40">编号</th>
            <th data-options="field:'resourceName',width:150,formatter:formatName">资源名称</th>
            <th data-options="field:'resourceUrl',width:200">资源路径</th>
            <th data-options="field:'resourceOrder',width:50">排序</th>
            <th data-options="field:'icon',width:80">图标</th>
            <th data-options="field:'resourceType',width:80">资源类型</th>
            <th data-options="field:'parentid',width:80,formatter:formatParentId">上级资源ID</th>
            <th data-options="field:'enable',width:50,formatter:formatState">状态</th>
            <th data-options="field:'action',width:120,formatter:formatAction">操作</th>
        </tr>
    </thead>
<span style="white-space:pre">	</span></table>
<span style="white-space:pre">	</span><div id="tb">
<span style="white-space:pre">		</span><a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-add" plain="true" onclick="onAdd()">增加</a>
<span style="white-space:pre">	</span>    <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-edit" plain="true" onclick="onUpdate()">编辑</a>
<span style="white-space:pre">		</span><a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-remove" plain="true" onclick="onDelete()">删除</a>  
<span style="white-space:pre">	</span></div>
</div>
</body>

从以上的代码可以看出为需要格式化的列的<th>标签的data-options属性中增加了formatter属性以及对应调用的格式化函数,具体函数的作用和实现已在代码中做出说明。只是需要注意的是,iconCls字段值为css的一个类,可以使用easyui所提供的图标,也可使用自定义的图标,若使用自定义的图标时,一定要特别注意图标的路径,否则也不能正常显示。

这样就完成了Treegrid属性展现资源数据。

源码下载:http://download.csdn.net/detail/a78460750/7811961

时间: 2024-10-10 07:37:47

SSH+Easyui之TreeGrid树形展现数据的相关文章

第二百二十八节,jQuery EasyUI,TreeGrid(树形表格)组件

jQuery EasyUI,TreeGrid(树形表格)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 TreeGrid(树形表格)组件的使用方法,这个组件依赖于 DataGrid(数据表格)组件. 一.加载方式 建立一个 JSON 文件 [ { "id": 1, "name": "系统管理", "date": "2015-05-10", &quo

TreeGrid( 树形表格)

本节课重点了解 EasyUI 中 TreeGrid(树形表格)组件的使用方法,这个组件依赖于DataGrid(数据表格)组件 一. 加载方式//建立一个 JSON 文件[{"id" : 1,"name" : "系统管理","date" : "2015-05-10","children" : [{"id" : 2,"name" : "主机信

easyUI中treegrid组件构造树形表格(简单数据类型)+ssm后台

这几天做的项目要求用树形表格的形式展示一部分数据,于是就想到了使用easyUI的treegrid组件,但几经翻查各种资料,发现数据类型大多采取标准数据类型,即包含children元素的数据类型,小编查遍各种资料,几经实验,小编找到了一种使用简单数据类型的展示树形表格的方法.在这里介绍给大家,仅供参考: 框架使用的是ssm框架,数据库用的是oracle,其中数据库中要展示的表设计成大致如下的样子: 参考了一下easyUI的demo中给出的数据类型,如下格式: 打开里面显示如下: 这是一个json串

EasyUI的treegrid组件动态加载数据问题的解决办法

http://www.jquerycn.cn/a_3455 —————————————————————————————————————————————————————————————————————————————————————— 最近涉及到treegrid组件的查询,需要根据查询条件动态更新EasyUI的treegrid组件的动态加载查询结果 搜遍了treegrid源码和文档发现treegrid是扩展自datagrid和tree的,不过以往利用datagrid的reload方法加参数的 方式

EasyUI ComboTree数据绑定树形分类显示

承接上篇博文[LINQ获取树形分类的层数].在上文中,笔者只分享了层数,在这里我把完整的实现贴出来,欢迎批评指正. 先附上效果图: 首先是Tree公共类 public class Tree { public int ModuleID { get; set; } public int ParentID { get; set; } public int ModulePath { get; set; } public string ModuleName { get; set; } } 接下来就是Tre

EasyUI的treegrid实现自动顺序选择行节点

这两天用EasyUI的treegrid写了一个根据滚动条滚动时相应的依次选中treegrid中的行的demo,之前用了一个递归实现不了,所以用了两个递归实现的,效果如图: 这里的使用的easyui 1.4版本,这个treegrid的方法很少,所以实现起来很费劲,需要自己写函数.好了,上代码: 1 <%@ include file='/main/head.jsp' %> 2 3 <div data-options="region:'center',title:'项目时刻进度展示'

easyui之treegrid的生成

要想用easyui生成一个树形结构的表格,首先你当然需要使你的数据结构和要求的一致,比如说id,text,parentId,state,children这些必须的参数,也可以根据自己的需求加额外的参数,比如url等.So,就先来建一个类 publicclass TreeNode { private Integer id; private String text; private Integer parentId; private String state; private List< TreeN

谈一谈EasyUI的TreeGrid的过滤功能

写在最前面 这个星期一直在纠结easyui的treegrid的过滤功能,原因呢,自然是项目中一个莫名奇妙的需求. easyui虽说是后端程序员的前端框架,但是说句实话,除去api,让我直接写里面的节点信息的话,还真是无从下手,在这里先对前端的同学膜拜下. 说下需求吧,最近一个项目中有个界面使用的easyui的treegrid展示,起初是没什么问题的,但是随着数据的导入发现实际操作上十分不便.原因呢是开发的时候treegrid并没有做分页的处理,目前测试环境数据达到456条,想从中找到一条然后处理

ajax请求返回Json字符串运用highcharts数据图表展现数据

[1].[图片] Json字符串和highcharts数据图表展现.jpg 跳至 [1] [2] [2].[代码] Json字符串和highcharts数据图表展现 跳至[1] [2] 001 /* 002 * Filename: OQtyOrPriceReport.js 003 * Description:客户订单数量和价格报表分析 004 * Created: 2013.11.14 005 * Author : liangjw 006 * Company:Copyright (C) 2013