LayUI之动态树

目录

1.效果图

 2.数据库

2.1创建数据库

2.2加入数据库

3.架构jar包(自定义)

4.配置文件

 5.实体类

6.实体dao类

 7.模型控制器

8.前端页面(jsp)

9.最后效果展示


1.效果图

 2.数据库

2.1创建数据库

 上面名称和属性类型进行创建表名为( t_easyui_permission )。

2.2加入数据库

3.架构jar包(自定义)

该架包是自定义MVC框架的jar架包,在本篇博客的最上面可以下载jar的资源包,下载后

进行解压即可使用,要将该文件的使用架包导入项目的WEB-INF文件中的lib文件中

如图所示:

4.配置文件

在项目中创建一个Source Folder的文件,命名为conf在该文件中,创建模型配置文件mvc.xml

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/orders" type="com.sy.web.OrdersAction">
	</action>
</config>

并且在项目的WEB-INF文件中,创建配置文件名为:web.xml

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>T269_mvc_blog</display-name>
  <servlet>
  	<servlet-name>mvc</servlet-name>
  	<servlet-class>com.zking.framework.DispatchServlet</servlet-class>
  	<init-param>
  		<param-name>configurationLocation</param-name>
  		<param-value>/mvc.xml</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mvc</servlet-name>
  	<url-pattern>*.action</url-pattern>
  </servlet-mapping>
</web-app>

其中com.zking.framework.DispatchServlet是自定义架构里面的导入 ,并且这里的配置文件名称

<param-value>/mvc.xml</param-value>必须要跟上面的模型配置文件mvc.xml名称一致

 5.实体类

Orders 实体类 模型

package com.sy.entity;

public class Orders {
	private long id;
	private String name;
	private String description;
	private String url;
	private long pid;
	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;
	}
	@Override
	public String toString() {
		return "Orders [id=" + id + ", name=" + name + ", description=" + description + ", url=" + url + ", pid=" + pid
				+ ", ismenu=" + ismenu + ", displayno=" + displayno + "]";
	}
	public Orders(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;
	}
	public Orders() {
		super();
	}
 


}

6.实体dao类

OrdersDao类

package com.sy.dao;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sy.entity.Orders;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.PageBean;
import com.zking.util.TreeVo;

public class OrdersDao extends BaseDao<Orders>{
	/**
	 * 
	 * @param order
	 * @param pageBean
	 * @return 获取t_easyui_permission数据表中所有数据
	 * @throws Exception
	 */
	public List<Orders> list(Orders order, PageBean pageBean) throws Exception {
		String sql="select * from t_easyui_permission";
		return super.executeQuery(sql, Orders.class, pageBean);
	}
/**
 * 
 * @param order
 * @param pageBean
 * @return 查询后的平级数据转换为父子关系的数据
 * @throws Exception
 */
	public List<TreeVo<Orders>> menus(Orders order, PageBean pageBean)throws Exception {
		//创建一个容器保存数据转换后的父子关系的数据
		List<TreeVo<Orders>> trpe = new ArrayList<TreeVo<Orders>>();
		//获取所有平级数据
		List<Orders> list = this.list(order, pageBean);
		//循环
		for (Orders p : list) {
			TreeVo<Orders> tp = new TreeVo<Orders>();
			//long强转String类型
			tp.setId(p.getId()+"");
			tp.setText(p.getName());
			tp.setParentId(p.getPid()+"");
			trpe.add(tp);
		}
		//返回调用工具类的方法将容器里的数据转成有父子关系的数据
		return BuildTree.buildList(trpe,"0");
	}
	
	public static void main(String[] args) throws Exception {
		List<TreeVo<Orders>> list = new OrdersDao().menus(null, null);
		ObjectMapper om = new ObjectMapper();
		System.out.println(om.writeValueAsString(list));
	}


}

其中此类继承的BaseDao工具类代码如下

package com.zking.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 所有Dao层的父类 BookDao UserDao OrderDao ...
 * 
 * @author Administrator
 *
 * @param <T>
 */
public class BaseDao<T> {

