您的位置:首页 > 数据库 > Redis

基于springboot+redis+bootstrap+mysql开发一套属于自己的分布式springcloud云权限架构(十二)【权限架构生产者(菜单管理)】

2018-02-22 21:15 896 查看
      在第十一章我们完成了对组织架构管理的集成,本章我们将完成对菜单管理的集成开发工作,首先打开我们的rbac-produce工程,接着在com/produce/sys/dao目录底下创建一个UserDao.java接口内容如下:package com.produce.sys.dao;

import com.base.entity.QueryTree;
import com.base.entity.Tree;
import com.base.entity.User;
import com.produce.common.base.dao.GenericDao;

import java.util.List;

/**
*@author linzf
**/
public interface TreeDao extends GenericDao<Tree, QueryTree> {

/**
* 功能描述:加载用户的菜单树的数据
* @param user
* @return
*/
List<Tree> loadUserTree(User user);
}      接着在我们的mapper文件夹底下创建一个mybatis_tree.xml文件,文件内容如下:<?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.produce.sys.dao.TreeDao">
<resultMap type="com.base.entity.Tree" id="TreeMap">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="icon" column="icon"/>
<result property="name" column="name"/>
<result property="pId" column="p_id"/>
<result property="treeOrder" column="tree_order"/>
<result property="url" column="url"/>
<result property="state" column="state"/>
</resultMap>

<!-- 加载用户的菜单树的数据 -->
<select id="loadUserTree" resultMap="TreeMap" parameterType="com.base.entity.User">
select DISTINCT t.* from tree t inner join role_associate_tree rat on t.id = rat.tree_id inner join user_role ur on rat.role_id = ur.id where ur.id in
<foreach collection="roles" index="index" item="role" open="(" separator="," close=")">
#{role.id}
</foreach>
</select>

<!--根据主键获取对象-->
<select id="get" parameterType="com.base.entity.Tree" resultMap="TreeMap">
SELECT id,code,icon,name,p_id,tree_order,url,state FROM tree
WHERE id=#{id}
</select>

