SpringSecurity系列(一) 初识 Spring Security
SpringSecurity系列(二) Spring Security入门
SpringSecurity系列(三) Spring Security 表单登录
这篇文章来实现树形菜单,和大多数权限功能类似,这里总共需要五张表,分别是:菜单表-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直接实现权限菜单,网上应该有许多例子,大家可以查一下。现在已经实现了最基础的功能:登录认证、权限菜单,接下来就是认证核心-权限设计了。