栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【爆肝推荐】手摸手带你做后台管理项目(第五章)动态目录和knife4j整合

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【爆肝推荐】手摸手带你做后台管理项目(第五章)动态目录和knife4j整合

前情提要

上一篇弄好了菜单和角色, 剩余用户和角色关联还没做, 动态菜单还没做, html按钮控制也没做, 这篇都弄完, 然后knife4j也整合进去, 上一篇太长了,
所以都留在这一篇完成了

直接进入主题,开整 SysUserEntity增加非表字段roles
 	//多个角色id,非表字段
    @TableField(exist = false)
    private List roles;
改造sysUserController

改动处加了注释,增删改查四个接口都动过

import com.macro.Vo.UserParam;
import com.macro.entity.UserEntity;
import com.macro.service.UserService;
import com.macro.utils.Result;
import com.macro.utils.shiro.ShiroUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("sysUser")
public class sysUserController {
    @Autowired
    private UserService userService;

    @GetMapping("list")
    public Result list(UserParam param){
        Result result = userService.findByParam(param);
        return result;
    }

    @PostMapping("add")
    public Result add(@RequestBody UserEntity user){
        //密码加密
        user.setPassword(ShiroUtils.getMdPassWord(user.getPassword()));
        //改动
        boolean save = userService.insert(user);
        if(save){
            return Result.success();
        }
        return Result.error("添加失败");
    }

    //只添加了@RequiresPermissions("sys:user:info")
    @RequiresPermissions("sys:user:info")
    @GetMapping("info/{id}")
    public Result info(@PathVariable("id") Integer id){
        //改动
        UserEntity userEntity = userService.findById(id);
        return Result.success(userEntity);
    }


    @PostMapping("update")
    public Result update(@RequestBody UserEntity user){
        user.setPassword(ShiroUtils.getMdPassWord(user.getPassword()));
        //改动
        boolean type = userService.updateData(user);
        return type ? Result.success() : Result.error("更新失败");
    }

    @PostMapping("del")
    public Result del(@RequestBody String[] ids){
        if(ids.length > 0){
            //改动
            boolean type = userService.delIds(ids);
            return type ? Result.success() : Result.error("删除失败");
        }
        return  Result.success();
    }


    @GetMapping("setting")
    public Result setting(){
        //直接通过ShiroUtils.getUserId()获取用户id
        UserEntity userEntity = userService.getById(ShiroUtils.getUserId());
        return Result.success(userEntity);
    }
}
UserService
import com.baomidou.mybatisplus.extension.service.IService;
import com.macro.Vo.UserParam;
import com.macro.entity.UserEntity;
import com.macro.utils.Result;

public interface UserService extends IService {
    UserEntity findByUserName(String username);

    Result findByParam(UserParam param);

    boolean insert(UserEntity user);

    UserEntity findById(Integer id);

    boolean updateData(UserEntity user);

    boolean delIds(String[] ids);
}

UserServiceImpl
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.macro.Vo.UserParam;
import com.macro.dao.UserDao;
import com.macro.entity.SysUserRoleEntity;
import com.macro.entity.UserEntity;
import com.macro.service.SysUserRoleService;
import com.macro.service.UserService;
import com.macro.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private SysUserRoleService userRoleService;

    @Override
    public UserEntity findByUserName(String username) {
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("username",username);
        return userDao.selectOne(wrapper);
    }

    //新增
    @Override
    public Result findByParam(UserParam param) {
        PageHelper.startPage(param.getPage(), param.getLimit());
        List list = userDao.findByParam(param);
        PageInfo pageInfo = new PageInfo<>(list);
        return Result.success(0,pageInfo.getTotal(),list);
    }

    //新增
    @Override
    public boolean insert(UserEntity user) {
        int insert = userDao.insert(user);
        if(insert > 0){
            List roles = user.getRoles();
            if(roles != null && roles.size() > 0){
                for (int i = 0; i < roles.size(); i++) {
                    SysUserRoleEntity entity  = new SysUserRoleEntity();
                    entity.setRoleId(roles.get(i));
                    entity.setUserId(user.getId());
                    userRoleService.save(entity);
                }
            }
        }
        return insert>0?true:false;
    }
    //新增
    @Override
    public UserEntity findById(Integer id) {
        UserEntity user = userDao.selectById(id);
        if(user!= null){
            List roleList = userRoleService.list(new QueryWrapper().eq("user_id",id));
            user.setRoles(roleList.stream().map(SysUserRoleEntity::getRoleId).collect(Collectors.toList()));
        }
        return user;
    }
    //新增
    @Override
    public boolean updateData(UserEntity user) {
        List roles = user.getRoles();
        List roleList = userRoleService.list(new QueryWrapper().eq("user_id",user.getId()));
        List list = roleList.stream().map(SysUserRoleEntity::getRoleId).collect(Collectors.toList());
        //新的id如果没在旧的中查询出来,则是新增的
        for (int i = 0; i < roles.size(); i++) {
            if(!list.contains(roles.get(i))){
                SysUserRoleEntity entity = new SysUserRoleEntity();
                entity.setUserId(user.getId());
                entity.setRoleId(roles.get(i));
                userRoleService.save(entity);
            }
        }
        //旧的没有在新的里面查出来,则是要删除的
        for (int i = 0; i < roleList.size(); i++) {
            if(!roles.contains(roleList.get(i).getRoleId())){
                userRoleService.removeById(roleList.get(i).getId());
            }
        }
        int i = userDao.updateById(user);
        return i >0?true:false;
    }
    //新增
    @Override
    public boolean delIds(String[] ids) {
        for (int i = 0; i < ids.length; i++) {
            List list = userRoleService.list(new QueryWrapper().eq("user_id", ids[i]));
            List userRoleIds = list.stream().map(SysUserRoleEntity::getId).collect(Collectors.toList());
            userRoleService.removeByIds(userRoleIds);
            userDao.deleteById(ids[i]);
        }
        return true;
    }
}

