树形结构是常见也是常用的,之前一直在使用但是基本都是调用别人写好的方法,好像也没调用太明白的感觉,这次在开发ITOO的时候终于研究了一番,发现其实要实现树形结构其实不是一件困难的事,而且实现方法也不是唯一的,之前大家都很倾向使用zTree,网上搜了一下发现zTtree是一个比较强大“树插件”但是觉得对于目前的我来说并不是很合适,首先我们的前台框架使用的easyUI,easyUI有自己的树形结构控件,再引入一个zTree没有多大的必要;而且对于我来说相对于js代码来说我更熟悉使用后台java代码来控制,所以决定研究一下后台生成树形结构,使用json的数据格式将数据传递给easyUI的树形控件。
首先说,easyUI的树形结构对json数据时有要求的,所以在后台将数据拼接成easyUI需要的格式就可以很轻松的生成一颗树形结构了。
首先来看需要树形结构的实体:
/***********************************************************************
* 模块: Institution.java
* 作者: 陈丽娜
* 说明: 机构实体类
* 日期: 2014年12月2日 20:49:05
***********************************************************************/
package com.tgb.itoo.basic.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.log4j.varia.FallbackErrorHandler;
import org.codehaus.jackson.annotate.JsonIgnore;
/**
* 机构实体
*/
@Entity
@Table(name = "TB_Institution")
public class Institution extends EntityDelete {
/**
* 机构代码
*/
@Column(name = "InstitutionCode", length = 255)
private String institutionCode;
/**
* 机构名称
*/
@Column(name = "InstitutionName", length = 255)
private String institutionName;
/**
* 学制
*/
@Column(name = "schoolSystem", length = 255)
private String schoolSystem;
/**
* 学费
*/
@Column(name = "money", length = 255)
private String money;
/**
* 机构类型Id
*/
@Column(name="nodeLevelId", length=30)
private String nodeLevelId;
/**
* 学校层次
*/
@ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER, targetEntity = SchoolLevel.class)
@JoinColumn(name = "levelId", nullable = true)
private SchoolLevel schoolLevel;
/**
* 自关联 父节点
*/
@ManyToOne(cascade = CascadeType.REFRESH,fetch=FetchType.EAGER,targetEntity = Institution.class)
@JoinColumn(name = "pId", nullable = true)
private Institution parentInstitution;
/**
*get/set方法省略
*/
}
将实体转换成easyUI需要的树形结构的方法类:
首先需要定义一个与easyUI需要的json数据一致的实体类:
package itoo.basic.tool.json;
import java.util.ArrayList;
import java.util.List;
/**
* easyUI树形结构转换实体
* @author 陈丽娜
* @version 1.0.0 , 2015年1月29日 上午10:39:28
*/
public class TreeNode{
/**
* 显示节点的id
*/
private String id;
/**
* 显示节点的名称
*/
private String text;
/**
* 显示节点的图标
*/
private String icon;
/**
* 显示节点的父节点
*/
private String parentId;
/**
* 显示节点的子节点集合
*/
private List<TreeNode> children;
/**
* 空的构造函数
*/
public TreeNode(){
}
/**
* 有参数的构造参数
* @param id 显示的节点ID
* @param text 显示的节点名称
* @param icon 显示的节点图标
* @param parentId 显示的节点的父节点
* @param children 显示节点的子节点
*/
public TreeNode(String id, String text,String icon,String parentId,List<TreeNode> children){
super();
this.id=id;
this.text=text;
this.icon=icon;
this.parentId=parentId;
this.children=children;
}
/**
*省略get/set方法
*/
/**
* 添加子节点的方法
* @param node 树节点实体
*/
public void addChild(TreeNode node){
if(this.children==null){
children=new ArrayList<TreeNode>();
children.add(node);
}else{
children.add(node);
}
}
}
定义好实体类之后,将查出来的需要以树形结构显示的数据转换为treenode的实体类型:
package itoo.basic.tool.json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.tgb.itoo.basic.entity.Institution;
/**
* 树形机构方法类
* @author 陈丽娜
* @version 1.0.0 , 2015年1月29日 上午10:44:55
*/
public class TreeUntil{
/**
* 将组织机构转换成treenode的方法
* @param institutions 需要转换的机构list集合
* @return 返回一个treenode结构的list集合
*/
public List fillTree(List<Institution> institutions){
List<TreeNode> list=new ArrayList<TreeNode>(); //定义一个树形结构实体
Map map=new HashMap<String, TreeNode>(); //定义一个map
try {
//将传递过来的参数赋值给机构实体,遍历每一个将机构赋值给treenode相应的属性
for(Institution institution:institutions){
TreeNode node=new TreeNode();
node.setId(institution.getId()); //id
node.setText(institution.getInstitutionName()); //赋值名称
//判断该机构节点是否有父节点,如果父节点不为空则赋值给treenode的父节点
if(institution.getParentInstitution()!=null){
node.setParentId(institution.getParentInstitution().getId());
}
map.put(institution.getId(), node); //将机构的id与树形结构实体放在map中
}
for(Institution institution:institutions){
if(institution.getParentInstitution()!=null){
//如果该机构节点的父节点不为空,但是父节点id为空,则在list中添加有一个
//map中的机构的的id;
//如果父节点id不为空定义pId为父节点的id;
//并定义两个树形结构实体,给父的树形结构pNode添加一个子节点实体cNode
if(institution.getParentInstitution().getId()==null){
list.add((TreeNode)map.get(institution.getId()));
}else{
String pId=institution.getParentInstitution().getId();
TreeNode pNode=(TreeNode)map.get(pId);
TreeNode cNode=(TreeNode)map.get(institution.getId());
pNode.addChild(cNode);
}
}else {
list.add((TreeNode)map.get(institution.getId()));
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return list; //返回树形结构list集合
}
}
这样大部分的工作就完成了,还需要再controller中将数据转成json,并在jsp页面中接收:
/**
* 查询所有的组织机构 树形结构
* @param response 向前台传递数据
* @param request 获取前台的传递数据
*/
@RequestMapping("/info/queryAll")
private void queryAllType(HttpServletResponse response,HttpServletRequest request){
try{
//查询到所有的组织机构信息
List<Institution> institutions =institutionBean.queryAllInstitutions();
treeUntil=new TreeUntil();
//将查询到的数据转换为树形结构的list
List list=treeUntil.fillTree(institutions);
jacksonJsonUntil=new JacksonJsonUntil();
//将返回的list转化成json数据,并返回给jsp页面
jacksonJsonUntil.beanToJson(response, list);
}catch(Exception e){
e.printStackTrace();
}
}
这时候在jsp中直接调用这个controller就可以了:
<div id="p" data-options="region:'west'" title="组织机构树" style="width:20%;padding:10px">
<ul id="tt" class="easyui-tree"
url="info/queryAll">
</ul>
</div>
最终的效果图为: