rbac权限模型之从数据库读取菜单,递归生成菜单树

先设计数据库,数据库设计如下:


SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for jrbac_menu
-- ----------------------------
DROP TABLE IF EXISTS `jrbac_menu`;
CREATE TABLE `jrbac_menu`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id,uuid32位',
  `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录用户名',
  `parent_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父菜单id',
  `url` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '访问地址',
  `icon` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '菜单图标',
  `m_order` tinyint(4) DEFAULT 0 COMMENT '菜单顺序',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单表' ROW_FORMAT = Compact;

-- ----------------------------
-- Records of jrbac_menu
-- ----------------------------
INSERT INTO `jrbac_menu` VALUES ('1', 'Forms', NULL, 'forms.html', 'fa fa-edit', 0);
INSERT INTO `jrbac_menu` VALUES ('2', 'UI Elements', NULL, '', 'fa fa-wrench', 1);
INSERT INTO `jrbac_menu` VALUES ('3', 'Buttons', '2', 'buttons.html', '', 0);
INSERT INTO `jrbac_menu` VALUES ('4', 'Icons', '2', 'icons.html', NULL, 1);
INSERT INTO `jrbac_menu` VALUES ('5', 'Multi-Level Dropdown', '', '', 'fa fa-sitemap', 2);
INSERT INTO `jrbac_menu` VALUES ('6', 'Second Level Item', '5', 'second.html', NULL, 0);
INSERT INTO `jrbac_menu` VALUES ('7', 'Third Level', '5', NULL, '', 1);
INSERT INTO `jrbac_menu` VALUES ('8', 'Third Level Item', '7', 'third.html', NULL, 0);

SET FOREIGN_KEY_CHECKS = 1;

菜单表字段分别有主键id、登录用户名、父菜单id、点击后的访问地址、菜单图标以及菜单顺序(优先级),并插入了一些数据,最顶级菜单的父菜单id为空

在java springboot中先在xml配置文件创建一个查询的mapperxml:

<?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.example.demo.mapper.MenuMapper">
    <select id="menuList" resultType="com.example.demo.entity.Menu">
        select * from jrbac_menu order by m_order;
    </select>
</mapper>

数据库交互使用的是mybatis-plus可以自动转驼峰。

mapper层:

public interface MenuMapper extends BaseMapper<Menu> {
    List<Menu> menuList();
}

service层:

public interface MenuService extends IService<Menu> {
    List<Menu> menuList();
}

service层的impl层:

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Override
    public List<Menu> menuList() {
        return this.baseMapper.menuList();
    }
}

菜单pojo(javabean实体类):

@Data //注解自动生成set、get、tostring方法
public class Menu {
    private String id;
    private String name;
    private String parentId;
    private String url;
    private String icon;
    private Long mOrder;
    //存放子菜单的列表
    private List<Menu> childMenus;
}

controller层:

@Controller
@RequestMapping("menu")

public class MenuController {
    @Autowired
    private MenuService menuService;
    @RequestMapping("menuJson")
    @ResponseBody
    public List<Menu> jsonMenu(){
        //获取全部菜单
        List<Menu> pmenu = menuService.menuList();
        List<Menu> jsonMenu=new ArrayList<>();
        //遍历菜单,判断是一级菜单的添加到要返回的json数据
        for(Menu menu:pmenu){
            if(StringUtils.isEmpty(menu.getParentId())){
                jsonMenu.add(menu);
            }
        }
        //给一级菜单添加子菜单,调用下面的递归方法加入进去
        for(Menu menu:jsonMenu){
            menu.setChildMenus(getChild(menu.getId(),pmenu));
        }
        return jsonMenu;
    }

    //添加子菜单的递归方法
    private List<Menu> getChild(String id, List<Menu> pmenu) {
        List<Menu> jsonMenu=new ArrayList<>();
        //遍历全部菜单,是否有符合即不是一级菜单又父菜单id等于参数id的,添加到list中
        for(Menu menu:pmenu){
            if(!StringUtils.isEmpty(menu.getParentId())) {
                if (menu.getParentId().equals(id)) {
                    jsonMenu.add(menu);
                }
            }
        }
        //遍历子菜单,看子菜单是否有点击路径,没有说明还有子菜单下还有子菜单继续递归添加子菜单
        for(Menu menu:jsonMenu){
            if(StringUtils.isEmpty(menu.getUrl())){
                menu.setChildMenus(getChild(menu.getId(), pmenu));
            }
        }
        //递归出口,若返回的子菜单list是空,就结束
        if(jsonMenu.size()==0){
            return null;
        }
        return jsonMenu;
    }
}

使用postman测试结果:

[
    {
        "id": "1",
        "name": "Forms",
        "parentId": null,
        "url": "forms.html",
        "icon": "fa fa-edit",
        "childMenus": null,
        "morder": 0
    },
    {
        "id": "2",
        "name": "UI Elements",
        "parentId": null,
        "url": "",
        "icon": "fa fa-wrench",
        "childMenus": [
            {
                "id": "3",
                "name": "Buttons",
                "parentId": "2",
                "url": "buttons.html",
                "icon": "",
                "childMenus": null,
                "morder": 0
            },
            {
                "id": "4",
                "name": "Icons",
                "parentId": "2",
                "url": "icons.html",
                "icon": null,
                "childMenus": null,
                "morder": 1
            }
        ],
        "morder": 1
    },
    {
        "id": "5",
        "name": "Multi-Level Dropdown",
        "parentId": "",
        "url": "",
        "icon": "fa fa-sitemap",
        "childMenus": [
            {
                "id": "6",
                "name": "Second Level Item",
                "parentId": "5",
                "url": "second.html",
                "icon": null,
                "childMenus": null,
                "morder": 0
            },
            {
                "id": "7",
                "name": "Third Level",
                "parentId": "5",
                "url": null,
                "icon": "",
                "childMenus": [
                    {
                        "id": "8",
                        "name": "Third Level Item",
                        "parentId": "7",
                        "url": "third.html",
                        "icon": null,
                        "childMenus": null,
                        "morder": 0
                    }
                ],
                "morder": 1
            }
        ],
        "morder": 2
    }
]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sshm_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值