LayUi之树形结构的详解(附有全案例代码)

Welcome Huihui's Code World ! !

接下来看看由辉辉所写的关于LayUi的相关操作吧

目录

Welcome Huihui's Code World ! !

一. 什么是树形结构

二.树形结构在什么时候使用(常见使用场景)

三.怎么完成树形结构中的数据交互 (思路)

1. 设计数据库表结构:

2. 插入数据:

3. 查询数据:

4. 处理层级关系:

5.编写servlet

6.jsp界面接收数据

7.最终效果展示

四.详细案例解析

实现效果

思路

表结构

实体类

工具类

配置文件

公共页面(引入的文件)

jsp界面

dao

servlet


上篇我们已经对LayUi有了一个基本的了解,并且使用它做出了两个简单的小案例,那么本篇,我们就来看看它其中的动态树组件吧!

其中还是有用到自定义mvc框架,不懂的小伙伴可以点击下方链接查看
自定义MVC框架【上篇】http://t.csdn.cn/giVlE

自定义MVC框架【中篇】--框架实现http://t.csdn.cn/pzCMx
自定义MVC框架【下篇】--运用框架完成增删改查http://t.csdn.cn/RHgke

一. 什么是树形结构

  • 树形结构是一种层次化的数据结构,采用分层的方式来组织和表示数据。它由节点(node)和边(edge)组成,节点代表数据的存储单元,边代表节点之间的关系
    • 树形结构中有一个根节点(root),它是整个树的起点,根节点可以有多个子节点(child node),每个子节点又可以有自己的子节点,如此递归下去,形成树状的结构。每个节点可以有任意数量的子节点,但一个节点只有一个父节点(除了根节点)。没有子节点的节点被称为叶节点(leaf node),而有子节点的节点称为内部节点
    • 树形结构可以用来表示各种实际问题,如文件系统的目录结构、组织机构的层级关系等。它具有良好的扩展性和灵活性,在查找、插入和删除等操作上具有较高的效率

二.树形结构在什么时候使用(常见使用场景)

  • 1. 文件系统:操作系统中的文件系统通常使用树形结构来组织文件和目录的层次关系。每个目录可以包含多个子目录和文件,形成一棵文件树
  • 2. 组织机构:组织机构中的层级关系常常可以使用树形结构来表示,如企业组织结构、学校院系结构等。每个部门或学院可以有多个子部门或学系,形成组织机构的分层关系
  • 3. 数据分类和分类索引:树形结构可以用于对数据进行分类和分类索引,如图书分类系统、商品分类系统等。每个分类可以有多个子分类,构建出数据的层级分类结构,方便数据的管理和检索
  • 4. XML和HTML文档:XML和HTML文档中的标签元素可以形成树形结构的层次关系,通过父子关系来表示不同元素之间的层级关系
  • 5. 数据库索引:数据库中的索引可以使用树形结构来组织,如B树和B+树等索引结构。这些树形结构可以加速数据库的查询操作
  • 6. 算法和数据结构:许多常见的算法和数据结构都基于树形结构,如二叉树、AVL树、红黑树等。这些树形结构可用于高效地实现搜索、排序和存储等操作
  • 7. 路由和网络拓扑:网络中的路由和网络拓扑结构常常使用树形结构来表示,通过节点和边的关系来描述设备之间的连接和通信路径
  • 8. AI决策树和推荐系统:在人工智能领域,决策树被广泛应用于分类和预测问题,通过递归地划分特征空间来进行决策。推荐系统中也可以使用树形结构来组织用户和物品之间的关系

这些只是树形结构的一些常见使用场景,实际上,树形结构在很多领域都有着重要的应用价值,可以更好地组织和表示复杂的关系和层级结构