sysUser.html改动

性别下方增加角色多选下拉框

sysUser.js

data中增加roleList :[] mounted中调用this.initRoles();

 //新增初始化请求
        initRoles(){
            axios({
                url:"role/roleList",
                method: "get"
            }).then(res =>{
                if(res.data.code == 200){
                    vm.roleList = res.data.data;
                }
            });
        },

SysRoleController 新增roleList
    //初始化获取所有角色
    @GetMapping("roleList")
    public Result roleList(){
        List list = roleService.list();
        return Result.success(list);
    }

运行之后是没什么问题的

动态目录

删除掉index.html中的这一块,并且给ul增加 id="menu", 目录和菜单都在js中完成
js部分增加menuList,并将menuList方法在mounted中调用
menuList中有两个for 第一层的for为目录,第二层为菜单,菜单可以点击,所以增加jump方法,像上面那种图设置跳转地址会跳出iframe所以自定义了一个jump方法,也算一个坑,最下方加入了一个layui的重新渲染

menuList代码
menuList() {
                //手动赋值,vue与layui不兼容
                axios({
                    url: "menu/user/list",
                    methods: "get"
                }).then(res => {
                    let list = res.data.data;
                    if (list != null && list.length > 0) {
                        let li = "";
                        for (let i = 0; i < list.length; i++) {
                            let menu = "
  • " + " "+list[i].name+"
    "; if(list[i].childList != null && list[i].childList.length){ for (let j = 0; j +list[i].childList[j].path + "','"+list[i].childList[j].name+"')"+" >"+ " "+list[i].childList[j].name+" " } } menu = menu + "
  • "; li = li + menu; } $("#menu").html(li); } //重新渲染 layui.use('element', function() { var element = layui.element; element.init(); }); }); },
    jump
    //页面跳转,重新修改跳转方式
        function jump(href,name){
            vm.val =name;
            vm.main = href;
        }
    
    SysMenuController

    编写menu/user/list接口

        //目录菜单
        @GetMapping("user/list")
        public Result userList(){
            List list = menuService.findListByUserId(ShiroUtils.getUserId());
            return Result.success(list);
        }
    
    SysMenuService
    List findListByUserId(Integer userId);
    
    SysMenuServiceImpl
     @Override
        public List findListByUserId(Integer userId) {
            List menuList = this.findByUserId(userId);
            List hierarchyList = getHierarchyList(menuList);
            return hierarchyList;
        }
    

    修改一下sys_menu中path数据和icon数据

    运行效果,修改了一下角色关联的目录,也是ok的

    整体结束

    看似结束了,基本算是做完了,还有一个按钮控制没做,这块推翻了我很多想法,比如yml配置中设置了非强制的跳转,
    但是也造成了一个坑,也就是html中shiro控制按钮,如果不从controller跳转过去,则无法生效,因为引入的一个jar包名称就叫做thymeleaf-extras-shiro,所以yml那个配置得注释掉,还得设置各种跳转的代码

    将IndexController改为PathController

    PathController全部代码

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class PathController {
    
        @GetMapping(value = {"index","","/"})
        public String index(){
            return "index";
        }
    
        @GetMapping(value = {"user"})
        public String user(){
            return "sysUser";
        }
    
        @GetMapping(value = {"info"})
        public String info(){
            return "info";
        }
    
        @GetMapping(value = {"main"})
        public String main(){
            return "main";
        }
    
        @GetMapping(value = {"role"})
        public String role(){
            return "sysRole";
        }
    
        @GetMapping(value = {"menu"})
        public String menu(){
            return "sysMenu";
        }
    
    }
    

    数据库sys_menu 修改path

    index.html

    main直接对应controller的main接口

    运行看一下效果,没什么问题

    thymeleaf整合shiro标签

    pom.xml增加依赖

    		
    		2.0.0
    		
            
                com.github.theborakompanioni
                thymeleaf-extras-shiro
                ${thymeleaf-shiro}
            
    
    ShiroConfig中增加shiroDialect

    加入这个方法便能在html中使用shiro的按钮控制了,当前角色控制也是可以,只是使用的东西不一样

        @Bean(name = "shiroDialect")
        public ShiroDialect shiroDialect() {
            return new ShiroDialect();
        }
    
    sysUser.html为增删改查按钮添加控制

    shiro:hasPermission="sys:user:save"控制权限的(Permission) 如果是Role就是角色了,别写错了

     
                    
                    
    

    LoginController修改退出

    退出之后清除掉登陆人的一些缓存信息,进入时重新加载数据,保存缓存的一致

      @GetMapping("logout")
        public String logout(){
             //清理缓存,并且跳转到登陆页面
            SecurityUtils.getSubject().logout();
            return "login";
        }
    

    测试一下,修改了角色权限,需要重新登陆才会生效,全部完成了

    项目完结

    项目基本结束了,权限校验只是拿出来部分做演示,没有全部去写,无论是controller的注解还是html的标签,都只是写了一部分,还有一些特别的点没做,比如事务,权限更新之后刷新redis内部的权限缓存,这两点都没去做,当然还有layui下次就直接用Elemenet UI不会用Layui 毕竟和vue用还是有好多不舒服的地方,比如还需要手动设置刷新,下拉控件、redio使用vue无效、毕竟两个东西走的方向不太一样,所以下次直接使用element ui 或者iview ui
    项目结束了,剩下就是整合knife4j生成好看的接口文档了,还有上传linux直接线上访问

    整合knife4j

    pim.xml添加knife4j的jar

    2.0.2
     
       com.github.xiaoymin
       knife4j-spring-boot-starter
       ${knife4j-version}
    
    
    添加配置

    config文件夹下添加Swagger2Config

    import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.documentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    @EnableKnife4j
    public class Swagger2Config {
    
        @Bean(value = "indexApi")
        public Docket indexApi() {
            return  new Docket(documentationType.SWAGGER_2)
                    .useDefaultResponseMessages(false)
                    .apiInfo(apiInfo())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.macro.controller"))
                    .paths(PathSelectors.any())
                    .build();
    
        }
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("后台项目管理")
                    .description("无术同学")
                    .version("1.0")
                    .build();
        }
    }
    

    原本想在getShiroFilterFactoryBean中放行swagger直接在外部访问的,想想算了,不安全

    sysUserController修改

    添加如下几个注解

    修改UserParam
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    //继承PageEntity
    @Data
    //swagger的注解
    @ApiModel(value = "用户参数")
    public class UserParam extends PageEntity {
        //昵称,添加这个注解能在文档上看到参数名称
        @ApiModelProperty(value = "昵称")
        private String niceName;
        //账号
        @ApiModelProperty(value = "账号")
        private String username;
    }
    
    修改PageEntity
    @Data
    public class PageEntity {
    //  页数
    @ApiModelProperty(value = "页数")
        private Integer page;
    //每页数量
    @ApiModelProperty(value = "每页数量")
        private Integer limit;
    }
    
    

    菜单中添加接口文档菜单

    然后就能看到如下图片了,只改了一小部分,只能登陆之后访问,或者修改getShiroFilterFactoryBean放行doc.html等资源,能直接看到,登陆之后可以直接访问http://127.0.0.1:8082/doc.html#/home也可以看到!

    源码

    在公众号内发送后台即可获取源码和数据库

    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/310538.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号