目录
一、后端
二、前端
树形菜单中分为了父级菜单和子级菜单,在数据库表中pid为-1的为一级菜单,pid为表中某个菜单的id说明他们是父子关系。为了使我们的树形菜单变为动态而不是在jsp页面中定死,在后端我们需要将父级菜单和子级菜单分类,在遍历父级菜单的同时 遍历子级菜单,根据id和pid找到他们相对应的关系。在前端我们使用ajax进行拼接,拿到后端传过来的方法进行遍历,用HasChildren判断是否存在子节点,存在即继续拼接。
数据库表:
思维导图:
一、后端
1、我们先根据数据库表的结构建立实体类
package com.zking.entity;
public class Permission {
private long id;
private String name;//菜单名
private String description;//描述
private String url;//点击菜单跳转页面
private long pid;//父级菜单的id
private int ismenu;//菜单、按钮
private long displayno;//显示的顺序
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() {
// TODO Auto-generated constructor stub
}
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 + "]";
}
}
2、Dao层方法
在Dao层我们需要定义两个查询方法,一个是继承自通用BaseDao的查询方法,一个是将父级菜单和子级菜单分类,达到我们最终需要的分层级菜单的效果
查询方法一:
public List list(Permission permission, PageBean pageBean) throws Exception {
String sql = "select * from t_oa_permission";
return super.executeQuery(sql, Permission.class, pageBean);
}
菜单分类方法:
public List> menus(Permission permission, PageBean pageBean) throws Exception {
List> trees = new ArrayList>();
List list = this.list(permission, pageBean);
for (Permission p : list) {
TreeVo vo = new TreeVo<>();
vo.setId(p.getId()+"");
vo.setText(p.getName());
vo.setParentId(p.getPid()+"");
trees.add(vo);
}
return BuildTree.buildList(trees, "-1");
}
在这个方法里我们调用了一个底层封装类TreeVo用来调用该类里面的属性,这是一个通用的菜单类。
package com.zking.entity;
public class Permission {
private long id;
private String name;//菜单名
private String description;//描述
private String url;//点击菜单跳转页面
private long pid;//父级菜单的id
private int ismenu;//菜单、按钮
private long displayno;//显示的顺序
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() {
// TODO Auto-generated constructor stub
}
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 + "]";
}
}
2、Dao层方法
在Dao层我们需要定义两个查询方法,一个是继承自通用BaseDao的查询方法,一个是将父级菜单和子级菜单分类,达到我们最终需要的分层级菜单的效果
查询方法一:
public List list(Permission permission, PageBean pageBean) throws Exception {
String sql = "select * from t_oa_permission";
return super.executeQuery(sql, Permission.class, pageBean);
}
菜单分类方法:
public List> menus(Permission permission, PageBean pageBean) throws Exception {
List> trees = new ArrayList>();
List list = this.list(permission, pageBean);
for (Permission p : list) {
TreeVo vo = new TreeVo<>();
vo.setId(p.getId()+"");
vo.setText(p.getName());
vo.setParentId(p.getPid()+"");
trees.add(vo);
}
return BuildTree.buildList(trees, "-1");
}
在这个方法里我们调用了一个底层封装类TreeVo用来调用该类里面的属性,这是一个通用的菜单类。
查询方法一:
public List list(Permission permission, PageBean pageBean) throws Exception {
String sql = "select * from t_oa_permission";
return super.executeQuery(sql, Permission.class, pageBean);
}
菜单分类方法:
public List> menus(Permission permission, PageBean pageBean) throws Exception {
List> trees = new ArrayList>();
List list = this.list(permission, pageBean);
for (Permission p : list) {
TreeVo vo = new TreeVo<>();
vo.setId(p.getId()+"");
vo.setText(p.getName());
vo.setParentId(p.getPid()+"");
trees.add(vo);
}
return BuildTree.buildList(trees, "-1");
}
在这个方法里我们调用了一个底层封装类TreeVo用来调用该类里面的属性,这是一个通用的菜单类。
public List> menus(Permission permission, PageBean pageBean) throws Exception { List > trees = new ArrayList >(); List list = this.list(permission, pageBean); for (Permission p : list) { TreeVo vo = new TreeVo<>(); vo.setId(p.getId()+""); vo.setText(p.getName()); vo.setParentId(p.getPid()+""); trees.add(vo); } return BuildTree.buildList(trees, "-1"); }
在这个方法里我们调用了一个底层封装类TreeVo用来调用该类里面的属性,这是一个通用的菜单类。
为了实现父级菜单和子级菜单的分层,遍历菜单集合时,实例化了通用菜单,然后我们将菜单类的节点id和节点名称以及父节点id赋值到通用菜单中,再将这个集合trees加到通用菜单里,返回的是构造树BuildTree里的.buildList方法调用的参数是trees和顶级菜单的节点id‘-1’,在底层自动判断是否存在子节点或者父节点,然后实现父级菜单和子级菜单的分层。
public static List> buildList(List> nodes, String idParam) {
if (nodes == null) {
return null;
}
List> topNodes = new ArrayList>();
for (TreeVo children : nodes) {
String pid = children.getParentId();
if (pid == null || idParam.equals(pid)) {
topNodes.add(children);
continue;
}
for (TreeVo 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、Web层
建立一个PermissionAction,继承Actionsupport并实现模型接口类ModuleDriver
package com.zking.web;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Response;
import com.zking.dao.PermissionDao;
import com.zking.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{
private Permission Permission = new Permission();
private PermissionDao permissionDao = new PermissionDao();
@Override
public Permission getModel() {
// TODO Auto-generated method stub
return Permission;
}
public String menus(HttpServletRequest req, HttpServletResponse resp) {
try {
List> menus = permissionDao.menus(null, null);
//向前端相应数据
ResponseUtil.write(resp, menus);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
4、配置Xml文件
二、前端
前端主要是在main.jsp界面将之前写死的树形菜单的左侧导航格式变成动态的,
使用AJAX将标签拼接,拿到后端传过来的方法,获取它的节点和节点名称
总结:很多方法都在底层封装好了,我们只需要拿过来根据我们的需求稍作修改就好,动态树形菜单最关键的点在于我们得捋清楚哪些是父级菜单和子级菜单。
package com.zking.web; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.ws.Response; import com.zking.dao.PermissionDao; import com.zking.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{ private Permission Permission = new Permission(); private PermissionDao permissionDao = new PermissionDao(); @Override public Permission getModel() { // TODO Auto-generated method stub return Permission; } public String menus(HttpServletRequest req, HttpServletResponse resp) { try { List > menus = permissionDao.menus(null, null); //向前端相应数据 ResponseUtil.write(resp, menus); } catch (Exception e) { e.printStackTrace(); } return null; } }



