一.数据库
从表中可以分析出这是一个三级菜单,‘权限管理’是父节点,‘书籍管理’,‘订单管理’是二级节点,其他的是三级节点
我们可以把分好的二级节点和三级节点加到父节点里
二.效果图
这就是一个左侧菜单的效果图
三.树形导航栏的实现
3.1.实体--Permission
package com.junlinyi.entity; /** * 菜单权限实体类 * * @author 君临沂 */ public class Permission { private long id; private String name; private String description; private String url; private long pid; private int ismenu;//控制当前系统的权限是菜单还是按钮 private long displayno;//菜单排序字段 public Permission() { // TODO Auto-generated constructor stub } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public long getPid() { return pid; } public void setPid(long pid) { this.pid = pid; } public int getIsmenu() { return ismenu; } public void setIsmenu(int ismenu) { this.ismenu = ismenu; } public long getDisplayno() { return displayno; } public void setDisplayno(long displayno) { this.displayno = displayno; } public Permission(long id, String name, String description, String url, long pid, int ismenu, long displayno) { super(); this.id = id; this.name = name; this.description = description; this.url = url; this.pid = pid; this.ismenu = ismenu; this.displayno = displayno; } @Override public String toString() { return "Permission [id=" + id + ", name=" + name + ", description=" + description + ", url=" + url + ", pid=" + pid + ", ismenu=" + ismenu + ", displayno=" + displayno + "]"; } }
3.2.工具类--TreeVo,BuildTree
TreeVo
package com.zking.util; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 权限工具类 * * @author 君临沂 */ public class TreeVo<T> { /** * 节点ID */ private String id; /** * 显示节点文本 */ private String text; /** * 节点状态,open closed */ private Map<String, Object> state; /** * 节点是否被选中 true false */ private boolean checked = false; /** * 节点属性 */ private Map<String, Object> attributes; /** * 节点的子节点 */ private List<TreeVo<T>> children = new ArrayList<TreeVo<T>>(); /** * 父ID */ private String parentId; /** * 是否有父节点 */ private boolean hasParent = false; /** * 是否有子节点 */ private boolean hasChildren = false; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getText() { return text; } public void setText(String text) { this.text = text; } public Map<String, Object> getState() { return state; } public void setState(Map<String, Object> state) { this.state = state; } public boolean isChecked() { return checked; } public void setChecked(boolean checked) { this.checked = checked; } public Map<String, Object> getAttributes() { return attributes; } public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; } public List<TreeVo<T>> getChildren() { return children; } public void setChildren(List<TreeVo<T>> children) { this.children = children; } public boolean isHasParent() { return hasParent; } public void setHasParent(boolean isParent) { this.hasParent = isParent; } public boolean isHasChildren() { return hasChildren; } public void setChildren(boolean isChildren) { this.hasChildren = isChildren; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public TreeVo(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes, List<TreeVo<T>> children, boolean isParent, boolean isChildren, String parentID) { super(); this.id = id; this.text = text; this.state = state; this.checked = checked; this.attributes = attributes; this.children = children; this.hasParent = isParent; this.hasChildren = isChildren; this.parentId = parentID; } public TreeVo() { super(); } }
BuildTree
package com.zking.util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 权限工具类 * @author: 君临沂 * */ public class BuildTree { /** * 默认-1为顶级节点 * @param nodes * @param <T> * @return */ public static <T> TreeVo<T> build(List<TreeVo<T>> nodes) { if (nodes == null) { return null; } List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>(); for (TreeVo<T> children : nodes) { String pid = children.getParentId(); if (pid == null || "-1".equals(pid)) { topNodes.add(children); continue; } for (TreeVo<T> parent : nodes) { String id = parent.getId(); if (id != null && id.equals(pid)) { parent.getChildren().add(children); children.setHasParent(true); parent.setChildren(true); continue; } } } TreeVo<T> root = new TreeVo<T>(); if (topNodes.size() == 1) { root = topNodes.get(0); } else { root.setId("000"); root.setParentId("-1"); root.setHasParent(false); root.setChildren(true); root.setChecked(true); root.setChildren(topNodes); root.setText("顶级节点"); Map<String, Object> state = new HashMap<>(16); state.put("opened", true); root.setState(state); } return root; } /** * 指定idparam为顶级节点 * @param nodes * @param idParam * @param <T> * @return */ public static <T> List<TreeVo<T>> buildList(List<TreeVo<T>> nodes, String idParam) { if (nodes == null) { return null; } List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>(); for (TreeVo<T> children : nodes) { String pid = children.getParentId(); if (pid == null || idParam.equals(pid)) { topNodes.add(children); continue; } for (TreeVo<T> parent : nodes) { String id = parent.getId(); if (id != null && id.equals(pid)) { parent.getChildren().add(children); children.setHasParent(true); parent.setChildren(true); continue; } } } return topNodes; } }
3.3.PermissionDao
package com.junlinyi.dao; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.junlinyi.entity.Permission; import com.fasterxml.jackson.databind.ObjectMapper; import com.zking.util.BaseDao; import com.zking.util.BuildTree; import com.zking.util.PageBean; import com.zking.util.TreeVo; public class PermissionDao extends BaseDao<Permission>{ //查询 public List<Permission> list(Permission permission, PageBean pageBean) throws Exception { String sql="select * from t_easyui_permission"; return super.executeQuery(sql, Permission.class, pageBean); } //将平级数据转成有父子关系的数据 // public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception { // List<TreeVo<Permission>> lst=new ArrayList<TreeVo<Permission>>(); // List<Permission> list = this.list(permission, pageBean); // for (Permission p : list) { // TreeVo<Permission> treevo=new TreeVo<Permission>(); // treevo.setId(p.getId()+""); // treevo.setText(p.getName()); // treevo.setParentId(p.getPid()+""); // lst.add(treevo); // } // return BuildTree.buildList(lst, "0"); // // } //分好的二级节点和三级节点 public List<TreeVo<Permission>> menus(Permission permission, PageBean pageBean) throws Exception { List<TreeVo<Permission>> trees = new ArrayList<TreeVo<Permission>>(); List<Permission> list = this.list(permission, pageBean); for (Permission p : list) { TreeVo<Permission> vo = new TreeVo<>(); vo.setId(p.getId()+""); vo.setText(p.getName());//节点名称 vo.setParentId(p.getPid()+""); trees.add(vo); } return BuildTree.buildList(trees,"0"); } public TreeVo<Permission> menu(Permission permission,PageBean pageBean) throws Exception { List<TreeVo<Permission>> trees = new ArrayList<TreeVo<Permission>>(); List<Permission> list = this.list(permission, pageBean); for (Permission p : list) { TreeVo<Permission> vo = new TreeVo<>(); vo.setId(p.getId()+""); vo.setText(p.getName());//节点名称 vo.setParentId(p.getPid()+""); vo.setChildren(menus(null, null));//将分好的二级节点和三级节点加到顶级节点里 trees.add(vo); } return BuildTree.build(trees); } public static void main(String[] args) throws Exception { List<TreeVo<Permission>> menus = new PermissionDao().menus(null, null); ObjectMapper om = new ObjectMapper(); System.out.println(om.writeValueAsString(menus)); } }
3.4.PermissionAction
package com.junlinyi.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.junlinyi.dao.PermissionDao; import com.junlinyi.entity.Permission; import com.zking.framework.ActionSupport; import com.zking.framework.ModelDriver; import com.zking.util.ResponseUtil; import com.zking.util.TreeVo; public class PermissionAction extends ActionSupport implements ModelDriver<Permission>{ private Permission p=new Permission(); private PermissionDao pd=new PermissionDao(); public void menu(HttpServletRequest req, HttpServletResponse resp) throws Exception { // List<TreeVo<Permission>> menus = pd.menus(null, null); // ResponseUtil.writeJson(resp, menus); TreeVo<Permission> menu2 = pd.menu(null, null);//调用顶级节点方法 //向前端响应树形结构的数据 ResponseUtil.writeJson(resp, menu2);//转为json格式 } @Override public Permission getModel() { return p; } }
3.5.配置文件--mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <config> <!-- <action path="/blog" type="com.zking.web.BlogAction"> <forward name="list" path="/blogList.jsp" redirect="false" /> <forward name="toList" path="/blog.action?methodName=list" redirect="true" /> <forward name="toEdit" path="/blogEdit.jsp" redirect="false" /> </action> --> <action path="/user" type="com.junlinyi.web.UserAction"> </action> <action path="/permission" type="com.junlinyi.web.PermissionAction"> </action> </config>
3.6.jsp页面--main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="common/header.jsp" %> <!DOCTYPE html > <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div> <!-- 头部区域(可配合layui 已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <!-- 移动端显示 --> <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft"> <i class="layui-icon layui-icon-spread-left"></i> </li> <!-- Top导航栏 --> <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li> <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li> <li class="layui-nav-item"> <a href="javascript:;">nav groups</a> <dl class="layui-nav-child"> <dd><a href="">menu 11</a></dd> <dd><a href="">menu 22</a></dd> <dd><a href="">menu 33</a></dd> </dl> </li> </ul> <!-- 个人头像及账号操作 --> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item layui-hide layui-show-md-inline-block"> <a href="javascript:;"> <img src="static/images/bg.jpg" class="layui-nav-img"> 个人中心 </a> <dl class="layui-nav-child"> <dd><a href="">Your Profile</a></dd> <dd><a href="">Settings</a></dd> <dd><a href="login.jsp">Sign out</a></dd> </dl> </li> <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect> <a href="javascript:;"> <i class="layui-icon layui-icon-more-vertical"></i> </a> </li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu"> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> <div style="padding: 15px;">内容主体区域。</div> </div> <div class="layui-footer"> <!-- 底部固定区域 --> 底部固定区域 </div> </div> <script type="text/javascript"> /* 三级菜单 */ layui.use(['jquery'], function(){ let $ = layui.jquery; $.ajax({ url:'${pageContext.request.contextPath }/permission.action?methodName=menu', dataType:'json', success:function(data){ console.log(data); let str=''; str +='<li class="layui-nav-item layui-nav-itemed">'; str +='<a class="" href="javascript:;">'+data.text+'</a>';//顶级节点 //判断节点是否存在子节点 if(!data.hasChildren){ str +='<dl class="layui-nav-child">'; let children = data.children; $.each(children,function(index,node){//二级节点 str +='<dd><a href="javascript:;">'+children[index].text+'</a></dd>'; if(!data.hasChildren){ str +='<dl class="layui-nav-child">'; let children2 =children[index].children; $.each(children2,function(index,node){//三级节点 str +='<dd><a href="javascript:;">'+children2[index].text+'</a></dd>'; }); str +='</dl>'; } }); str +='</dl>'; } str +='</li>'; $("#menu").html(str);//渲染 } }); }); </script> </body> </html>
注:在拼接完成后,最好是对其进行渲染,否则遍历的数据可能会出不来哦!