首页 > 数据库技术 > 详细

Extjs4 treePanel异步加载菜单(后台从数据库读取)

时间:2015-12-11 22:05:05      阅读:772      评论:0      收藏:0      [点我收藏+]

运行环境:springMVC+mybatis

 

一、建表

技术分享

说明:0表示此节点为非叶子节点,即此节点还包括了子节点;1表示此节点为叶子节点,即此节点没有子节点。

二、运用mybatis 的generator插件自动生成pojo、映射文件及访问接口并做适当的添加修改。

1.pojo

package com.shyy.web.entity;

import java.util.List;

public class Tree {
    private String id;

    private String text;

    private String iconCls;

    private Boolean leaf;

    private String fatherId;

    private List<Tree> children;

    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 getIconCls() {
        return iconCls;
    }

    public void setIconCls(String iconCls) {
        this.iconCls = iconCls;
    }

    public Boolean getLeaf() {
        return leaf;
    }

    public void setLeaf(Boolean leaf) {
        this.leaf = leaf;
    }

    public String getFatherId() {
        return fatherId;
    }

    public void setFatherId(String fatherId) {
        this.fatherId = fatherId;
    }

    public List<Tree> getChildren() {
        return children;
    }

    public void setChildren(List<Tree> children) {
        this.children = children;
    }

    @Override
    public String toString() {
        return "Tree{" +
                "id=‘" + id + ‘\‘‘ +
                ", text=‘" + text + ‘\‘‘ +
                ", iconCls=‘" + iconCls + ‘\‘‘ +
                ", leaf=" + leaf +
                ", fatherId=‘" + fatherId + ‘\‘‘ +
                ", children=" + children +
                ‘}‘;
    }
}

2.映射文件:

需要注意的是, <result property="leaf" column="leaf" jdbcType="TINYINT" javaType="Boolean" />这样的话,mybatis就会自动将数据库中的TINYINT类型的leaf转化成布尔类型,0会转化为false,1会转化为true。这里一定要有这个,不然在执行时会报异常。

<?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="com.shyy.web.service.TreeMapper" >
  <resultMap id="BaseResultMap" type="com.shyy.web.entity.Tree" >
    <id column="id" property="id" jdbcType="VARCHAR" />
    <result column="text" property="text" jdbcType="VARCHAR" />
    <result column="iconCls" property="iconCls" jdbcType="VARCHAR" />
    <result column="leaf" property="leaf" jdbcType="TINYINT" javaType="Boolean" />
    <result column="fatherId" property="fatherId" jdbcType="VARCHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, text, iconCls, leaf, fatherId
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
    select 
    <include refid="Base_Column_List" />
    from t_tree
    where id = #{id,jdbcType=VARCHAR}
  </select>
  <select id="getFather" resultMap="BaseResultMap">
      SELECT
      <include refid="Base_Column_List" />
      FROM t_tree
      WHERE fatherId IS NULL
  </select>
  <select id="getChildren" resultMap="BaseResultMap" parameterType="java.lang.String">
      SELECT
      <include refid="Base_Column_List" />
      FROM t_tree
      WHERE fatherId = #{fatherId}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
    delete from t_tree
    where id = #{id,jdbcType=VARCHAR}
  </delete>
  <insert id="insert" parameterType="com.shyy.web.entity.Tree" >
    insert into t_tree (id, text, iconCls, 
      leaf, fatherId)
    values (#{id,jdbcType=VARCHAR}, #{text,jdbcType=VARCHAR}, #{iconCls,jdbcType=VARCHAR}, 
      #{leaf,jdbcType=TINYINT}, #{fatherId,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.shyy.web.entity.Tree" >
    insert into t_tree
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="text != null" >
        text,
      </if>
      <if test="iconCls != null" >
        iconCls,
      </if>
      <if test="leaf != null" >
        leaf,
      </if>
      <if test="fatherId != null" >
        fatherId,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=VARCHAR},
      </if>
      <if test="text != null" >
        #{text,jdbcType=VARCHAR},
      </if>
      <if test="iconCls != null" >
        #{iconCls,jdbcType=VARCHAR},
      </if>
      <if test="leaf != null" >
        #{leaf,jdbcType=TINYINT},
      </if>
      <if test="fatherId != null" >
        #{fatherId,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.shyy.web.entity.Tree" >
    update t_tree
    <set >
      <if test="text != null" >
        text = #{text,jdbcType=VARCHAR},
      </if>
      <if test="iconCls != null" >
        iconCls = #{iconCls,jdbcType=VARCHAR},
      </if>
      <if test="leaf != null" >
        leaf = #{leaf,jdbcType=TINYINT},
      </if>
      <if test="fatherId != null" >
        fatherId = #{fatherId,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=VARCHAR}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.shyy.web.entity.Tree" >
    update t_tree
    set text = #{text,jdbcType=VARCHAR},
      iconCls = #{iconCls,jdbcType=VARCHAR},
      leaf = #{leaf,jdbcType=TINYINT},
      fatherId = #{fatherId,jdbcType=VARCHAR}
    where id = #{id,jdbcType=VARCHAR}
  </update>