三.怎么完成树形结构中的数据交互 (思路)

  • 1. 设计数据库表结构:

    • 首先需要设计合适的数据库表结构来存储树形结构的数据。通常可以使用两种方法来表示树型结构的数据库表设计:邻接表模型和嵌套集模型。邻接表模型使用一张表,每行记录代表一个节点,通过一个外键来表示父节点与子节点之间的关系。嵌套集模型使用两个字段来表示每个节点的左右边界,通过这些边界值可以确定节点的子节点
  • 2. 插入数据:

    • 将树形结构的数据插入到数据库表中。可以按照规定的表结构,逐个节点地插入到相应的表中,确保每个节点的数据与其父节点正确关联
  • 3. 查询数据:

    • 可以使用SQL等查询语言来从数据库中获取树形结构的数据。根据具体的需求,可以使用递归查询、连接查询或者子查询等方式来获得树形结构中的节点及其关系
    • package com.wh.dao;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import com.wh.entity.Permission;
      import com.wh.entity.User;
      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{
      	//查询所有
      		public List list( Permission permission, PageBean pageBean) throws Exception {
      	  String sql="select * from t_oa_permission";
      			return super.executeQuery(sql, Permission.class, pageBean);
      		}	
      }
      
  • 4. 处理层级关系:

    • 根据查询出来的数据,可以根据节点之间的层级关系来构建树形结构,并进行进一步的处理。可以使用编程语言中的数据结构或者自定义类来表示和操作树形结构
    • package com.wh.dao;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import com.wh.entity.Permission;
      import com.wh.entity.User;
      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{
      	//将原数据转换成有层级关系的数据(借助自定义 工具类TreeVo完成)
      	public List> menus( Permission permission, PageBean pageBean) throws Exception {
      		List> menus = new ArrayList<>();
      		List list = this.list(permission, pageBean);
      		for (Permission p : list) {
      			TreeVo tv = new TreeVo<>();
      			tv.setId(p.getId()+"");
      			tv.setParentId(p.getPid()+"");
      			tv.setText(p.getName());
      			menus.add(tv);
      		}
      //		return menus;
      		return BuildTree.buildList(menus, "-1");//-1是顶级节点的id
      	}
      		
      		
      }
      
  • 5.编写servlet

    • package com.wh.web;
      
      import java.util.List;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import com.wh.dao.PermissionDao;
      import com.wh.entity.Permission;
      import com.zking.framework.ActionSupport;
      import com.zking.framework.ModelDriver;
      import com.zking.util.PageBean;
      import com.zking.util.ResponseUtil;
      import com.zking.util.TreeVo;
      
      public class PermissionAction extends ActionSupport implements ModelDriver{
      private Permission permission = new Permission();
      private PermissionDao pd = new PermissionDao();
      
      	public void menus(HttpServletRequest req, HttpServletResponse resp) {
      				try {
      					List> menus = pd.menus(null, null);
      					ResponseUtil.writeJson(resp, menus);
      				} catch (Exception e) {
      					e.printStackTrace();
      				}
      	}
      	@Override
      	public Permission getModel() {
      		return permission;
      	}
      
      }
      
  • 6.jsp界面接收数据

    • <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      
      
      
        <%@include file="/common/head.jsp" %>
      
      
      
      
      
      
      
      
      
  • 7.最终效果展示

    • LayUi之树形结构的详解(附有全案例代码)_第1张图片

四.详细案例解析

实现效果

LayUi之树形结构的详解(附有全案例代码)_第2张图片

思路

  1. 先要从layui的文档中找到树形菜单的样式,将其粘贴过来使用
  2. 观察树形菜单➡所需数据【json&&有层级关系的数据】
  3. 将原本的数据查询出来,借助工具类将其转换成我们所需要的数据
  4. 将所需要的数据进行循环遍历
    1. 外层循环:一级菜单
    2. 内层循环:二级菜单(需要与一级菜单的id相比,一样便遍历)

表结构

LayUi之树形结构的详解(附有全案例代码)_第3张图片

实体类

package com.wh.entity;

public class Module {
private int id;
private int pid;
private String name;
private String icon;
private String url;
private int sort;

public Module() {
	// TODO Auto-generated constructor stub
}

public Module(int id, int pid, String name, String icon, String url, int sort) {
	super();
	this.id = id;
	this.pid = pid;
	this.name = name;
	this.icon = icon;
	this.url = url;
	this.sort = sort;
}

public int getId() {
	return id;
}

public void setId(int id) {
	this.id = id;
}

public int getPid() {
	return pid;
}

public void setPid(int pid) {
	this.pid = pid;
}

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public String getIcon() {
	return icon;
}

public void setIcon(String icon) {
	this.icon = icon;
}

public String getUrl() {
	return url;
}

public void setUrl(String url) {
	this.url = url;
}

public int getSort() {
	return sort;
}

public void setSort(int sort) {
	this.sort = sort;
}

@Override
public String toString() {
	return "Module [id=" + id + ", pid=" + pid + ", name=" + name + ", icon=" + icon + ", url=" + url + ", sort=" + sort
			+ "]";
}




}

工具类

package com.zking.util;
 
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
 
/**
 * 提供了一组获得或关闭数据库对象的方法
 * 
 */
public class DBAccess {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
 
