一、首先设计编写Menu实体类,存储每个菜单项的信息
package com.deppon.entity; public class Menu { private String tid; private String text; private boolean leaf; private String parentId; public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String getText() { return text; } public void setText(String text) { this.text = text; } public boolean isLeaf() { return leaf; } public void setLeaf(boolean leaf) { this.leaf = leaf; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } @Override public String toString() { return "Menu [tid=" + tid + ", text=" + text + ", leaf=" + leaf + ", parentId=" + parentId + "]"; } }
-
实体类有四个私有属性,tid是自身的id,
-
text就是菜单在页面显示的的数据,
-
leaf就是是否为叶子节点,
-
parentId为父亲节点的id
二、接下来设计数据库,插入数据(我用的是Oracle)
create table T_TREE ( t_id VARCHAR2(10), text NVARCHAR2(10), leaf CHAR(1), parent_id VARCHAR2(10) )
- 需要注意的就是实体类是boolean值的leaf在数据库中用CHAR(1)存储,值为0或1
- 然后插入数据
insert into T_TREE values('101','一级菜单1',0,null); insert into T_TREE values('102','一级菜单2',0,null); insert into T_TREE values('103','一级菜单3',0,null); insert into T_TREE values('1001','二级菜单1',1,'101'); insert into T_TREE values('1002','二级菜单2',0,'102'); insert into T_TREE values('1003','二级菜单3',0,'102'); insert into T_TREE values('1004','二级菜单4',0,'103'); insert into T_TREE values('1005','二级菜单5',0,'103'); insert into T_TREE values('10001','三级菜单1',1,'1002'); insert into T_TREE values('10002','三级菜单2',1,'1002'); insert into T_TREE values('10003','三级菜单3',1,'1003'); insert into T_TREE values('10004','三级菜单4',1,'1003'); insert into T_TREE values('10005','三级菜单5',1,'1004'); insert into T_TREE values('10006','三级菜单6',1,'1004'); insert into T_TREE values('10007','三级菜单7',1,'1004'); insert into T_TREE values('10008','三级菜单8',1,'1005'); insert into T_TREE values('10009','三级菜单9',1,'1005');
三、设计dao层,由于我是使用Mybatis的,就把mapper文件的代码粘贴一下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="Menu"> <resultMap id="MenuResult" type="Menu"> <result property="tid" column="t_id" /> <result property="text" column="text" /> <result property="leaf" column="leaf" javaType="Boolean" jdbcType="CHAR"/> <result property="parentId" column="parent_id" /> </resultMap> <select id="findLeaf" parameterType="String" resultMap="MenuResult"> select t_id,text,leaf,parent_id from t_tree where 1=1 <choose> <when test="_parameter!=null and _parameter!=''"> and parent_id = #{_parameter} </when> <otherwise> and parent_id is null </otherwise> </choose> </select> </mapper>
- 主要的思路就是,根据父亲节点的id找到所对应的所有子节点
- 需要注意的是, <result property="leaf" column="leaf" javaType="Boolean" jdbcType="CHAR"/>这样的话,mybatis就会自动将数据库中的CHAR类型的leaf转化成布尔类型
下面是dao层的代码
package com.deppon.dao.impl; import java.util.List; import org.mybatis.spring.support.SqlSessionDaoSupport; import com.deppon.dao.IMenuDao; import com.deppon.entity.Menu; public class MenuDaoImpl extends SqlSessionDaoSupport implements IMenuDao{ @SuppressWarnings("unchecked") @Override public List<Menu> findLeaf(String tid) { return this.getSqlSession().selectList("Menu.findLeaf", tid); } }
IMenuDao是我写的一个dao接口,其实就是Service层调用Dao层接口,Action层再调用Service层接口
四、接下来编写界面js
Ext.onReady(function(){ var store = Ext.create('Ext.data.TreeStore', { autoLoad : true, proxy : { type : 'ajax', url : 'menuAction!findLeaf',//请求 reader : { type : 'json', root : 'menuList'//数据 }, //传参 extraParams : { tid : '' } }, root : { text : '管理菜单', expanded : true }, listeners : { 'beforeexpand' : function(node,eOpts){ //点击父亲节点的菜单会将节点的id通过ajax请求,将到后台 this.proxy.extraParams.tid = node.raw.tid; } } }); Ext.create('Ext.tree.Panel', { renderTo : Ext.getBody(), title : '动态加载TreePanel', width : 300, height : 500, useArrows : true, store : store }); });
首次加载的时候tid的值为空,所以就会从数据库把三个一级菜单查出来,
因为三个一级菜单的parent_id is null
五、最后编写Action
package com.deppon.action; import java.util.List; import com.deppon.entity.Menu; import com.deppon.service.IMenuService; public class MenuAction extends BaseAction { private IMenuService menuService; private String tid; private List<Menu> menuList; public String findLeaf() { menuList = this.menuService.findLeaf(tid); System.out.println(menuList); return "findLeaf"; } public void setMenuService(IMenuService menuService) { this.menuService = menuService; } public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public List<Menu> getMenuList() { return menuList; } public void setMenuList(List<Menu> menuList) { this.menuList = menuList; } }
在struts.xml和application.xml配置Action
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" namespace="/" extends="json-default"> <action name="menuAction" class="menuAction"> <result name="findLeaf" type="json"> <param name="includeProperties">menuList.*</param> </result> </action> </package> </struts>
<!-- 配置dao --> <bean id="menuDao" class="com.deppon.dao.impl.MenuDaoImpl" scope="prototype"> <property name="sqlSessionTemplate" ref="sqlSession"></property> </bean> <!-- 配置service --> <bean id="menuService" class="com.deppon.service.impl.MenuServiceImpl"> <property name="menuDao" ref="menuDao"></property> </bean> <!-- 配置Action --> <bean id="menuAction" class="com.deppon.action.MenuAction"> <property name="menuService" ref="menuService"></property> </bean>
这样基本上就写完了,现在我粘贴一下运行的效果
1、首次加载
2、全部展开