这篇文章来实现树形菜单,和大多数权限功能类似,这里总共需要五张表,分别是:菜单表-v_menu、用户表-v_user、角色表v_role、菜单角色表-v_menu_role、用户角色表表v_user_role。
相关代码及数据库已经上传到gitee:https://gitee.com/king-high/vms-master
1. 实体类
package com.javaboy.vms.entity; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.util.List; /** * @author: gaoyang * @date: 2021-04-20 16:31:24 * @description: 菜单(VMenu)实体类 */ @Getter @Setter public class VMenu implements Serializable { private static final long serialVersionUID = 130350349649865335L; /** * 主键 */ private Integer id; /** * 权限控制使用 */ private String url; /** * 前端请求路径 */ private String path; /** * 组件名 */ private String component; /** * 组件名称 */ private String name; /** * 菜单图标 */ private String iconCls; /** * 是否保活:前端是否在内存中销毁 */ private Boolean keepAlive; /** * 是否需要认证 */ private Boolean requireAuth; /** * 父级id */ private Integer parentId; /** * 是否启用 */ private Boolean enabled; private List<VMenu> children; }
其他省略…
2. 菜单接口
package com.javaboy.vms.controller.system; import com.javaboy.vms.entity.VMenu; import com.javaboy.vms.service.VMenuService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** * 菜单(VMenu)表控制层 * * @author gaoyang * @since 2021-04-20 16:34:12 */ @RestController @RequestMapping("/menu") public class VMenuController { /** * 服务对象 */ @Resource private VMenuService vMenuService; /** * 根据登录的 userId 查询权限菜单 * @return */ @GetMapping("/auth") public List<VMenu> getMenusByHrId() { return this.vMenuService.getMenusByUserId(); } }
一般来说,前端传过来的数据是不可信的。比如数据校验,前端校验了,后端也是需要校验一遍的,这里的 userId 我们不从前端传值,由后端获取。
2. 实现
package com.javaboy.vms.service.impl; import com.javaboy.vms.entity.VMenu; import com.javaboy.vms.mapper.VMenuMapper; import com.javaboy.vms.service.VMenuService; import com.javaboy.vms.util.UserUtil; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; /** * @author: gaoyang * @date: 2021-04-20 16:37:25 * @description: 菜单(VMenu)表服务实现类 */ @Service("vMenuService") public class VMenuServiceImpl implements VMenuService { @Resource private VMenuMapper vMenuMapper; @Override public List<VMenu> getMenusByUserId() { Integer userId = UserUtil.getCurrentHr().getId(); List<VMenu> menus = this.vMenuMapper.getMenusByUserId(userId); List<VMenu> menuTree = new ArrayList<>(); menus.forEach(menu -> { // 判断是否为顶层节点 if (menu.getParentId() == 1) { // 获取子节点 menu.setChildren(this.getChildTree(menu.getId(), menus)); menuTree.add(menu); } }); return menuTree; } private List<VMenu> getChildTree(Integer id, List<VMenu> menuList) { List<VMenu> childList = new ArrayList<>(); // 循环获取子节点 menuList.forEach(menu -> { if (menu.getParentId() != null){ if (menu.getParentId().equals(id)) { childList.add(menu); } } }); // 获取子节点的子节点 childList.forEach(menu -> { // 递归获取子节点 List<VMenu> childTree = this.getChildTree(menu.getId(), menuList); if (childTree.size() > 0) { menu.setChildren(childTree); } }); return childList; } }
3. xml
<select id="getMenusByUserId" resultMap="VMenuMap"> select m.* from v_menu m, v_menu_role mr, v_user_role ur, v_user u where m.id = mr.menu_id and mr.role_id = ur.role_id and ur.user_id = u.id and u.id = #{userId} order by m.id asc </select>
service、mapper 自行实现。
4. 测试
先登录,再测试权限菜单
5. 总结
这里的权限菜单是使用的Java递归调用,也比较方便,如果需要mybatis直接实现权限菜单,网上应该有许多例子,大家可以查一下。现在已经实现了最基础的功能:登录认证、权限菜单,接下来就是认证核心-权限设计了。