深圳建筑网站建设,旅游网站建设设计,凡科门店通包括哪些产品,厦门市建设工程安全管理协会网站十一、后台模块-菜单列表
菜单指的是权限菜单#xff0c;也就是一堆权限字符串
1. 查询菜单
1.1 接口分析
需要展示菜单列表#xff0c;不需要分页。可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询。菜单要按照父菜单id和orderNum进行排序 请求方式 请求路径…十一、后台模块-菜单列表
菜单指的是权限菜单也就是一堆权限字符串
1. 查询菜单
1.1 接口分析
需要展示菜单列表不需要分页。可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询。菜单要按照父菜单id和orderNum进行排序 请求方式 请求路径 是否需求token头 GET system/menu/list 是
请求参数是query格式的
{
status : 状态menuName 菜单名
}
响应格式:
{code:200,data:[{component:组件路径,icon:build,id:2023,isFrame:1,menuName:菜单名称,menuType:C,orderNum:0,parentId:0,path:write,perms:权限字符串,remark:备注信息,status:0,visible:0},{icon:system,id:1,isFrame:1,menuName:菜单名称,menuType:M,orderNum:1,parentId:0,path:system,perms:权限字符串,remark:备注信息,status:0,visible:0}],msg:操作成功
}
2.2 代码实现
第一步: 在keke-framework工程的Vo目录新建MenuVo类写入如下用于把指定字段返回给前端
package com.keke.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;Data
NoArgsConstructor
AllArgsConstructor
public class AdminMenuVo {//菜单IDprivate Long id;//菜单名称private String menuName;//父菜单IDprivate Long parentId;//显示顺序private Integer orderNum;//路由地址private String path;//组件路径private String component;//是否为外链0是 1否private Integer isFrame;//菜单类型M目录 C菜单 F按钮private String menuType;//菜单状态0显示 1隐藏private String visible;//菜单状态0正常 1停用private String status;//权限标识private String perms;//菜单图标private String icon;//备注private String remark;
}第二步: 在keke-admin工程的controller目录新建MenuController类写入如下是查询菜单列表的访问接口
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/system/menu)
public class MenuController {Autowiredprivate MenuService menuService;//查询菜单列表GetMapping(/list)public ResponseResult selectAllMenu(Menu menu){return menuService.selectAllMenu(menu);}
}第三步把keke-framework工程的MenuService接口修改为如下增加了查询菜单列表的接口
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;import java.util.List;/*** 菜单权限表(Menu)表服务接口** author makejava* since 2023-10-18 20:55:48*/
public interface MenuService extends IServiceMenu {//查询用户权限信息ListString selectPermsByUserId(Long userId);//查询用户的路由信息也就是权限菜单ListMenu selectRouterMenuTreeByUserId(Long userId);ResponseResult selectAllMenu(Menu menu);}第四步: 把keke-framework工程的MenuServiceImpl类修改为如下增加了查询菜单列表的具体代码实现
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.constants.SystemConstants;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.domain.vo.AdminMenuVo;
import com.keke.mapper.MenuMapper;
import com.keke.service.MenuService;
import com.keke.utils.BeanCopyUtils;
import com.keke.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 菜单权限表(Menu)表服务实现类** author makejava* since 2023-10-18 20:55:48*/
Service(menuService)
public class MenuServiceImpl extends ServiceImplMenuMapper, Menu implements MenuService {//根据用户id查询权限关键字Overridepublic ListString selectPermsByUserId(Long userId) {//如果用户id为1代表管理员roles 中只需要有admin// permissions中需要有所有菜单类型为C(菜单)或者F(按钮)的状态为正常的未被删除的权限if(SecurityUtils.isAdmin()) {LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);lambdaQueryWrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);//由于我们的逻辑删除字段已经配置了所以无需封装lambdaQueryWrapperListMenu menuList list(lambdaQueryWrapper);//我们需要的是String类型的集合这里我们要进行数据的处理这里采用流的方式ListString permissions menuList.stream().map(new FunctionMenu, String() {Overridepublic String apply(Menu menu) {String perms menu.getPerms();return perms;}}).collect(Collectors.toList());return permissions;}//否则返回这个用户所具有的权限//这里我们需要进行连表查询因为我们的用户先和角色关联然后角色才跟权限关联MenuMapper menuMapper getBaseMapper();//我们期望menuMapper中有一个方法可以直接帮我们去实现这个复杂的逻辑这里直接返回return menuMapper.selectPermsByUserId(userId);}Overridepublic ListMenu selectRouterMenuTreeByUserId(Long userId) {MenuMapper menuMapper getBaseMapper();ListMenu menus null;//如果是管理员返回所有if(SecurityUtils.isAdmin()){menus menuMapper.selectAllRoutersMenu();}else {//如果不是管理员返回对应用户的菜单menus menuMapper.selectRoutersMenuTreeByUserId(userId);}//因为上面的查询都是从数据库进行查询所以无法封装children这里构建TreeListMenu menuTree buildMenuTree(menus,0L);return menuTree;}Overridepublic ResponseResult selectAllMenu(Menu menu) {//可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(menu.getMenuName()),Menu::getMenuName,menu.getMenuName());lambdaQueryWrapper.eq(StringUtils.hasText(menu.getStatus()),Menu::getStatus,menu.getStatus());//排序 parent_id和order_numlambdaQueryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum);ListMenu menus list(lambdaQueryWrapper);ListAdminMenuVo adminMenuVos BeanCopyUtils.copyBeanList(menus, AdminMenuVo.class);return ResponseResult.okResult(adminMenuVos);}/*** 构建MenuTree* 思路先找第一层级的菜单就是找到id于parentId的对应关系然后把parentId设置为Id的children* param menus* return*/private ListMenu buildMenuTree(ListMenu menus,Long parentId) {//转化流处理ListMenu menuTree menus.stream()//过滤掉除一级菜单之外的菜单.filter(menu - menu.getParentId().equals(parentId))//然后将获取其子菜单设置到children字段并返回.map(m - m.setChildren(gerChildren(m, menus))).collect(Collectors.toList());return menuTree;}//获取当前菜单的子菜单private ListMenu gerChildren(Menu menu, ListMenu menus) {//流处理遍历每一个流对象筛选出流对象的parentIdmenu的id即过滤ListMenu children menus.stream().filter(m - m.getParentId().equals(menu.getId()))//这里其实不必要写这一步的逻辑是如果有三级//可以把流对象中再过筛选出子菜单设置给对应的children并返回.map(m - m.setChildren(gerChildren(m,menus))).collect(Collectors.toList());return children;}}2.3 测试
运行前端工程打开redis打开菜单管理 2. 新增菜单
2.1 接口分析
新增权限菜单 请求方式 请求路径 是否需求token头 POST system/menu 是
请求体参数:
Menu类对应的json格式
响应格式:
{code:200,msg:操作成功
}
2.2 代码实现
第一步: 把keke-framework工程的Menu类修改为如下注意有四个字段使用了mybatisplus的字段自增
package com.keke.domain.entity;import java.util.Date;
import java.util.List;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.experimental.Accessors;/*** 菜单权限表(Menu)表实体类** author makejava* since 2023-10-18 20:55:24*/
SuppressWarnings(serial)
Data
NoArgsConstructor
AllArgsConstructor
Accessors(chain true)
TableName(sys_menu)
public class Menu {//菜单IDprivate Long id;//菜单名称private String menuName;//父菜单IDprivate Long parentId;//显示顺序private Integer orderNum;//路由地址private String path;//组件路径private String component;//是否为外链0是 1否private Integer isFrame;//菜单类型M目录 C菜单 F按钮private String menuType;//菜单状态0显示 1隐藏private String visible;//菜单状态0正常 1停用private String status;//权限标识private String perms;//菜单图标private String icon;//创建者TableField(fill FieldFill.INSERT)private Long createBy;//创建时间TableField(fill FieldFill.INSERT)private Date createTime;//更新者TableField(fill FieldFill.INSERT_UPDATE)private Long updateBy;//更新时间TableField(fill FieldFill.INSERT_UPDATE)private Date updateTime;//备注private String remark;private String delFlag;//由于数据库没有children字段所以我们要添加TableField(exist false)注解// 让mybatis在查表时不查询这个字段TableField(exist false)private ListMenu children;
}第二步: 把huanf-framework工程的MenuController类修改为如下增加了新增菜单的具体代码实现
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/menu)
public class MenuController {Autowiredprivate MenuService menuService;//查询菜单列表GetMapping(/list)public ResponseResult selectAllMenu(Menu menu){return menuService.selectAllMenu(menu);}//新增菜单PostMappingpublic ResponseResult add(RequestBody Menu menu) {menuService.save(menu);return ResponseResult.okResult();}}2.3 测试
启动工程打开前端工程redis
测试在 系统管理 页面点击 新增能否可以添加测试目录类型的菜单 3. 修改菜单
能够修改菜单但是修改的时候不能把父菜单设置为当前菜单如果设置了需要给出相应的提示。并且修改失败。
修改菜单包含两个接口一个是点击修改回显出菜单的详情信息一个是点击确定后菜单修改成功
3.1 菜单详情
3.1.1菜单详情接口分析
请求方式请求路径是否需求token头Getsystem/menu/{id}是
请求参数PathVariable格式
id: 菜单id
响应格式
{code:200,data:{icon:table,id:2017,menuName:内容管理,menuType:M,orderNum:4,parentId:0,path:content,remark:,status:0,visible:0},msg:操作成功
}
3.1.2 代码实现
controller层新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/menu)
public class MenuController {Autowiredprivate MenuService menuService;//查询菜单列表GetMapping(/list)public ResponseResult selectAllMenu(Menu menu){return menuService.selectAllMenu(menu);}//新增菜单PostMappingpublic ResponseResult add(RequestBody Menu menu) {menuService.save(menu);return ResponseResult.okResult();}GetMapping(/{menuId})public ResponseResult getInfoById(PathVariable(menuId) Long menuId){Menu menu menuService.getById(menuId);return ResponseResult.okResult(menu);}}3.1.3 测试
点击修改按钮后回显出菜单的详情信息 3.2 修改菜单
3.2.1 修改菜单接口分析
请求方式请求路径是否需求token头PUTsystem/menu是
请求体参数
Menu类对应的json格式
响应格式
{code:200,msg:操作成功
}
如果把父菜单设置为当前菜单:
{code:500,msg:修改菜单写博文失败上级菜单不能选择自己
}
3.2.2 代码实现
第一步Controller层新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/menu)
public class MenuController {Autowiredprivate MenuService menuService;//查询菜单列表GetMapping(/list)public ResponseResult selectAllMenu(Menu menu){return menuService.selectAllMenu(menu);}//新增菜单PostMappingpublic ResponseResult add(RequestBody Menu menu) {menuService.save(menu);return ResponseResult.okResult();}GetMapping(/{menuId})public ResponseResult getInfoById(PathVariable(menuId) Long menuId){Menu menu menuService.getById(menuId);return ResponseResult.okResult(menu);}PutMappingpublic ResponseResult editMenu(RequestBody Menu menu){return menuService.editMenu(menu);}}第二步domain/entity的Menu实体类修改四个字段设置为mp自动填充
package com.keke.domain.entity;import java.util.Date;
import java.util.List;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.experimental.Accessors;/*** 菜单权限表(Menu)表实体类** author makejava* since 2023-10-18 20:55:24*/
SuppressWarnings(serial)
Data
NoArgsConstructor
AllArgsConstructor
Accessors(chain true)
TableName(sys_menu)
public class Menu {//菜单IDprivate Long id;//菜单名称private String menuName;//父菜单IDprivate Long parentId;//显示顺序private Integer orderNum;//路由地址private String path;//组件路径private String component;//是否为外链0是 1否private Integer isFrame;//菜单类型M目录 C菜单 F按钮private String menuType;//菜单状态0显示 1隐藏private String visible;//菜单状态0正常 1停用private String status;//权限标识private String perms;//菜单图标private String icon;//创建者TableField(fill FieldFill.INSERT)private Long createBy;//创建时间TableField(fill FieldFill.INSERT)private Date createTime;//更新者TableField(fill FieldFill.INSERT_UPDATE)private Long updateBy;//更新时间TableField(fill FieldFill.INSERT_UPDATE)private Date updateTime;//备注private String remark;private String delFlag;//由于数据库没有children字段所以我们要添加TableField(exist false)注解// 让mybatis在查表时不查询这个字段TableField(exist false)private ListMenu children;
}第三步service层新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;import java.util.List;/*** 菜单权限表(Menu)表服务接口** author makejava* since 2023-10-18 20:55:48*/
public interface MenuService extends IServiceMenu {//查询用户权限信息ListString selectPermsByUserId(Long userId);//查询用户的路由信息也就是权限菜单ListMenu selectRouterMenuTreeByUserId(Long userId);ResponseResult selectAllMenu(Menu menu);ResponseResult editMenu(Menu menu);}第四步impl层新增
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.constants.SystemConstants;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.domain.vo.AdminMenuVo;
import com.keke.mapper.MenuMapper;
import com.keke.service.MenuService;
import com.keke.utils.BeanCopyUtils;
import com.keke.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 菜单权限表(Menu)表服务实现类** author makejava* since 2023-10-18 20:55:48*/
Service(menuService)
public class MenuServiceImpl extends ServiceImplMenuMapper, Menu implements MenuService {Autowiredprivate MenuService menuService;//根据用户id查询权限关键字Overridepublic ListString selectPermsByUserId(Long userId) {//如果用户id为1代表管理员roles 中只需要有admin// permissions中需要有所有菜单类型为C(菜单)或者F(按钮)的状态为正常的未被删除的权限if(SecurityUtils.isAdmin()) {LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);lambdaQueryWrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);//由于我们的逻辑删除字段已经配置了所以无需封装lambdaQueryWrapperListMenu menuList list(lambdaQueryWrapper);//我们需要的是String类型的集合这里我们要进行数据的处理这里采用流的方式ListString permissions menuList.stream().map(new FunctionMenu, String() {Overridepublic String apply(Menu menu) {String perms menu.getPerms();return perms;}}).collect(Collectors.toList());return permissions;}//否则返回这个用户所具有的权限//这里我们需要进行连表查询因为我们的用户先和角色关联然后角色才跟权限关联MenuMapper menuMapper getBaseMapper();//我们期望menuMapper中有一个方法可以直接帮我们去实现这个复杂的逻辑这里直接返回return menuMapper.selectPermsByUserId(userId);}Overridepublic ListMenu selectRouterMenuTreeByUserId(Long userId) {MenuMapper menuMapper getBaseMapper();ListMenu menus null;//如果是管理员返回所有if(SecurityUtils.isAdmin()){menus menuMapper.selectAllRoutersMenu();}else {//如果不是管理员返回对应用户的菜单menus menuMapper.selectRoutersMenuTreeByUserId(userId);}//因为上面的查询都是从数据库进行查询所以无法封装children这里构建TreeListMenu menuTree buildMenuTree(menus,0L);return menuTree;}Overridepublic ResponseResult selectAllMenu(Menu menu) {//可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(menu.getMenuName()),Menu::getMenuName,menu.getMenuName());lambdaQueryWrapper.eq(StringUtils.hasText(menu.getStatus()),Menu::getStatus,menu.getStatus());//排序 parent_id和order_numlambdaQueryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum);ListMenu menus list(lambdaQueryWrapper);ListAdminMenuVo adminMenuVos BeanCopyUtils.copyBeanList(menus, AdminMenuVo.class);return ResponseResult.okResult(adminMenuVos);}Overridepublic ResponseResult editMenu(Menu menu) {if(menu.getParentId().equals(menu.getId())){return ResponseResult.okResult(500,修改菜单 menu.getMenuName() 失败上级菜单不能选择自己);}updateById(menu);return ResponseResult.okResult();}/*** 构建MenuTree* 思路先找第一层级的菜单就是找到id于parentId的对应关系然后把parentId设置为Id的children* param menus* return*/private ListMenu buildMenuTree(ListMenu menus,Long parentId) {//转化流处理ListMenu menuTree menus.stream()//过滤掉除一级菜单之外的菜单.filter(menu - menu.getParentId().equals(parentId))//然后将获取其子菜单设置到children字段并返回.map(m - m.setChildren(gerChildren(m, menus))).collect(Collectors.toList());return menuTree;}//获取当前菜单的子菜单private ListMenu gerChildren(Menu menu, ListMenu menus) {//流处理遍历每一个流对象筛选出流对象的parentIdmenu的id即过滤ListMenu children menus.stream().filter(m - m.getParentId().equals(menu.getId()))//这里其实不必要写这一步的逻辑是如果有三级//可以把流对象中再过筛选出子菜单设置给对应的children并返回.map(m - m.setChildren(gerChildren(m,menus))).collect(Collectors.toList());return children;}}3.2.3 测试 4. 删除菜单
能够删除菜单但是如果要删除的菜单有子菜单则提示存在子菜单不允许删除 并且删除失败
4.1 接口分析
请求方式请求路径是否需求token头DELETEcontent/article/{menuId}是
请求参数PathVariable参数
menuId要删除菜单的id
响应格式
{code:200,msg:操作成功
}
如果有子菜单
{code:500,msg:存在子菜单不允许删除
} 4.2 代码实现
第一步controller层新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/menu)
public class MenuController {Autowiredprivate MenuService menuService;//查询菜单列表GetMapping(/list)public ResponseResult selectAllMenu(Menu menu){return menuService.selectAllMenu(menu);}//新增菜单PostMappingpublic ResponseResult add(RequestBody Menu menu) {menuService.save(menu);return ResponseResult.okResult();}GetMapping(/{menuId})public ResponseResult getInfoById(PathVariable(menuId) Long menuId){Menu menu menuService.getById(menuId);return ResponseResult.okResult(menu);}PutMappingpublic ResponseResult editMenu(RequestBody Menu menu){return menuService.editMenu(menu);}DeleteMapping(/{menuId})public ResponseResult deleteMenu(PathVariable(menuId) Long menuId){return menuService.deleteMenu(menuId);}}第二步service层新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;import java.util.List;/*** 菜单权限表(Menu)表服务接口** author makejava* since 2023-10-18 20:55:48*/
public interface MenuService extends IServiceMenu {//查询用户权限信息ListString selectPermsByUserId(Long userId);//查询用户的路由信息也就是权限菜单ListMenu selectRouterMenuTreeByUserId(Long userId);ResponseResult selectAllMenu(Menu menu);ResponseResult editMenu(Menu menu);ResponseResult deleteMenu(Long menuId);
}第三步impl层新增
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.constants.SystemConstants;
import com.keke.domain.ResponseResult;
import com.keke.domain.entity.Menu;
import com.keke.domain.vo.AdminMenuVo;
import com.keke.mapper.MenuMapper;
import com.keke.service.MenuService;
import com.keke.utils.BeanCopyUtils;
import com.keke.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 菜单权限表(Menu)表服务实现类** author makejava* since 2023-10-18 20:55:48*/
Service(menuService)
public class MenuServiceImpl extends ServiceImplMenuMapper, Menu implements MenuService {Autowiredprivate MenuService menuService;//根据用户id查询权限关键字Overridepublic ListString selectPermsByUserId(Long userId) {//如果用户id为1代表管理员roles 中只需要有admin// permissions中需要有所有菜单类型为C(菜单)或者F(按钮)的状态为正常的未被删除的权限if(SecurityUtils.isAdmin()) {LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);lambdaQueryWrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);//由于我们的逻辑删除字段已经配置了所以无需封装lambdaQueryWrapperListMenu menuList list(lambdaQueryWrapper);//我们需要的是String类型的集合这里我们要进行数据的处理这里采用流的方式ListString permissions menuList.stream().map(new FunctionMenu, String() {Overridepublic String apply(Menu menu) {String perms menu.getPerms();return perms;}}).collect(Collectors.toList());return permissions;}//否则返回这个用户所具有的权限//这里我们需要进行连表查询因为我们的用户先和角色关联然后角色才跟权限关联MenuMapper menuMapper getBaseMapper();//我们期望menuMapper中有一个方法可以直接帮我们去实现这个复杂的逻辑这里直接返回return menuMapper.selectPermsByUserId(userId);}Overridepublic ListMenu selectRouterMenuTreeByUserId(Long userId) {MenuMapper menuMapper getBaseMapper();ListMenu menus null;//如果是管理员返回所有if(SecurityUtils.isAdmin()){menus menuMapper.selectAllRoutersMenu();}else {//如果不是管理员返回对应用户的菜单menus menuMapper.selectRoutersMenuTreeByUserId(userId);}//因为上面的查询都是从数据库进行查询所以无法封装children这里构建TreeListMenu menuTree buildMenuTree(menus,0L);return menuTree;}Overridepublic ResponseResult selectAllMenu(Menu menu) {//可以针对菜单名进行模糊查询。也可以针对菜单的状态进行查询LambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(menu.getMenuName()),Menu::getMenuName,menu.getMenuName());lambdaQueryWrapper.eq(StringUtils.hasText(menu.getStatus()),Menu::getStatus,menu.getStatus());//排序 parent_id和order_numlambdaQueryWrapper.orderByAsc(Menu::getParentId,Menu::getOrderNum);ListMenu menus list(lambdaQueryWrapper);ListAdminMenuVo adminMenuVos BeanCopyUtils.copyBeanList(menus, AdminMenuVo.class);return ResponseResult.okResult(adminMenuVos);}Overridepublic ResponseResult editMenu(Menu menu) {if(menu.getParentId().equals(menu.getId())){return ResponseResult.okResult(500,修改菜单 menu.getMenuName() 失败上级菜单不能选择自己);}updateById(menu);return ResponseResult.okResult();}Overridepublic ResponseResult deleteMenu(Long menuId) {Menu menu menuService.getById(menuId);//如果该菜单有子菜单那么就提示不能删除逻辑就是查询菜单表中是否有父菜单id是当前菜单idLambdaQueryWrapperMenu lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.eq(Menu::getParentId,menuId);ListMenu menus list(lambdaQueryWrapper);if(!menus.isEmpty()) {return ResponseResult.okResult(500, 存在子菜单不允许删除);}removeById(menuId);return ResponseResult.okResult();}/*** 构建MenuTree* 思路先找第一层级的菜单就是找到id于parentId的对应关系然后把parentId设置为Id的children* param menus* return*/private ListMenu buildMenuTree(ListMenu menus,Long parentId) {//转化流处理ListMenu menuTree menus.stream()//过滤掉除一级菜单之外的菜单.filter(menu - menu.getParentId().equals(parentId))//然后将获取其子菜单设置到children字段并返回.map(m - m.setChildren(gerChildren(m, menus))).collect(Collectors.toList());return menuTree;}//获取当前菜单的子菜单private ListMenu gerChildren(Menu menu, ListMenu menus) {//流处理遍历每一个流对象筛选出流对象的parentIdmenu的id即过滤ListMenu children menus.stream().filter(m - m.getParentId().equals(menu.getId()))//这里其实不必要写这一步的逻辑是如果有三级//可以把流对象中再过筛选出子菜单设置给对应的children并返回.map(m - m.setChildren(gerChildren(m,menus))).collect(Collectors.toList());return children;}
}4.3 测试 十二、后台模块-角色列表
1. 查询角色
需要有角色列表分页查询的功能。
要求能够针对角色名称进行模糊查询。
要求能够针对状态进行查询。
要求按照role_sort进行升序排列。
1.1 接口分析
请求方式请求路径是否需求token头GETsystem/role/list是
Query格式请求参数
pageNum: 页码pageSize: 每页条数roleName角色名称status状态 响应格式
{code:200,data:{rows:[{id:12,roleKey:link,roleName:友链审核员,roleSort:1,status:0}],total:1},msg:操作成功
}
1.2 代码实现
第一步新建RoleController新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}
}第二步service层新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;import java.util.List;/*** 角色信息表(Role)表服务接口** author makejava* since 2023-10-18 21:04:06*/
public interface RoleService extends IServiceRole {ListString selectRoleKeyByUserId(Long userId);ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize);
}第三步impl层新增
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.domain.vo.PageVo;
import com.keke.mapper.RoleMapper;
import com.keke.service.RoleService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;/*** 角色信息表(Role)表服务实现类** author makejava* since 2023-10-18 21:04:06*/
Service(roleService)
public class RoleServiceImpl extends ServiceImplRoleMapper, Role implements RoleService {//根据用户id查询角色信息Overridepublic ListString selectRoleKeyByUserId(Long userId) {//如果userId为1那么角色权限字符串就只需要返回一个adminif(userId1L){ListString roles new ArrayList();roles.add(admin);return roles;}//如果用户id不为1那么需要根据userId连表查询对应的roleId然后再去角色表中去查询//对应的角色权限字符串//这里我们期望RoleMapper中封装一个方法去帮我们实现这个复杂的操作RoleMapper roleMapper getBaseMapper();return roleMapper.selectRoleKeyByUserId(userId);}Overridepublic ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize) {LambdaQueryWrapperRole lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName());lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus());lambdaQueryWrapper.orderByAsc(Role::getRoleSort);PageRole page new Page(pageNum,pageSize);page(page,lambdaQueryWrapper);PageVo pageVo new PageVo(page.getRecords(),page.getTotal());return ResponseResult.okResult(pageVo);}
}1.3 测试 2. 改变角色状态
要求能够修改角色的停启用状态
2.1 接口分析
请求方式请求路径是否需求token头PUTsystem/role/changeStatus是
请求体
{roleId:11,status:1
}
响应格式
{code:200,msg:操作成功
}
2.2 代码实现
第一步controller层新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}PutMapping(/changeStatus)public ResponseResult changeRoleStatus(RequestBody ChangeRoleStatusDto changeRoleStatusDto){return roleService.changeRoleStatus(changeRoleStatusDto);}
}第二步domain/dto新增
package com.keke.domain.dto;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;Data
AllArgsConstructor
NoArgsConstructor
public class ChangeRoleStatusDto {private Long roleId;//角色状态0正常 1停用private String status;}第三步service层新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;import java.util.List;/*** 角色信息表(Role)表服务接口** author makejava* since 2023-10-18 21:04:06*/
public interface RoleService extends IServiceRole {ListString selectRoleKeyByUserId(Long userId);ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize);ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto);
}第四步impl层新增
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.domain.vo.PageVo;
import com.keke.mapper.RoleMapper;
import com.keke.service.RoleService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;/*** 角色信息表(Role)表服务实现类** author makejava* since 2023-10-18 21:04:06*/
Service(roleService)
public class RoleServiceImpl extends ServiceImplRoleMapper, Role implements RoleService {//根据用户id查询角色信息Overridepublic ListString selectRoleKeyByUserId(Long userId) {//如果userId为1那么角色权限字符串就只需要返回一个adminif(userId1L){ListString roles new ArrayList();roles.add(admin);return roles;}//如果用户id不为1那么需要根据userId连表查询对应的roleId然后再去角色表中去查询//对应的角色权限字符串//这里我们期望RoleMapper中封装一个方法去帮我们实现这个复杂的操作RoleMapper roleMapper getBaseMapper();return roleMapper.selectRoleKeyByUserId(userId);}Overridepublic ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize) {LambdaQueryWrapperRole lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName());lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus());lambdaQueryWrapper.orderByAsc(Role::getRoleSort);PageRole page new Page(pageNum,pageSize);page(page,lambdaQueryWrapper);PageVo pageVo new PageVo(page.getRecords(),page.getTotal());return ResponseResult.okResult(pageVo);}Overridepublic ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto) {Long roleId changeRoleStatusDto.getRoleId();Role role getById(roleId);role.setStatus(changeRoleStatusDto.getStatus());updateById(role);return ResponseResult.okResult();}
}2.3 测试
把该用户启用 数据库中状态正常
3. 新增角色
需要提供新增角色的功能。新增角色时能够直接设置角色所关联的菜单权限
首先应该获取权限菜单数勾选然后才能新增
分析下来有两个接口需要实现
3.1 获取菜单权限树接口
3.1.1 接口分析
请求方式请求路径是否需求token头GET/system/menu/treeselect是
无需请求参数
响应格式
{code:200,data:[{children:[],id:2023,label:写博文,parentId:0},{children:[{children:[{children:[],id:1001,label:用户查询,parentId:100},{children:[],id:1007,label:重置密码,parentId:100}],id:100,label:用户管理,parentId:1},{children:[{children:[],id:2024,label:友链新增,parentId:2022},{children:[],id:2025,label:友链修改,parentId:2022},{children:[],id:2026,label:友链删除,parentId:2022},{children:[],id:2027,label:友链查询,parentId:2022}],id:2022,label:友链管理,parentId:2017},{children:[],id:2021,label:标签管理,parentId:2017}],id:2017,label:内容管理,parentId:0}],msg:操作成功
}
3.1.2 代码实现 3.1.3 测试 3.2 新增角色接口
3.2.1 接口分析
请求方式请求路径是否需求token头POSTsystem/role是
请求体
{roleName:测试新增角色,roleKey:wds,roleSort:0,status:0,menuIds:[1,100],remark:我是角色备注
}
响应格式
{code:200,msg:操作成功
}
3.2.2 代码实现
第一步domain/dto层新增
package com.keke.domain.dto;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;
import java.util.List;Data
AllArgsConstructor
NoArgsConstructor
public class AdminAddRoleDto {//角色名称private String roleName;//角色权限字符串private String roleKey;//显示顺序private Integer roleSort;//角色状态0正常 1停用private String status;//备注private String remark;//关联的menuIdListLong menuIds;
}第二步domain/entity层新增
package com.keke.domain.entity;import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;/*** 角色和菜单关联表(RoleMenu)表实体类** author makejava* since 2023-10-23 17:00:27*/
SuppressWarnings(serial)
Data
NoArgsConstructor
AllArgsConstructor
TableName(sys_role_menu)
public class RoleMenu {//角色IDprivate Long roleId;//菜单IDprivate Long menuId;}第三步mapper层新增RoleMenuMapper
package com.keke.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keke.domain.entity.RoleMenu;/*** 角色和菜单关联表(RoleMenu)表数据库访问层** author makejava* since 2023-10-23 17:01:09*/
public interface RoleMenuMapper extends BaseMapperRoleMenu {}第四步service新增RoleMenuService
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.entity.RoleMenu;/*** 角色和菜单关联表(RoleMenu)表服务接口** author makejava* since 2023-10-23 17:01:09*/
public interface RoleMenuService extends IServiceRoleMenu {}第五步impl层新增RoleMenuServiceImpl
package com.keke.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.entity.RoleMenu;
import com.keke.mapper.RoleMenuMapper;
import com.keke.service.RoleMenuService;
import org.springframework.stereotype.Service;/*** 角色和菜单关联表(RoleMenu)表服务实现类** author makejava* since 2023-10-23 17:01:09*/
Service(roleMenuService)
public class RoleMenuServiceImpl extends ServiceImplRoleMenuMapper, RoleMenu implements RoleMenuService {}第六步controller的RoleController新增
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}PutMapping(/changeStatus)public ResponseResult changeRoleStatus(RequestBody ChangeRoleStatusDto changeRoleStatusDto){return roleService.changeRoleStatus(changeRoleStatusDto);}PostMappingpublic ResponseResult addRole(RequestBody AdminAddRoleDto adminAddRoleDto){return roleService.addRole(adminAddRoleDto);}}第七步service层的RoleService新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;import java.util.List;/*** 角色信息表(Role)表服务接口** author makejava* since 2023-10-18 21:04:06*/
public interface RoleService extends IServiceRole {ListString selectRoleKeyByUserId(Long userId);ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize);ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto);ResponseResult addRole(AdminAddRoleDto adminAddRoleDto);}第八步impl层的RoleServiceImpl新增记得方法加上Transactional注解
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.domain.entity.RoleMenu;
import com.keke.domain.vo.PageVo;
import com.keke.mapper.RoleMapper;
import com.keke.service.RoleMenuService;
import com.keke.service.RoleService;
import com.keke.utils.BeanCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 角色信息表(Role)表服务实现类** author makejava* since 2023-10-18 21:04:06*/
Service(roleService)
public class RoleServiceImpl extends ServiceImplRoleMapper, Role implements RoleService {Autowiredprivate RoleMenuService roleMenuService;//根据用户id查询角色信息Overridepublic ListString selectRoleKeyByUserId(Long userId) {//如果userId为1那么角色权限字符串就只需要返回一个adminif(userId1L){ListString roles new ArrayList();roles.add(admin);return roles;}//如果用户id不为1那么需要根据userId连表查询对应的roleId然后再去角色表中去查询//对应的角色权限字符串//这里我们期望RoleMapper中封装一个方法去帮我们实现这个复杂的操作RoleMapper roleMapper getBaseMapper();return roleMapper.selectRoleKeyByUserId(userId);}Overridepublic ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize) {LambdaQueryWrapperRole lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName());lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus());lambdaQueryWrapper.orderByAsc(Role::getRoleSort);PageRole page new Page(pageNum,pageSize);page(page,lambdaQueryWrapper);PageVo pageVo new PageVo(page.getRecords(),page.getTotal());return ResponseResult.okResult(pageVo);}Overridepublic ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto) {Long roleId changeRoleStatusDto.getRoleId();Role role getById(roleId);role.setStatus(changeRoleStatusDto.getStatus());updateById(role);return ResponseResult.okResult();}TransactionalOverridepublic ResponseResult addRole(AdminAddRoleDto adminAddRoleDto) {//Bean拷贝Role role BeanCopyUtils.copyBean(adminAddRoleDto, Role.class);//拿到菜单权限id集合ListLong menuIds adminAddRoleDto.getMenuIds();//流式处理转化把每一个menuId都设置到该roleId下ListRoleMenu roleMenuList menuIds.stream().map(new FunctionLong, RoleMenu() {Overridepublic RoleMenu apply(Long menuId) {RoleMenu roleMenu new RoleMenu();roleMenu.setRoleId(role.getId());roleMenu.setMenuId(menuId);return roleMenu;}}).collect(Collectors.toList());//mp批量保存到数据库中roleMenuService.saveBatch(roleMenuList);//封装返回return ResponseResult.okResult();}
}第九步domain/entity的Role实体类修改四个字段为mp自动填充
package com.keke.domain.entity;import java.util.Date;
import java.io.Serializable;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.baomidou.mybatisplus.annotation.TableName;/*** 角色信息表(Role)表实体类** author makejava* since 2023-10-18 21:03:52*/
SuppressWarnings(serial)
Data
NoArgsConstructor
AllArgsConstructor
TableName(sys_role)
public class Role {//角色IDprivate Long id;//角色名称private String roleName;//角色权限字符串private String roleKey;//显示顺序private Integer roleSort;//角色状态0正常 1停用private String status;//删除标志0代表存在 1代表删除private String delFlag;//创建者TableField(fill FieldFill.INSERT)private Long createBy;//创建时间TableField(fill FieldFill.INSERT)private Date createTime;//更新者TableField(fill FieldFill.INSERT_UPDATE)private Long updateBy;//更新时间TableField(fill FieldFill.INSERT_UPDATE)private Date updateTime;//备注private String remark;
}3.2.3 测试 4. 修改角色
需要提供修改角色的功能。修改角色时可以修改角色所关联的菜单权限
这里可以分析到修改角色有三个接口一个点击是修改角色后角色信息的回显接口回显中有一个菜单权限树接口另一个是修改角色的接口
4.1 角色信息回显接口
4.1.1接口分析
请求路径请求方式是否需求token头system/role/{id}Get是
请求参数PathVariable格式
id: 角色id
响应格式
{code:200,data:{id:11,remark:嘎嘎嘎,roleKey:aggag,roleName:嘎嘎嘎,roleSort:5,status:0},msg:操作成功
}
4.1.2 代码实现
第一步controller层
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}PutMapping(/changeStatus)public ResponseResult changeRoleStatus(RequestBody ChangeRoleStatusDto changeRoleStatusDto){return roleService.changeRoleStatus(changeRoleStatusDto);}PostMappingpublic ResponseResult addRole(RequestBody AdminAddRoleDto adminAddRoleDto){return roleService.addRole(adminAddRoleDto);}GetMapping(/{id})public ResponseResult getRoleInfo(PathVariable(id) Long id){return roleService.getRoleInfo(id);}
}第二步domain/vo层新增
package com.keke.domain.vo;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;Data
AllArgsConstructor
NoArgsConstructor
public class AdminRoleVo {//角色IDprivate Long id;//角色名称private String roleName;//角色权限字符串private String roleKey;//显示顺序private Integer roleSort;//角色状态0正常 1停用private String status;//备注private String remark;
}第三步service层
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;import java.util.List;/*** 角色信息表(Role)表服务接口** author makejava* since 2023-10-18 21:04:06*/
public interface RoleService extends IServiceRole {ListString selectRoleKeyByUserId(Long userId);ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize);ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto);ResponseResult addRole(AdminAddRoleDto adminAddRoleDto);ResponseResult getRoleInfo(Long id);
}第四步impl层新增
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.entity.Role;
import com.keke.domain.entity.RoleMenu;
import com.keke.domain.vo.AdminRoleVo;
import com.keke.domain.vo.PageVo;
import com.keke.mapper.RoleMapper;
import com.keke.service.RoleMenuService;
import com.keke.service.RoleService;
import com.keke.utils.BeanCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 角色信息表(Role)表服务实现类** author makejava* since 2023-10-18 21:04:06*/
Service(roleService)
public class RoleServiceImpl extends ServiceImplRoleMapper, Role implements RoleService {Autowiredprivate RoleMenuService roleMenuService;//根据用户id查询角色信息Overridepublic ListString selectRoleKeyByUserId(Long userId) {//如果userId为1那么角色权限字符串就只需要返回一个adminif(userId1L){ListString roles new ArrayList();roles.add(admin);return roles;}//如果用户id不为1那么需要根据userId连表查询对应的roleId然后再去角色表中去查询//对应的角色权限字符串//这里我们期望RoleMapper中封装一个方法去帮我们实现这个复杂的操作RoleMapper roleMapper getBaseMapper();return roleMapper.selectRoleKeyByUserId(userId);}Overridepublic ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize) {LambdaQueryWrapperRole lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName());lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus());lambdaQueryWrapper.orderByAsc(Role::getRoleSort);PageRole page new Page(pageNum,pageSize);page(page,lambdaQueryWrapper);PageVo pageVo new PageVo(page.getRecords(),page.getTotal());return ResponseResult.okResult(pageVo);}Overridepublic ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto) {Long roleId changeRoleStatusDto.getRoleId();Role role getById(roleId);role.setStatus(changeRoleStatusDto.getStatus());updateById(role);return ResponseResult.okResult();}TransactionalOverridepublic ResponseResult addRole(AdminAddRoleDto adminAddRoleDto) {//Bean拷贝Role role BeanCopyUtils.copyBean(adminAddRoleDto, Role.class);//拿到菜单权限id集合ListLong menuIds adminAddRoleDto.getMenuIds();//流式处理转化把每一个menuId都设置到该roleId下ListRoleMenu roleMenuList menuIds.stream().map(new FunctionLong, RoleMenu() {Overridepublic RoleMenu apply(Long menuId) {RoleMenu roleMenu new RoleMenu();roleMenu.setRoleId(role.getId());roleMenu.setMenuId(menuId);return roleMenu;}}).collect(Collectors.toList());//mp批量保存到数据库中roleMenuService.saveBatch(roleMenuList);//封装返回return ResponseResult.okResult();}Overridepublic ResponseResult getRoleInfo(Long id) {Role role getById(id);AdminRoleVo adminRoleVo BeanCopyUtils.copyBean(role, AdminRoleVo.class);return ResponseResult.okResult(adminRoleVo);}
}4.1.3 测试
回显成功 4.2 菜单权限树接口
4.2.1 接口分析
请求方式请求路径是否需求token头Get/system/menu/roleMenuTreeselect/{id}是
请求参数PathVariable格式
id: 角色id
响应格式 字段介绍 menus菜单树 checkedKeys角色所关联的菜单权限id列表 {code:200,data:{menus:[{children:[],id:2023,label:写博文,parentId:0},{children:[{children:[{children:[],id:1001,label:用户查询,parentId:100},{children:[],id:1002,label:用户新增,parentId:100},{children:[],id:1003,label:用户修改,parentId:100},{children:[],id:1004,label:用户删除,parentId:100},{children:[],id:1005,label:用户导出,parentId:100},{children:[],id:1006,label:用户导入,parentId:100},{children:[],id:1007,label:重置密码,parentId:100}],id:100,label:用户管理,parentId:1},{children:[{children:[],id:1008,label:角色查询,parentId:101},{children:[],id:1009,label:角色新增,parentId:101},{children:[],id:1010,label:角色修改,parentId:101},{children:[],id:1011,label:角色删除,parentId:101},{children:[],id:1012,label:角色导出,parentId:101}],id:101,label:角色管理,parentId:1},{children:[{children:[],id:1013,label:菜单查询,parentId:102},{children:[],id:1014,label:菜单新增,parentId:102},{children:[],id:1015,label:菜单修改,parentId:102},{children:[],id:1016,label:菜单删除,parentId:102}],id:102,label:菜单管理,parentId:1}],id:1,label:系统管理,parentId:0},{children:[{children:[],id:2019,label:文章管理,parentId:2017},{children:[{children:[],id:2028,label:导出分类,parentId:2018}],id:2018,label:分类管理,parentId:2017},{children:[{children:[],id:2024,label:友链新增,parentId:2022},{children:[],id:2025,label:友链修改,parentId:2022},{children:[],id:2026,label:友链删除,parentId:2022},{children:[],id:2027,label:友链查询,parentId:2022}],id:2022,label:友链管理,parentId:2017},{children:[],id:2021,label:标签管理,parentId:2017}],id:2017,label:内容管理,parentId:0}],checkedKeys:[1001 ]},msg:操作成功
}
4.2.2 代码实现待实现
4.2.3 测试待实现
4.3 修改角色接口
4.3.1 接口分析
请求方式请求路径是否需求token头PUTsystem/role是
请求体
{id:13,remark:我是角色备注,roleKey:wds,roleName:测试新增角色,roleSort:0,status:0,menuIds:[1,100,1001]
}
响应体
{code:200,msg:操作成功
}
4.3.2 代码实现
第一步domain/dto层新增
package com.keke.domain.dto;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;
import java.util.List;Data
AllArgsConstructor
NoArgsConstructor
public class EditRoleDto {//角色IDprivate Long id;//角色名称private String roleName;//角色权限字符串private String roleKey;//显示顺序private Integer roleSort;//角色状态0正常 1停用private String status;//备注private String remark;//权限idprivate ListLong menuIds;
}第二步controller层新增EditRole接口
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.dto.EditRoleDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}PutMapping(/changeStatus)public ResponseResult changeRoleStatus(RequestBody ChangeRoleStatusDto changeRoleStatusDto){return roleService.changeRoleStatus(changeRoleStatusDto);}PostMappingpublic ResponseResult addRole(RequestBody AdminAddRoleDto adminAddRoleDto){return roleService.addRole(adminAddRoleDto);}GetMapping(/{id})public ResponseResult getRoleInfo(PathVariable(id) Long id){return roleService.getRoleInfo(id);}PutMappingpublic ResponseResult editRole(RequestBody EditRoleDto editRoleDto){return roleService.editRole(editRoleDto);}
}第二步service新增
package com.keke.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.dto.EditRoleDto;
import com.keke.domain.entity.Role;import java.util.List;/*** 角色信息表(Role)表服务接口** author makejava* since 2023-10-18 21:04:06*/
public interface RoleService extends IServiceRole {ListString selectRoleKeyByUserId(Long userId);ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize);ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto);ResponseResult addRole(AdminAddRoleDto adminAddRoleDto);ResponseResult getRoleInfo(Long id);ResponseResult editRole(EditRoleDto editRoleDto);
}第三步impl新增逻辑和添加用户一样
package com.keke.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.dto.EditRoleDto;
import com.keke.domain.entity.Role;
import com.keke.domain.entity.RoleMenu;
import com.keke.domain.vo.AdminRoleVo;
import com.keke.domain.vo.PageVo;
import com.keke.mapper.RoleMapper;
import com.keke.service.RoleMenuService;
import com.keke.service.RoleService;
import com.keke.utils.BeanCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** 角色信息表(Role)表服务实现类** author makejava* since 2023-10-18 21:04:06*/
Service(roleService)
public class RoleServiceImpl extends ServiceImplRoleMapper, Role implements RoleService {Autowiredprivate RoleMenuService roleMenuService;//根据用户id查询角色信息Overridepublic ListString selectRoleKeyByUserId(Long userId) {//如果userId为1那么角色权限字符串就只需要返回一个adminif(userId1L){ListString roles new ArrayList();roles.add(admin);return roles;}//如果用户id不为1那么需要根据userId连表查询对应的roleId然后再去角色表中去查询//对应的角色权限字符串//这里我们期望RoleMapper中封装一个方法去帮我们实现这个复杂的操作RoleMapper roleMapper getBaseMapper();return roleMapper.selectRoleKeyByUserId(userId);}Overridepublic ResponseResult selectPageRole(Role role, Integer pageNum, Integer pageSize) {LambdaQueryWrapperRole lambdaQueryWrapper new LambdaQueryWrapper();lambdaQueryWrapper.like(StringUtils.hasText(role.getRoleName()),Role::getRoleName,role.getRoleName());lambdaQueryWrapper.eq(StringUtils.hasText(role.getStatus()),Role::getStatus,role.getStatus());lambdaQueryWrapper.orderByAsc(Role::getRoleSort);PageRole page new Page(pageNum,pageSize);page(page,lambdaQueryWrapper);PageVo pageVo new PageVo(page.getRecords(),page.getTotal());return ResponseResult.okResult(pageVo);}Overridepublic ResponseResult changeRoleStatus(ChangeRoleStatusDto changeRoleStatusDto) {Long roleId changeRoleStatusDto.getRoleId();Role role getById(roleId);role.setStatus(changeRoleStatusDto.getStatus());updateById(role);return ResponseResult.okResult();}TransactionalOverridepublic ResponseResult addRole(AdminAddRoleDto adminAddRoleDto) {//Bean拷贝Role role BeanCopyUtils.copyBean(adminAddRoleDto, Role.class);//拿到菜单权限id集合ListLong menuIds adminAddRoleDto.getMenuIds();//流式处理转化把每一个menuId都设置到该roleId下ListRoleMenu roleMenuList menuIds.stream().map(new FunctionLong, RoleMenu() {Overridepublic RoleMenu apply(Long menuId) {RoleMenu roleMenu new RoleMenu();roleMenu.setRoleId(role.getId());roleMenu.setMenuId(menuId);return roleMenu;}}).collect(Collectors.toList());//mp批量保存到数据库中roleMenuService.saveBatch(roleMenuList);//封装返回return ResponseResult.okResult();}Overridepublic ResponseResult getRoleInfo(Long id) {Role role getById(id);AdminRoleVo adminRoleVo BeanCopyUtils.copyBean(role, AdminRoleVo.class);return ResponseResult.okResult(adminRoleVo);}Overridepublic ResponseResult editRole(EditRoleDto editRoleDto) {Role role BeanCopyUtils.copyBean(editRoleDto, Role.class);ListLong menuIds editRoleDto.getMenuIds();ListRoleMenu roleMenuList menuIds.stream().map(new FunctionLong, RoleMenu() {Overridepublic RoleMenu apply(Long menuId) {RoleMenu roleMenu new RoleMenu();roleMenu.setRoleId(role.getId());roleMenu.setMenuId(menuId);return roleMenu;}}).collect(Collectors.toList());roleMenuService.saveBatch(roleMenuList);return ResponseResult.okResult();}
}4.3.3 测试待实现 5. 删除角色
删除固定的某个角色逻辑删除
5.1 接口分析
请求方式请求路径是否需求token头DELETEsystem/role/{id}是
请求参数PathVariable格式
id要删除的角色id 响应格式
{code:200,msg:操作成功
}
5.2 代码实现
controller层新增接口逻辑较少直接写
package com.keke.controller;import com.keke.domain.ResponseResult;
import com.keke.domain.dto.AdminAddRoleDto;
import com.keke.domain.dto.ChangeRoleStatusDto;
import com.keke.domain.dto.EditRoleDto;
import com.keke.domain.entity.Role;
import com.keke.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;RestController
RequestMapping(/system/role)
public class RoleController {Autowiredprivate RoleService roleService;GetMapping(/list)public ResponseResult selectPageRole(Role role,Integer pageNum,Integer pageSize){return roleService.selectPageRole(role,pageNum,pageSize);}PutMapping(/changeStatus)public ResponseResult changeRoleStatus(RequestBody ChangeRoleStatusDto changeRoleStatusDto){return roleService.changeRoleStatus(changeRoleStatusDto);}PostMappingpublic ResponseResult addRole(RequestBody AdminAddRoleDto adminAddRoleDto){return roleService.addRole(adminAddRoleDto);}GetMapping(/{id})public ResponseResult getRoleInfo(PathVariable(id) Long id){return roleService.getRoleInfo(id);}PutMappingpublic ResponseResult editRole(RequestBody EditRoleDto editRoleDto){return roleService.editRole(editRoleDto);}DeleteMapping(/{id})public ResponseResult deleteRoleById(PathVariable(id) Long id){roleService.removeById(id);return ResponseResult.okResult();}
}5.3 测试 只是逻辑删除