</mapper>

3.访问映射文件的接口(没有实现类,直接由该接口访问对应的映射文件)

package com.shyy.web.service;

import com.shyy.web.entity.Tree;

import java.util.List;

public interface TreeMapper {
    int deleteByPrimaryKey(String id);

    int insert(Tree record);

    int insertSelective(Tree record);

    Tree selectByPrimaryKey(String id);

    List<Tree> getFather();

    List<Tree> getChildren(String id);

    int updateByPrimaryKeySelective(Tree record);

    int updateByPrimaryKey(Tree record);
}

4.控制层代码

package com.shyy.web.controller.anntation;

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

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

import com.shyy.web.entity.Tree;
import com.shyy.web.service.TreeMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.shyy.web.controller.response.EmptyResponse;
import com.shyy.web.controller.response.NormalResponse;
import com.shyy.web.controller.response.Response;
import com.shyy.web.entity.Privilege;
import com.shyy.web.service.PrivilegeService;
import com.shyy.web.service.impl.PrivilegeServiceImpl;

@Controller
@RequestMapping("/menu/")
public class PrivilegeController {

    Logger logger = LoggerFactory.getLogger(PrivilegeController.class);

    @Autowired
    private TreeMapper treeMapper;


    @SuppressWarnings("unused")
    @RequestMapping("showmyMenu")
    @ResponseBody
    public List<Tree> myMenus(HttpServletRequest req, HttpServletResponse resp) {
        System.out.println("-aaa--");
        List<Tree> pris = treeMapper.getFather();//一级菜单
        List<Tree> menus = new ArrayList<Tree>();

        for(Tree pri:pris){//迭代一级菜单找二级菜单
            List<Tree> prisNode = treeMapper.getChildren(pri.getId());//二级菜单
            pri.setChildren(prisNode);

            for (Tree privilege : prisNode) {//迭代二级菜单找三级菜单
                List<Tree> childNode = treeMapper.getChildren(privilege.getId());//三级菜单
                privilege.setChildren(childNode);
                //如果有四级菜单,则需迭代三级菜单找四级菜单
            }
            menus.add(pri);
        }

        System.out.println(menus);

        if (menus != null || menus.size() > 0) {
            return menus;
        } else {
            return null;
        }
    }

    public String test(){
        return "wang";
    }

}

js代码:

Ext.onReady(function(){

            var model = Ext.define("TreeModel", { // 定义树节点数据模型
                extend : "Ext.data.Model",
                fields : [{name : "id",type : "string"},
                    {name : "text",type : "string"},
                    {name : "iconCls",type : "string"},
                    {name : "leaf",type : "boolean"},
                    {name : ‘url‘,type:"string"},
                    {name : ‘description‘,type:"string"}]
            });

            var store = Ext.create(‘Ext.data.TreeStore‘, {
                model : model,//定义当前store对象的Model数据模型
//                autoLoad : true,
                proxy : {
                    type : ‘ajax‘,
                    url : ‘../menu/showmyMenu‘,//请求
                    reader : {
                        type : ‘json‘,
//                        root : ‘data‘//数据
                    }
                },
                root : {//定义根节点,此配置是必须的
//                    text : ‘管理菜单‘,
                    expanded : true
                }

            });

            Ext.create(‘Ext.tree.Panel‘, {
                title: ‘Simple Tree‘,
                width: 200,
                height: 550,
                store: store,
                rootVisible: false,//隐藏根节点
                renderTo: Ext.getBody()
            });

  });

说明:在http://liuchangming1993-126-com.iteye.com/blog/1938482文章中的博主用的struts2,返回形式与本文的springMVC不同,因此这里没有指定root属性。

 

下面看一下js中的ajax请求返回的数据(片段):

[Tree{id=‘101‘, text=‘图像报表‘, iconCls=‘Chartbar‘, leaf=false, fatherId=‘null‘,
children=[Tree{id=‘1001‘, text=‘饼状图‘, iconCls=‘Chartpie‘, leaf=false, fatherId=‘101‘, children=[Tree{id=‘10001‘, text=‘饼状图一‘, iconCls=‘Chartpieadd‘, leaf=true, fatherId=‘1001‘, children=null}, Tree{id=‘10002‘, text=‘饼状图二‘, iconCls=‘Chartpiedelete‘, leaf=true, fatherId=‘1001‘, children=null}]},
Tree{id=‘1002‘, text=‘线状图‘, iconCls=‘Chartline‘, leaf=false, fatherId=‘101‘, children=[Tree{id=‘10003‘, text=‘线状图一‘, iconCls=‘Chartcurveadd‘, leaf=true, fatherId=‘1002‘, children=null}, Tree{id=‘10004‘, text=‘线状图二‘, iconCls=‘Chartcurvedelete‘, leaf=true, fatherId=‘1002‘, children=null}]}]}]