	/**
	 * 适合多表联查的数据返回
	 * @param sql
	 * @param pageBean
	 * @return
	 * @throws SQLException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public List<Map<String, Object>> executeQuery(String sql, PageBean pageBean)
			throws SQLException, InstantiationException, IllegalAccessException {

		List<Map<String, Object>> list = new ArrayList<>();
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		// 获取源数据
		ResultSetMetaData md = rs.getMetaData();
		int count = md.getColumnCount();
		Map<String, Object> map = null;
		while (rs.next()) {
			map = new HashMap<>();
			for (int i = 1; i <= count; i++) {
//				map.put(md.getColumnName(i), rs.getObject(i));
				map.put(md.getColumnLabel(i), rs.getObject(i));
			}
			list.add(map);
		}
		return list;

	}

	/**
	 * 
	 * @param sql
	 * @param attrs
	 *            map中的key
	 * @param paMap
	 *            jsp向后台传递的参数集合
	 * @return
	 * @throws SQLException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public int executeUpdate(String sql, String[] attrs, Map<String, String[]> paMap) throws SQLException,
			NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		for (int i = 0; i < attrs.length; i++) {
			pst.setObject(i + 1, JsonUtils.getParamVal(paMap, attrs[i]));
		}
		return pst.executeUpdate();
	}

	/**
	 * 批处理
	 * @param sqlLst
	 * @return
	 */
	public static int executeUpdateBatch(String[] sqlLst) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			conn = DBAccess.getConnection();
			// 设置不自动提交
			conn.setAutoCommit(false);
			for (String sql : sqlLst) {
				stmt = conn.prepareStatement(sql);
				stmt.executeUpdate();
			}
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException(e1);
			}
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			DBAccess.close(conn, stmt, null);
		}
		return sqlLst.length;
	}

	/**
	 * 通用的增删改方法
	 * 
	 * @param book
	 * @throws Exception
	 */
	public int executeUpdate(String sql, T t, String[] attrs) throws Exception {
		// String[] attrs = new String[] {"bid", "bname", "price"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		// pst.setObject(1, book.getBid());
		// pst.setObject(2, book.getBname());
		// pst.setObject(3, book.getPrice());
		/*
		 * 思路: 1.从传进来的t中读取属性值 2.往预定义对象中设置了值
		 * 
		 * t->book f->bid
		 */
		for (int i = 0; i < attrs.length; i++) {
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			pst.setObject(i + 1, f.get(t));
		}
		return pst.executeUpdate();
	}

	/**
	 * 通用分页查询
	 * 
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql, Class<T> clz, PageBean pageBean) throws Exception {
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();
		;
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * 
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
		// -- countSql=select count(1) from (sql) t 符合条件的总记录数
		return "select count(1) from (" + sql + ") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * 
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql, PageBean pageBean) {
		// (this.page - 1) * this.rows
		// pageSql=sql limit (page-1)*rows,rows
		return sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
	}
}

 7.模型控制器

OrdersAction 控制器

package com.sy.web;

import java.util.List;

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

import com.sy.dao.OrdersDao;
import com.sy.entity.Orders;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.ResponseUtil;
import com.zking.util.TreeVo;

public class OrdersAction extends ActionSupport implements ModelDriver<Orders>{
	//实例化orders实体(模型)
		private Orders orders= new Orders();
		//实例化OrdersDao实体的方法类(Dao层)
		private OrdersDao ordersDao= new OrdersDao();
		
		public void menus(HttpServletRequest req, HttpServletResponse resp) {
			try {
				//调用方法获取有父子级关系的数据
				List<TreeVo<Orders>> menus = ordersDao.menus(null, null);
				//调用工具类将该数据(menus)传递到前端
				ResponseUtil.writeJson(resp, menus);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}


	@Override
	public Orders getModel() {
	return orders;
	}

}

8.前端页面(jsp)

使用LayUI动态树的修改/优化后的jsp页面代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%@include file="common/header.jsp" %>
</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="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          tester
        </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">
      <li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">menu group 1</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">menu 1</a></dd>
            <dd><a href="javascript:;">menu 2</a></dd>
            <dd><a href="javascript:;">menu 3</a></dd>
            <dd><a href="">the links</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item">
          <a href="javascript:;">menu group 2</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">list 1</a></dd>
            <dd><a href="javascript:;">list 2</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
        <li class="layui-nav-item"><a href="">the links</a></li> 
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <!-- 内容主体区域 -->
    <div style="padding: 15px;">内容主体区域。记得修改 layui.css 和 js 的路径</div>
  </div>
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
            底部固定区域
  </div>
</div>
<script>
layui.use(['element', 'layer', 'util'], function(){
  var element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.$;
  
  $.ajax({
	  url:"${pageContext.request.contextPath }/orders.action?methodName=menus",
	  dataType:'json',
      success:function(data){
			/* console.log(data); */
			/* 定义标签要拼接的文本内容  */
			let datacontent = '';
			$.each(data,function(i,n){
				datacontent += ' <li class="layui-nav-item layui-nav-itemed">';
				datacontent +='<a class="" href="javascript:;">'+n.text+'</a>';
				
				/* 判断是否有子节点有就进行子菜单增加,没有就不加 */
				if(n.hasChildren){
					datacontent +='<dl class="layui-nav-child">';
					/* 循环所有的子节点  n.children*/
					$.each(n.children,function(index,node){
						datacontent += '<dd><a href="javascript:;">'+node.text+'</a></dd>';
					})
					datacontent += ' </dl> ';
				}
				datacontent += ' </li> ';
			})
			/* 重置里面的文本内容 */
			$("#menu").html(datacontent);
			element.render('menu');
		}
  });
 
    
  });
</script>
</body>


</html>

9.最后效果展示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[2\]的代码,可以看出在测试类PermissionDaoTest中,使用了Junit进行测试。在testList方法中,通过调用permissionDao的list方法获取到了形菜单的数据,并将其打印出来。所以,可以使用类似的方法来动态获取形菜单。 具体实现步骤如下: 1. 创建一个测试类,使用Junit进行测试。 2. 在测试方法中,调用获取形菜单的方法,将返回的数据打印出来。 3. 可以使用ObjectMapper将返回的数据转换成JSON格式,方便前端使用。 示例代码如下: ```java import static org.junit.Assert.*; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.fasterxml.jackson.databind.ObjectMapper; import com.zking.dao.PermissionDao; import com.zking.entity.Permission; import com.zking.util.TreeVo; public class TreeMenuTest { private PermissionDao permissionDao = new PermissionDao(); @Before public void setUp() throws Exception { // 初始化操作 } @After public void tearDown() throws Exception { // 清理操作 } @Test public void testGetTreeMenu() { try { List<TreeVo<Permission>> list = permissionDao.getTreeMenu(); for (TreeVo<Permission> t : list) { System.out.println(t); } ObjectMapper om = new ObjectMapper(); System.out.println(om.writeValueAsString(list)); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上述代码中,testGetTreeMenu方法调用了permissionDao的getTreeMenu方法获取形菜单数据,并将其打印出来。同时,使用ObjectMapper将返回的数据转换成JSON格式,并打印出来。 请注意,上述代码仅为示例,具体的实现可能需要根据你的项目结构和需求进行调整。 #### 引用[.reference_title] - *1* *2* [LayUI--动态形菜单](https://blog.csdn.net/weixin_67450855/article/details/125617088)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值