	static {// 静态块执行一次,加载 驱动一次
		try {
			InputStream is = DBAccess.class
					.getResourceAsStream("config.properties");
 
			Properties properties = new Properties();
			properties.load(is);
 
			driver = properties.getProperty("driver");
			url = properties.getProperty("url");
			user = properties.getProperty("user");
			password = properties.getProperty("pwd");
 
			Class.forName(driver);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
 
	/**
	 * 获得数据连接对象
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		try {
			Connection conn = DriverManager.getConnection(url, user, password);
			return conn;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
 
	public static void close(ResultSet rs) {
		if (null != rs) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
 
	public static void close(Statement stmt) {
		if (null != stmt) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
 
	public static void close(Connection conn) {
		if (null != conn) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
 
	public static void close(Connection conn, Statement stmt, ResultSet rs) {
		close(rs);
		close(stmt);
		close(conn);
	}
 
	public static boolean isOracle() {
		return "oracle.jdbc.driver.OracleDriver".equals(driver);
	}
 
	public static boolean isSQLServer() {
		return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver);
	}
	
	public static boolean isMysql() {
		return "com.mysql.cj.jdbc.Driver".equals(driver);
	}
 
	public static void main(String[] args) {
		Connection conn = DBAccess.getConnection();
		System.out.println(conn);
		DBAccess.close(conn);
		System.out.println("isOracle:" + isOracle());
		System.out.println("isSQLServer:" + isSQLServer());
		System.out.println("isMysql:" + isMysql());
		System.out.println("数据库连接(关闭)成功");
	}
}
package com.zking.util;
 
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/*
 * 通用的增删改以及查询
 */
public class BaseDao {
	/**
	 * @author W
	 * 
	 * 通用版分页查询
	 * @param sql sql语句
	 * @param clas 指定对象类类
	 * @param pageBean 分页工具类
	 * @return list 结果集
	 * @throws Exception
	 */
	public List executeQuery (String sql,Class clas,PageBean pageBean) throws Exception{
		Connection conn = null;//连接对象
		PreparedStatement ps = null;//执行对象
		ResultSet rs = null;//结果集对象
		List list= new ArrayList();//集合
		/**
		 * 是否分页?
		 */
		if(pageBean!=null&&pageBean.isPagination()) {//如果分页的工具类传进来了【不为空】,并且分页工具类的是否分页的方法的返回值是true时
			//那么便定义分页的sql语句和符合条件的总记录数
			String countSql=getCountSql(sql);//符合条件的总记录数的sql
			conn = DBAccess.getConnection();//获取连接对象
			ps = conn.prepareStatement(countSql);//执行sql语句
			rs=ps.executeQuery();//获取结果集对象
			if(rs.next()) {
				pageBean.setTotal(rs.getObject("n").toString());//结果集查询的结果设置到分页工具类的总记录的方法中
			}
			String pageSql=getPageSql(sql,pageBean);//分页的sql
			conn = DBAccess.getConnection();//获取连接对象
			ps = conn.prepareStatement(pageSql);//执行sql语句
			rs=ps.executeQuery();//获取结果集对象
		}else {
			conn = DBAccess.getConnection();//获取连接对象
			ps = conn.prepareStatement(sql);//执行sql语句
			rs=ps.executeQuery();//获取结果集对象
		}
		while(rs.next()) {
			T t= (T) clas.newInstance();//类类
			Field[] fields = clas.getDeclaredFields();//拿到特定实体的所有的属性
			for (Field field : fields) {//遍历所有的属性
				field.setAccessible(true);//打开权限通道,可以拿到私有的属性
				field.set(t, rs.getObject(field.getName()));//为指定的实体对象更改指定的属性
			}
			list.add(t);//将其加入到集合中
		}
		return list;//返回集合
	}
 
	/**
	 * 符合条件的总记录数
	 * @param sql 查询的sql语句
	 * @return 符合条件的总记录数的sql语句
	 */
	private String getCountSql(String sql) {
		return " select count(1) as n from ( "+sql+" ) t";//sql语句
	}
 
	/**
	 * 分页的sql语句
	 * @param sql 查询的sql语句
	 * @param pageBean 分页工具类
	 * @return 分页的sql语句
	 */
	private String getPageSql(String sql, PageBean pageBean) {
		return sql+" limit  "+pageBean.getStartIndex()+", "+pageBean.getRows();//sql语句
	}
	
	
	
	
	/**
	 * @author W
	 * 通用的增删改
	 */
	public int executeUpdate (T t,String sql,String [] attr) throws Exception{
		Connection conn = DBAccess.getConnection();//获取连接对象
		PreparedStatement ps =conn.prepareStatement(sql);//执行sql语句
		for (int i = 0; i < attr.length; i++) {//遍历装有对象属性的数组
			Field field = t.getClass().getDeclaredField(attr[i]);//动态实例化并拿到此对象中所有属性
			field.setAccessible(true);//打开获取私有属性的通道
			ps.setObject(i+1, field.get(t));//为占位符赋值
		}
		return ps.executeUpdate();
	}
 
}
package com.zking.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/*
*将源数据转换成有层级关系的数据
*/
public class TreeVo {
	/**
	 * 节点ID
	 */
	private String id;
	/**
	 * 显示节点文本
	 */
	private String text;
	/**
	 * 节点状态,open closed
	 */
	private Map state;
	/**
	 * 节点是否被选中 true false
	 */
	private boolean checked = false;
	/**
	 * 节点属性
	 */
	private Map attributes;

	/**
	 * 节点的子节点
	 */
	private List> children = new ArrayList>();

	/**
	 * 父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 getState() {
		return state;
	}

	public void setState(Map state) {
		this.state = state;
	}

	public boolean isChecked() {
		return checked;
	}

	public void setChecked(boolean checked) {
		this.checked = checked;
	}

	public Map getAttributes() {
		return attributes;
	}

	public void setAttributes(Map attributes) {
		this.attributes = attributes;
	}

	public List> getChildren() {
		return children;
	}

	public void setChildren(List> 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 state, boolean checked, Map attributes,
                  List> 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();
	}

}
package com.zking.util;
 
import java.io.PrintWriter;
 
import javax.servlet.http.HttpServletResponse;
 
import com.fasterxml.jackson.databind.ObjectMapper;
/*
*jaso格式数据的转换与回显
*/
 
public class ResponseUtil {
 
	public static void write(HttpServletResponse response,Object o)throws Exception{
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(o.toString());
		out.flush();
		out.close();
	}
	
	public static void writeJson(HttpServletResponse response,Object o)throws Exception{
		ObjectMapper om = new ObjectMapper();
//		om.writeValueAsString(o)代表了json串
		write(response, om.writeValueAsString(o));
	}
}

配置文件

#oracle9i
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:ora9
#user=test
#pwd=test
 
 
#sql2005
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#url=jdbc:sqlserver://localhost:1423;DatabaseName=test
#user=sa
#pwd=sa
 
 
#sql2000
#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
#url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB
#user=sa
#pwd=888888
 
#mysql5
#driver=com.mysql.jdbc.Driver
#url=jdbc:mysql://127.0.0.1:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
#user=mybatis_ssm
#pwd=xiaoli
 
#mysql8
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useSSL=true
user=root
pwd=123456
 
 
 


	
	
	
	
	
	
	

	
	


 T269_mvc_crud
  
  	mvc
  	com.zking.framework.DispatchServlet
  	
  		configurationLocation
  		/mvc.xml
  	
  
  
  	mvc
  	*.action
  

公共页面(引入的文件)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>







 

jsp界面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>



  <%@include file="/common/head.jsp" %>








dao

package com.wh.dao;

import java.util.ArrayList;
import java.util.List;

import com.wh.entity.Module;
import com.wh.entity.Permission;
import com.wh.entity.User;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.PageBean;
import com.zking.util.TreeVo;

public class ModuleDao extends BaseDao{
	//查询所有
		public List< Module> list(  Module  module, PageBean pageBean) throws Exception {
	  String sql="select * from t_module";
			return super.executeQuery(sql,  Module.class, pageBean);
		}
	
	
	//将原数据转换成有层级关系的数据(借助自定义 工具类TreeVo完成)
	public List> menus(  Module  module, PageBean pageBean) throws Exception {
		List> menus = new ArrayList<>();
		List list = this.list(module, pageBean);
		for (Module m : list) {
			TreeVo tv = new TreeVo<>();
			tv.setId(m.getId()+"");
			tv.setParentId(m.getPid()+"");
			tv.setText(m.getName());
			menus.add(tv);
		}
//		return menus;
		return BuildTree.buildList(menus, "-1");//-1是顶级节点的id
	}
		
		
}

servlet

package com.wh.web;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.wh.dao.ModuleDao;
import com.wh.dao.PermissionDao;
import com.wh.entity.Module;
import com.wh.entity.Permission;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.PageBean;
import com.zking.util.ResponseUtil;
import com.zking.util.TreeVo;

public class ModuleAction extends ActionSupport implements ModelDriver< Module>{
private  Module  module = new  Module();
private  ModuleDao md = new  ModuleDao();

	public void menus(HttpServletRequest req, HttpServletResponse resp) {
				try {
					List> menus = md.menus(null, null);
					ResponseUtil.writeJson(resp, menus);
				} catch (Exception e) {
					e.printStackTrace();
				}
	}
	@Override
	public  Module getModel() {
		return  module;
	}

}

      好啦,今天的分享就到这了,希望能够帮到你呢!         

你可能感兴趣的:(LayUi,layui,前端,javascript)