基于ssm与maven,使用easyui--tree生成类似部门管理树形结构图
基于ssm与maven,使用easyui--tree生成类似部门管理树形结构图
本文主要记录自己在实际开发中,遇到的一个问题:需要数据库中读取部门数据,并生成部门管理树形结构图,对部门进行操作,显示效果如下图所示:
由于涉及到公司商业机密,因此在此自己将这个模块单独提炼出来并做了一些修改,并只贴出主要代码。
一、前期说明及准备:
1.后台是基于ssm框架(Spring MVC+Spring+Mybatis);
2.使用mysql数据库;
3.前端使用easyUI+freeMark。
4.项目使用maven构建,Eclipse开发;
5.dao、model、mapper使用mybatis-generator自动生成
6.创建一个名为“treedemo”的数据库及名为“dept”的表,sql语句如下:
- CREATE DATABASE treedemo;
- USE treedemo;
- /*
- Navicat MySQL Data Transfer
- Source Server : mysql
- Source Server Version : 50022
- Source Host : localhost:3306
- Source Database : treedemo
- Target Server Type : MYSQL
- Target Server Version : 50022
- File Encoding : 65001
- */
- SET FOREIGN_KEY_CHECKS=0;
- -- ----------------------------
- -- Table structure for dept
- -- ----------------------------
- DROP TABLE IF EXISTS `dept`;
- CREATE TABLE `dept` (
- `id` varchar(32) NOT NULL,
- `pid` varchar(32) NOT NULL,
- `name` varchar(50) NOT NULL,
- `type` varchar(32) ,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- -- ----------------------------
- -- Records of dept
- -- ----------------------------
- INSERT INTO `dept` VALUES ('0a22ff1186f24a6b9189ae0bccc37528', '9ebd264055aa4f5b9112db58c338e94e', '广告部1','dept');
- INSERT INTO `dept` VALUES ('2c9153620f6344bda08ed1b238a4cdf0', 'e99e1e819fce4dac8054d8c42e4854ab', '业务部','dept');
- INSERT INTO `dept` VALUES ('2f83c97cb5464890bba8291b51bd61a8', 'e99e1e819fce4dac8054d8c42e4854ab', '研发部','dept');
- INSERT INTO `dept` VALUES ('33f0fbc0243743cfa615714b1764fcf7', 'da7b002944dd41d0bf7c00120b94bb48', '财务部','dept');
- INSERT INTO `dept` VALUES ('3b70590f02e1486a967b2eb3463d024c', '779df9d28040485781768a08ead27567', '活动部','dept');
- INSERT INTO `dept` VALUES ('779df9d28040485781768a08ead27567', 'e99e1e819fce4dac8054d8c42e4854ab', '企划部','dept');
- INSERT INTO `dept` VALUES ('7ac8139930fb4a5fb4fd5412e2aa87bf', 'e99e1e819fce4dac8054d8c42e4854ab', '销售部','dept');
- INSERT INTO `dept` VALUES ('9ebd264055aa4f5b9112db58c338e94e', 'df6253b3095c4d2c8083ef9cd4074b40', '广告部','dept');
- INSERT INTO `dept` VALUES ('b7091fb6a38149079d07911d4b5a9537', '9ebd264055aa4f5b9112db58c338e94e', '广告部2','dept');
- INSERT INTO `dept` VALUES ('da7b002944dd41d0bf7c00120b94bb48', 'e99e1e819fce4dac8054d8c42e4854ab', '运营部','dept');
- INSERT INTO `dept` VALUES ('df6253b3095c4d2c8083ef9cd4074b40', '33f0fbc0243743cfa615714b1764fcf7', '策划部','dept');
- INSERT INTO `dept` VALUES ('e99e1e819fce4dac8054d8c42e4854ab', '00000000000000000000000000000000', '示例单位','unit');
二、后台代码
后台代码结构:
1.Dept.java
与数据库中的dept表对应,其如下代码:
- package com.beauxie.model;
- public class Dept {
- /**
- * This field was generated by MyBatis Generator.
- * This field corresponds to the database column dept.id
- *
- * @mbggenerated
- */
- private String id;
- /**
- * This field was generated by MyBatis Generator.
- * This field corresponds to the database column dept.pid
- *
- * @mbggenerated
- */
- private String pid;
- /**
- * This field was generated by MyBatis Generator.
- * This field corresponds to the database column dept.name
- *
- * @mbggenerated
- */
- private String name;
- /**
- * This field was generated by MyBatis Generator.
- * This field corresponds to the database column dept.type
- *
- * @mbggenerated
- */
- private String type;
- /**
- * This method was generated by MyBatis Generator.
- * This method returns the value of the database column dept.id
- *
- * @return the value of dept.id
- *
- * @mbggenerated
- */
- public String getId() {
- return id;
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method sets the value of the database column dept.id
- *
- * @param id the value for dept.id
- *
- * @mbggenerated
- */
- public void setId(String id) {
- this.id = id == null ? null : id.trim();
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method returns the value of the database column dept.pid
- *
- * @return the value of dept.pid
- *
- * @mbggenerated
- */
- public String getPid() {
- return pid;
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method sets the value of the database column dept.pid
- *
- * @param pid the value for dept.pid
- *
- * @mbggenerated
- */
- public void setPid(String pid) {
- this.pid = pid == null ? null : pid.trim();
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method returns the value of the database column dept.name
- *
- * @return the value of dept.name
- *
- * @mbggenerated
- */
- public String getName() {
- return name;
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method sets the value of the database column dept.name
- *
- * @param name the value for dept.name
- *
- * @mbggenerated
- */
- public void setName(String name) {
- this.name = name == null ? null : name.trim();
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method returns the value of the database column dept.type
- *
- * @return the value of dept.type
- *
- * @mbggenerated
- */
- public String getType() {
- return type;
- }
- /**
- * This method was generated by MyBatis Generator.
- * This method sets the value of the database column dept.type
- *
- * @param type the value for dept.type
- *
- * @mbggenerated
- */
- public void setType(String type) {
- this.type = type == null ? null : type.trim();
- }
- }
2.DeptMapper.xml
主要提供一个查询方法,用以查询单位或部门:
- <mapper namespace="com.beauxie.dao.DeptMapper">
- <resultMap id="BaseResultMap" type="com.beauxie.model.Dept">
- <!-- WARNING - @mbggenerated This element is automatically generated by
- MyBatis Generator, do not modify. -->
- <id column="id" property="id" jdbcType="VARCHAR" />
- <result column="pid" property="pid" jdbcType="VARCHAR" />
- <result column="name" property="name" jdbcType="VARCHAR" />
- <result column="type" property="type" jdbcType="VARCHAR" />
- </resultMap>
- //中间无关代码省略...
- <!-- 查询符合条件的记录 -->
- <select id="list" parameterType="map" resultMap="BaseResultMap">
- SELECT
- <include refid="Base_Column_List" />
- FROM
- dept
- WHERE
- type like #{type,jdbcType=VARCHAR}
- <if test="id != null">
- AND id like #{id,jdbcType=VARCHAR}
- </if>
- <if test="pid != null">
- AND pid like #{pid,jdbcType=VARCHAR}
- </if>
- </select>
- </mapper>
3.DeptMapper.java
与DeptMapper.xml对应,代码如下:
- package com.beauxie.dao;
- import java.util.List;
- import java.util.Map;
- import com.beauxie.model.Dept;
- public interface DeptMapper {
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- int deleteByPrimaryKey(String id);
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- int insert(Dept record);
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- int insertSelective(Dept record);
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- Dept selectByPrimaryKey(String id);
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- int updateByPrimaryKeySelective(Dept record);
- /**
- * This method was generated by MyBatis Generator.
- * This method corresponds to the database table dept
- *
- * @mbggenerated
- */
- int updateByPrimaryKey(Dept record);
- /**
- * @param para
- * @return List<Dept>
- */
- List<Dept> list(Map<String, Object> para);
- }
4.DeptServiceI.java
是一个service层的接口,里面只有一个抽象方法,如下:
- package com.beauxie.service;
- import com.beauxie.util.TreeModel;
- public interface DeptServiceI {
- /**
- * 返回所有的单位及部门的树形结构
- * @param id 部门id,即作为下一级子节点的pid
- * @param containsDept 是否包含子节点
- * @return TreeModel
- */
- TreeModel selectTree(String id, boolean containsDept);
- }
5.DeptServiceImpl.java
该类实现了DeptServiceI接口,是构造组织树的主要代码,如下:
- package com.beauxie.service.impl;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Service;
- import org.springframework.util.CollectionUtils;
- import com.beauxie.dao.DeptMapper;
- import com.beauxie.model.Dept;
- import com.beauxie.service.DeptServiceI;
- import com.beauxie.util.TreeModel;
- import com.beauxie.util.TreeUtil;
- @Service
- public class DeptServiceImpl implements DeptServiceI{
- @Resource//或者@Autowired
- private DeptMapper deptMapper;
- /******************************************************** 构造单位及部门树形结构 ********************************************************/
- private List<Dept> selectChildren(String id, String type) {
- Map<String, Object> para = new HashMap<String, Object>();
- para.put("type", type);
- para.put("pid", id);
- return deptMapper.list(para);
- }
- public TreeModel selectTree(String id, boolean containsDept) {
- TreeModel tm = new TreeModel();
- //在此只保留部门或单位的id及name属性,可拓展
- String[] s = new String[] { "getId", "getName" };
- String type = containsDept ? "%" : "unit";
- List<Dept> li = this.selectChildren(id, type);
- this.tree(tm, li, s, containsDept);
- return tm;
- }
- // 构造组织机构树数据
- private void tree(TreeModel tm, List<Dept> li, String[] s,
- boolean containsDept) {
- if (!CollectionUtils.isEmpty(li)) {
- for (int i = 0, l = li.size(); i < l; i++) {
- TreeModel ntm = new TreeModel();
- Dept dept = li.get(i);
- TreeUtil.copyModel(ntm, dept, s);// 复制值到TreeModel
- tm.getChildren().add(ntm);// 添加到孩子节点列表
- String type = containsDept ? "%" : "unit";
- List<Dept> list = this.selectChildren(dept.getId(), type);
- tree(ntm, list, s, containsDept);// 递归,实现无限层级
- }
- }
- }
- /******************************************************** end ********************************************************/
- }
6.TreeModel.java
自定义的树的数据模型,代码如下:
- package com.beauxie.util;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 树的数据模型
- */
- public class TreeModel {
- private String id;
- private String text;// 名称
- private String iconCls;// 图标
- private String linkUrl;// 链接地址
- // 状态(closed折叠、open展开)
- // private String state = "closed";
- private List<TreeModel> children;// 孩子节点集合
- public TreeModel() {
- this.children = new ArrayList<TreeModel>();
- }
- 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 String getLinkUrl() {
- return linkUrl;
- }
- public void setLinkUrl(String linkUrl) {
- this.linkUrl = linkUrl;
- }
- public String getIconCls() {
- return iconCls;
- }
- public void setIconCls(String iconCls) {
- this.iconCls = iconCls;
- }
- public List<TreeModel> getChildren() {
- return children;
- }
- public void setChildren(List<TreeModel> children) {
- this.children = children;
- }
- }
7.TreeUtil.java
该类是一个工具类,用以构造树,代码如下所示:
- package com.beauxie.util;
- import java.lang.reflect.Method;
- /**
- * 树结构处理工具类
- */
- public class TreeUtil {
- /**
- * 复制数据到树model
- * @param tm 树model
- * @param o 待复制的对象
- * @param s 变长参数,方法的名称字符串
- * 约定第1个为id,第2个为text,
- * 第3个为linkUrl,第4个为iconCls,
- * 第5个为splitNum
- */
- public static void copyModel(TreeModel tm, Object o, String... s) {
- Class<?> clazz = o.getClass();// 获取类包名
- int l = s.length;
- try {
- if(l - 0 > 0 && s[0] != null) {
- Method id = clazz.getMethod(s[0]);// 约定第1个为id
- tm.setId(String.valueOf(id.invoke(o)));
- }
- if(l - 1 > 0 && s[1] != null) {
- Method text = clazz.getMethod(s[1]);// 约定第2个为text
- tm.setText(String.valueOf(text.invoke(o)));
- }
- if(l - 2 > 0 && s[2] != null) {
- Method url = clazz.getMethod(s[2]);// 约定第3个为funcUrl
- tm.setLinkUrl(String.valueOf(url.invoke(o)));
- }
- if(l - 3 > 0 && s[3] != null) {
- Method cls = clazz.getMethod(s[3]);// 约定第4个为iconCls
- tm.setIconCls(String.valueOf(cls.invoke(o)));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
8.DeptController.java
- package com.beauxie.controller;
- import java.util.List;
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.beauxie.service.DeptServiceI;
- import com.beauxie.util.TreeModel;
- @Controller
- @RequestMapping("/deptController")
- public class DeptController {
- @Resource
- private DeptServiceI deptService;
- // 表示根目录的pid
- public static final String ROOT = "00000000000000000000000000000000";
- /**
- * 单位部门树(含部门)json
- */
- @RequestMapping("/deptTree")
- @ResponseBody
- // 返回的是JSON格式
- public List<TreeModel> deptTree(HttpServletRequest request) {
- // 默认从根节点开始
- String id = ROOT;
- TreeModel tm = deptService.selectTree(id, true);
- return tm.getChildren();
- }
- }
三、前段代码
1.index.js
向后台发送数据请求,并接收、处理后台传回来的数据,代码如下:
- var treeUrl = '/treedemo/deptController/deptTree.do';
- var tree = null;//表示树
- $(function() {
- tree = $('#vl');
- initTree();//初始化树
- });
- function initTree() {
- tree.tree({
- url: treeUrl,
- animate: false,
- lines : true,
- checkbox : false,//是否显示复选框
- onClick: function(node) {
- //nodeClick(node);
- },
- onLoadSuccess: function(data) {
- alert("加载成功!");
- }
- });
- }
2.index.html
显示树,代码如下:
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>treedemo</title>
- <link rel="stylesheet" type="text/css"
- href="js_lib/easyui/themes/default/easyui.css">
- <link rel="stylesheet" type="text/css"
- href="js_lib/easyui/themes/icon.css">
- <script type="text/javascript" src="js_lib/jquery-1.8.3.min.js"></script>
- <script type="text/javascript"
- src="js_lib/easyui/jquery.easyui.min.js"></script>
- <script type="text/javascript"
- src="js_lib/easyui/easyui-lang-zh_CN.js"></script>
- <script type="text/javascript"
- src="js/index.js"></script>
- </head>
- <body>
- <div style="width: 30%; position: absolute; top: 34px; bottom: 0;">
- <ul id="vl" data-options="region:'center',border: true"
- class="easyui-tree">
- </ul>
- </div>
- </body>
- </html>
四、总结
1.前台代码并不复杂,只是一个控件,关键是后台的逻辑代码;
2.首先自己定义了一个树的数据模型,然后再从数据库中查找出数据,通过工具方法将数据封装到树model里,默认从根节点开始查找。