树的封装类:
public class TreeVO {
private Long id; // id
private String text; // 名称
private Boolean checked; // 是否选中
private String state; // 展开还是合并状态
private Long parentId; // 指向父级id
private List children; // 子节点
// Getter ...
// Setter ...
}
有菜单表如下:
public class Menu{
private Long menuId;
private String menuName;
private Long parentId;
// 省略其他属性和Getter、Setter
}
本例使用JPA做ORM
/**
* MenuDao接口
*/
@Repository
public interface MenuDao extends JpaRepository<Menu,Long>,JpaSpecificationExecutor<Menu> {
List<Menu> findByParentId(Long parentId);
}
/**
* MenuService实现类
*/
@Service
public class MenuServiceImpl implements MenuService(){
@Autowired
MenuDao menuDao;
public List<TreeVO> createMenuTree(){
// 存放结果的list
List<TreeVO> result = new ArrayList<TreeVO>();
// 从数据库中查询出根节点(即parentId为0的记录)
List<Menu> menuList= menuDao.findByParentId(0);
// 循环根节点并生成树
for(Menu menu : menuList){
// 构造树对象
TreeVO tree = new TreeVO();
// 赋值
tree.setId(menu.getMenuId());
tree.setText(menu.getMenuName());
tree.setParentId(menu.getParentId());
// 调用递归方法查询所有子节点
tree.setChildren(findChildren(tree));
// 添加到结果里面
result.add(tree);
}
return result;
}
public List<TreeVO> findChildren(TreeVO treeVO){
// 如果传入的是空直接返回null
if(treeVo == null)
return null;
// 否则根据传入的对象的id属性获取子节点
List<Menu> menuList = menuDao.findByParentId(treeVO.getId())
// 存放某一级数所有子节点的list集合
List<TreeVO> children = new ArrayList<TreeVO>();
if(menuList.size() > 0){
// 如果有子节点,则循环遍历构造子节点的TreeVO对象
TreeVO vo = null;
for(Menu menu : menuList){
// 构造一个对象
vo = new TreeVO();
// set...
vo.setState("closed");
vo.setIsMenu(true);
vo.setParentId(treeVO.getId());
vo.setText(m.getMenuName());
vo.setId(m.getMenuId());
// 递归调用获取字某一级数的子节点
vo.setChildren(createMenuTreeNoFunctoin(vo));
// 将某一级下的某个节点添加到结果集中
children.add(vo);
}
// 返回结果
return result;
} else {
// 如果没有查询出子节点则返回空
return null;
}
}
}
本例并不够完美,对数据库做了多次查询操作,但是方便理解
改造方法可以一次查询出所有的Menu在方法中逐渐过滤,可以减少数据库的访问