<!--保存-->
<insert id="save" parameterType="com.base.entity.Tree" useGeneratedKeys="true" keyProperty="id">
INSERT INTO tree(code,icon,name,p_id,tree_order,url,state)
VALUES(#{code},#{icon},#{name},#{pId},#{treeOrder},#{url},#{state})
</insert>

<!--修改-->
<update id="update" parameterType="com.base.entity.Tree">
UPDATE tree SET code=#{code},icon=#{icon},name=#{name},p_id=#{pId},tree_order=#{treeOrder},url=#{url},state=#{state}
WHERE id=#{id}
</update>

<!--删除-->
<delete id="delete" parameterType="com.base.entity.Tree">
DELETE FROM tree WHERE id=#{id}
</delete>

<!--分页查询-->
<select id="findByPage" parameterType="com.base.entity.QueryTree" resultMap="TreeMap">
SELECT id,code,icon,name,p_id,tree_order,url,state FROM tree
WHERE 1=1
<if test="code!=null and code!='' ">
AND code=#{code}
</if>
<if test="icon!=null and icon!='' ">
AND icon=#{icon}
</if>
<if test="name!=null and name!='' ">
AND name=#{name}
</if>
<if test="pId!=null and pId!='' ">
AND p_id=#{pId}
</if>
<if test="treeOrder!=null and treeOrder!='' ">
AND tree_order=#{treeOrder}
</if>
<if test="url!=null and url!='' ">
AND url=#{url}
</if>
<if test="state!=null and state!='' ">
AND state=#{state}
</if>
<if test="sort!= null and sort!='' ">
order by ${sort} ${order}
</if>
limit #{offset},#{limit}
</select>

<!--统计-->
<select id="count" parameterType="com.base.entity.QueryTree" resultType="int">
SELECT count(*) FROM tree
WHERE 1=1
<if test="code!=null and code!='' ">
AND code=#{code}
</if>
<if test="icon!=null and icon!='' ">
AND icon=#{icon}
</if>
<if test="name!=null and name!='' ">
AND name=#{name}
</if>
<if test="pId!=null and pId!='' ">
AND p_id=#{pId}
</if>
<if test="treeOrder!=null and treeOrder!='' ">
AND tree_order=#{treeOrder}
</if>
<if test="url!=null and url!='' ">
AND url=#{url}
</if>
<if test="state!=null and state!='' ">
AND state=#{state}
</if>
<if test="sort!= null and sort!='' ">
order by ${sort} ${order}
</if>
</select>

<!--查询-->
<select id="query" parameterType="com.base.entity.QueryTree" resultMap="TreeMap">
SELECT id,code,icon,name,p_id,tree_order,url,state FROM tree
WHERE 1=1
<if test="code!=null and code!='' ">
AND code=#{code}
</if>
<if test="icon!=null and icon!='' ">
AND icon=#{icon}
</if>
<if test="name!=null and name!='' ">
AND name=#{name}
</if>
<if test="pId!=null and pId!='' ">
AND p_id=#{pId}
</if>
<if test="treeOrder!=null and treeOrder!='' ">
AND tree_order=#{treeOrder}
</if>
<if test="url!=null and url!='' ">
AND url=#{url}
</if>
<if test="state!=null and state!='' ">
AND state=#{state}
</if>
<if test="sort!= null and sort!='' ">
order by ${sort} ${order}
</if>
</select>
</mapper>
      由于我们对菜单进行维护的时候,我们在对角色管理的时候会对相应的角色赋予相应的菜单,因此在我们删除某些菜单的时候,我们需要同时删除菜单与角色相关联的数据,因此我们需要在com/produce/sys/dao目录底下创建一个RoleAssociateTreeDao.java接口内容如下:package com.produce.sys.dao;

import com.base.entity.QueryRoleAssociateTree;
import com.base.entity.RoleAssociateTree;
import com.base.entity.Tree;
import com.base.entity.UserRole;
import com.produce.common.base.dao.GenericDao;

/**
*@author linzf
**/
public interface RoleAssociateTreeDao extends GenericDao<RoleAssociateTree, QueryRoleAssociateTree> {

/**
* 功能描述:根据菜单ID来删除关联的菜单数据
* @param tree
* @return
*/
int removeTreeByTreeId(Tree tree);

/**
* 功能描述:根据角色ID来删除关联的菜单数据
* @param userRole
* @return
*/
int removeTreeByRoleId(UserRole userRole);

}      接着在我们的mapper文件夹底下创建一个mybatis_roleAssociateTree.xml文件,文件内容如下:<?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.produce.sys.dao.RoleAssociateTreeDao">
<resultMap type="com.base.entity.RoleAssociateTree" id="RoleAssociateTreeMap">
<result property="roleId" column="role_id"/>
<result property="treeId" column="tree_id"/>
</resultMap>

<!-- 根据菜单ID来删除关联的菜单数据 -->
<delete id="removeTreeByTreeId" parameterType="com.base.entity.Tree">
delete from role_associate_tree where tree_id = #{id}
</delete>

<!-- 根据角色ID来删除关联的菜单数据 -->
<delete id="removeTreeByRoleId" parameterType="com.base.entity.UserRole">
delete from role_associate_tree where role_id = #{id}
</delete>

<!--根据主键获取对象-->
<select id="get" parameterType="com.base.entity.RoleAssociateTree" resultMap="RoleAssociateTreeMap">
SELECT role_id,tree_id FROM role_associate_tree
WHERE
</select>

<!--保存-->
<insert id="save" parameterType="com.base.entity.RoleAssociateTree">
INSERT INTO role_associate_tree(role_id,tree_id)
VALUES(#{roleId},#{treeId})
</insert>

<!--修改-->
<update id="update" parameterType="com.base.entity.RoleAssociateTree">
UPDATE role_associate_tree SET role_id=#{roleId},tree_id=#{treeId}
WHERE
</update>

<!--删除-->
<delete id="delete" parameterType="com.base.entity.RoleAssociateTree">
DELETE FROM role_associate_tree WHERE
</delete>

<!--分页查询-->
<select id="findByPage" parameterType="com.base.entity.QueryRoleAssociateTree" resultMap="RoleAssociateTreeMap">
SELECT role_id,tree_id FROM role_associate_tree
WHERE 1=1
<if test="roleId!=null and roleId!='' " >
AND role_id=#{roleId}
</if>
<if test="treeId!=null and treeId!='' " >
AND tree_id=#{treeId}
</if>
<if test="sort!= null">
order by ${sort} ${order}
</if>
limit #{offset},#{limit}
</select>

<!--统计-->
<select id="count" parameterType="com.base.entity.QueryRoleAssociateTree" resultType="int">
SELECT count(*) FROM role_associate_tree
WHERE 1=1
<if test="roleId!=null and roleId!='' ">
AND role_id=#{roleId}
</if>
<if test="treeId!=null and treeId!='' ">
AND tree_id=#{treeId}
</if>
</select>

<!--查询-->
<select id="query" parameterType="com.base.entity.QueryRoleAssociateTree" resultMap="RoleAssociateTreeMap">
SELECT role_id,tree_id FROM role_associate_tree
WHERE 1=1
<if test="roleId!=null and roleId!='' ">
AND role_id=#{roleId}
</if>
<if test="treeId!=null and treeId!='' ">
AND tree_id=#{treeId}
</if>
<if test="sort!= null">
order by ${sort} ${order}
</if>
</select>
</mapper>      在我们的用户加载菜单的时候,我们需要根据用户的信息来实现加载菜单,因此我们需要在我们的rbac-produce工程中引入redis的依赖以及注入redis和redis的配置,因此我们需要分别修改以下的文件:
1、在主入口类引入如下的配置:



2、在com/produce/common/util底下创建一个node包,同时在该包底下创建NodeUtil.java类内容如下:package com.produce.common.util.node;

import com.base.entity.Tree;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/*
* 类描述:
* @auther linzf
* @create 2017/9/20 0020
*/
public class NodeUtil {

private static List<Tree> returnList = new ArrayList<Tree>();

/**
* 根据父节点的ID获取所有子节点
* @param list 分类表
* @param typeId 传入的父节点ID
* @return String
*/
public static List<Tree> getChildNodes(List<Tree> list, Long typeId) {
returnList = new ArrayList<Tree>();
if(list == null && typeId == null) return new ArrayList<Tree>();
for (Iterator<Tree> iterator = list.iterator(); iterator.hasNext();) {
Tree node = (Tree) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (node.getpId()==0 && typeId==node.getId()) {
recursionFn(list, node);
}
// 二、遍历所有的父节点下的所有子节点
if (node.getpId()==0) {
recursionFn(list, node);
}
}
// 对顶层菜单按照treeOrder从大到小进行进行排序
Collections.sort(returnList);
return returnList;
}

private static void recursionFn(List<Tree> list, Tree node) {
List<Tree> childList = getChildList(list, node);// 得到子节点列表
if (hasChild(list, node)) {// 判断是否有子节点
Iterator<Tree> it = childList.iterator();
while (it.hasNext()) {
Tree n = (Tree) it.next();
if(hasChild(list,n)){// 判断子节点是否还有相应的子节点,若有则再次递归遍历
recursionFn(list, n);
}
}
node.setChild(childList);
returnList.add(node);
}
}

// 得到子节点列表
private static List<Tree> getChildList(List<Tree> list, Tree node) {
List<Tree> nodeList = new ArrayList<Tree>();
Iterator<Tree> it = list.iterator();
while (it.hasNext()) {
Tree n = (Tree) it.next();
if (n.getpId() == node.getId()) {
nodeList.add(n);
}
}
Collections.sort(nodeList);
return nodeList;
}

// 判断是否有子节点
private static boolean hasChild(List<Tree> list, Tree node) {
return getChildList(list, node).size() > 0 ? true : false;
}

}
3、在com/produce/common/util/user包的UserInfo.java类中增加以下的方法:/**
* 功能描述:加载菜单节点的数据
* @return
*/
public static List<Tree> loadUserTree(TreeService treeService, User user){
Map<Long,Tree> treeMap = new HashMap<Long,Tree>();
for(Tree tree:treeService.loadUserTree(user)){
treeMap.put(tree.getId(),tree);
}
List<Tree> treeList = NodeUtil.getChildNodes(new ArrayList<Tree>(treeMap.values()),0l);
return treeList;
}      最后在我们的com/produce/sys/controller底下创建我们的TreeController.java实现类内容如下:package com.produce.sys.controller;

import com.base.entity.QueryTree;
import com.base.entity.Tree;
import com.base.entity.User;
import com.base.util.redis.RedisCache;
import com.produce.common.base.constant.SystemStaticConst;
import com.produce.common.base.controller.GenericController;
import com.produce.common.base.service.GenericService;
import com.produce.common.util.user.UserInfo;
import com.produce.sys.service.TreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframewor
b5e6
k.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
* 类描述:菜单操作controller
* @auther linzf
* @create 2017/10/10 0010
*/
@RestController
@RequestMapping("/tree")
public class TreeController extends GenericController<Tree,QueryTree> {

@Autowired
private TreeService treeService;

@Autowired
private RedisCache redisCache;

@Override
protected GenericService<Tree, QueryTree> getService() {
return treeService;
}

/**
* 功能描述:加载首页菜单节点的数据
* @return
*/
@RequestMapping(value="/mainTree",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String,Object> mainTree(String token){
Map<String,Object> result = new HashMap<String, Object>();
List<Tree> trees = UserInfo.loadUserTree(treeService,(User)redisCache.getObject(token,User.class));
result.put("data",trees);
result.put(SystemStaticConst.RESULT, SystemStaticConst.SUCCESS);
return result;
}

/**
* 功能描述:直接加载整个菜单树的数据(且必须要有管理员权限才可以加载该菜单树的数据)
* @return
*/
@RequestMapping(value = "/loadUserTree",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String,Object> loadUserTree(){
Map<String,Object> result = new HashMap<String, Object>();
List<Tree> treeList = treeService.query(null);
result.put(SystemStaticConst.RESULT, SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"加载菜单数据成功!");
result.put("data",treeList);
return result;
}

}
      到此处我们完成了对菜单管理的集成,接着启动我们的注册中心,链路中心同时启动我们的rbac-produce,接着直接访问我们的swagger工程地址:http://127.0.0.1:8100/swagger-ui.html#/,那么我们会看到如下的页面则表示我们的菜单管理已经集成成功了。



      到此为止的GitHub项目地址:https://github.com/185594-5-27/spring-cloud-rbac/tree/master-base-produce-tree

上一篇文章地址:基于springboot+redis+bootstrap+mysql开发一套属于自己的分布式springcloud云权限架构(十一)【权限架构生产者(组织架构)】下一篇文章地址:基于springboot+redis+bootstrap+mysql开发一套属于自己的分布式springcloud云权限架构(十三)【权限架构生产者(改造角色管理)】
QQ交流群:578746866
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