可以看出是reader 将对象的数据转化成了json格式。

 

运行效果:

技术分享

 

方法二

这里的逻辑是一次性加载完所有的菜单返回至前台,在http://liuchangming1993-126-com.iteye.com/blog/1938482的博客中用到的是另一种方式,即根据用户点击的菜单展开子菜单。

现在用这种方式实现一下:

说明:因为之前建的表t_tree与pojo的主键都是id,发现与Extjs冲突,所以这次将表的主键改为tid,然后自动生成相应代码。

一、在映射文件中加一个sql

    <select id="findLeaf" parameterType="String" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_List" />
        FROM t_tree
        WHERE 1=1
        <choose>
            <when test="_parameter!=null and _parameter!=‘‘">
                and fatherId = #{fatherId}
            </when>
            <otherwise>
                and fatherId IS NULL
            </otherwise>
        </choose>
    </select>

二、修改访问映射文件的接口,即增加访问上面sql的方法

package com.shyy.web.service;

import com.shyy.web.entity.Tree;

import java.util.List;

public interface TreeMapper {
    int deleteByPrimaryKey(String tid);

    int insert(Tree record);

    int insertSelective(Tree record);

    Tree selectByPrimaryKey(String tid);

    List<Tree> getFather();

    List<Tree> getChildren(String id);

    List<Tree> findLeaf(String id);

    int updateByPrimaryKeySelective(Tree record);

    int updateByPrimaryKey(Tree record);
}

三、修改控制器,增加一个方法

    @SuppressWarnings("unused")
    @RequestMapping("showmyMenu2")
    @ResponseBody
    public List<Tree> myMenus2(HttpServletRequest req, HttpServletResponse resp,@RequestParam String tid) {

        System.out.println("tid:"+tid);

        List<Tree> menus = new ArrayList<Tree>();
        menus = treeMapper.findLeaf(tid);

        if (menus != null || menus.size() > 0) {
            return menus;
        } else {
            return null;
        }
    }

四、修改js

        Ext.onReady(function(){
            var store = Ext.create(‘Ext.data.TreeStore‘, {
                autoLoad : true,
                proxy : {
                    type : ‘ajax‘,
                    url : ‘../menu/showmyMenu2‘,//请求
                    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,
                rootVisible: false,
                store : store
            });

        });

注:

1. 这个配置默认是false,但是即使注释掉此配置也是没有影响的;

2.可以看出上面的js已去掉了model 配置,是没有影响的,在Ext.data.TreeStore的API中有这样的说明:

Using Models 用例模型

如果未指定模型Model,将创建实现于Ext.data.NodeInterface的一种隐式模型。 标准的Tree字段列表也将被复制到Model上来保持自身的状态。 在Ext.data.NodeInterface文档中列出了这些字段。

 

那么model是干嘛的(如上面的创建的继承于Ext.data.Model的实例"TreeModel"),NodeInterface又是干嘛的?下面看一下Ext.data.NodeInterface的API简介:

本类是一个应用到Model的原型上的方法集合,使其具有Node API。这意味着树状模型 具有所有与树相关的方法。通常情况下, 开发者不会直接使用本类。为了保存树的状态和UI, 本类会在模型上创建一些额外的字段(如果它们不存在)。 这些字段记录为config选项。

 

到这里model的作用就明确了,举例来说,像本文定义的model,比如它有一个字段名为“leaf”,那么由于在Ext.data.NodeInterface中也具有这个配置属性,所以这个leaf的值会在加载时起作用。其他定义的字段在树面板上起到什么作用则均可在Ext.data.NodeInterface找到答案。

 

在api中可以看出Ext.data.TreeStore继承了Ext.data.NodeStore,而Ext.data.NodeStore的接口正是Ext.data.NodeInterface

 

3.上面js中listeners 定义的‘beforeexpand’事件也来源于Ext.data.NodeInterface。在本节点展开前触发。

 

4.reader 中的root配置,在Ext.data.TreeStore的API中有这样的说明:

Reading Nested Data 读取内嵌数据

对于树读取内嵌数据,在Ext.data.reader.Reader中必须配置一个root属性, 这样reader可以找到关于每个节点的内嵌数据。 如果未指定root,那么它将默认为‘children‘

这里介绍它的作用是“读取内嵌数据”,我并未指定,然而它说默认为‘children’,刚好我在设计菜单的pojo时对于子菜单属性的引用名就是children:

 

private List<Tree> children;

 

所以如果上面的引用是别的什么,那么就要指定了?——这里不作测试了。

 

 

运行效果:

技术分享

 

Extjs4 treePanel异步加载菜单(后台从数据库读取)

原文:http://www.cnblogs.com/wql025/p/5040165.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!