基于Ant DesignPro Vue实现通过SpringBoot后台加载自定义菜单- 前后端分离

7 篇文章 3 订阅

基于Ant DesignPro Vue实现通过SpringBoot后台加载自定义菜单- 前后端分离

本文想基于Ant DesignPro Vue构建的前端+SpringBoot实现的后端接口服务,实现前后端分离开发和独立运行,业务场景是登录认证,认证成功后返回该用户相应权限范围内可见的菜单。

Ant Design Pro相关系列文章:
一、AntDesign Pro安装过程
二、基于Ant DesignPro实现通过SpringBoot后台加载自定义菜单-前端部分
三、基于Ant DesignPro实现通过SpringBoot后台加载自定义菜单-SpringBoot后端部分
四、搭建Vue版Ant Design Pro后台管理系统
五、基于Ant DesignPro Vue实现通过SpringBoot后台加载自定义菜单- 前后端分离
六、基于Ant DesignPro Vue + SpringBoot 前后端分离 - 部署后解决跨域的问题
七、基于Ant DesignPro Vue + SpringBoot 前后端分离 - 后端微服化 + 接口网关 + Nacos
八、基于Ant DesignPro Vue + SpringBoot 前后端分离 - 后端微服化 + 接口网关 + Nacos + Sentinel

一、通过Ant DesignPro Vue构建前端

参见 搭建Vue版Ant Design Pro后台管理系统

二、Ant DesignPro Vue前端对接后台服务接口

1、去掉Mock

编辑src/main.js,把mock注释
在这里插入图片描述

2、vue.config.js 中配置api代理

在这里插入图片描述

说明:
上面target配置属性是指后台服务接口URL,默认格式为:target指定的Ulr/api/请求接口

在这里插入图片描述

3、修改菜单加载是从后台服务接口请求

在这里插入图片描述

三、创建Ant DesignPro后台服务SpringBoot项目

1. File->New->Project

第一步第二步
第三步
第四步

2.编辑pom.xml,添加需要的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/>
    </parent>
    <groupId>cn.chinaelink.im</groupId>
    <artifactId>mcvboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mcboot</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 热部署加入的引用,1.spring-boot-devtools-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--json需要的依赖 -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib-ext-spring</artifactId>
            <version>1.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
		<!--重点:模板引擎,用于显示网页需要的依赖,如果不需要将静态页面放入当前工程,则不需要解注下面依赖-->
		<!-- 如果要在当前工程中加入静态页面,首先需要解注下面依赖,并在src/main/resources/目录下创建static和templates目录-->
		<!--
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.编辑application.properties

#配置管理服务端口号,默认为8080
server.port=8080
#服务访问路径
server.servlet.context-path=/

# 输出的log文件名
logging.file.name=mc
# 输出的文件的路径
logging.file.path=./logs/mcv/
# 限制日志文件的大小
logging.file.max-size=10MB
# 日志的保存天数
logging.file.max-history=7

# 输出级别
logging.level.root=warn
logging.level.cn.com.hxyl.filebs=debug

# xml配置文件
logging.config=classpath:logback-spring.xml

#关闭缓存
#如果不需要将静态页面放入当前工程,则不需要解注下面依赖
#如果要在当前工程中加入静态页面,首先需要解注下面依赖,并将静态页面文件放入src/main/resources/static/目录下
#spring.thymeleaf.cache=false
#spring.thymeleaf.prefix=classpath:/static/
server.tomcat.threads.max=100
server.tomcat.threads.min-spare=30

#开启项目热部署
spring.devtools.restart.enabled=true

4.创建依赖的实体类

在这里插入图片描述

4.1 登录请求实体类UserLoginDto.java

package cn.chinaelink.im.mcvboot.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserLoginDto {
    // 用户名
    private String username;
    // 密码
    private String password;
    // 手机号
    private String mobile;
    // 验证码
    private String captcha;
}

4.2 向前端画面传输的用户信息实体类 UserVo.java

package cn.chinaelink.im.mcvboot.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserVo {
    private String id;
    private String name;
    private String username;
    private String password;
    private String avatar;
    private int status;
    private String telephone;
    private String lastLoginIp;
    private long lastLoginTime;
    private String creatorId;
    private long createTime;
    private int deleted;
    private String roleId;
    private String lang;
    private String token;
}

4.3 菜单实体类MenuVo.java

package cn.chinaelink.im.mcvboot.vo.menu;

import lombok.Data;

@Data
public class MenuVo {
    private String name;
    private int id;
    private int parentId;
    private String component;
    private String redirect;
    private String path;
    private MenuMetaVo meta;
}

4.4 菜单项实体类MenuMetaVo.java

package cn.chinaelink.im.mcvboot.vo.menu;

import lombok.Data;

@Data
public class MenuMetaVo {
    private String title;
    private String icon;
    private String target;
    private boolean show;
}

5.创建登录认证(/api/auth/)接口响应处理类

所以有接口实现都是参见src/mock/services/目录的相应的模拟接口js的结果定义的

在这里插入图片描述

AuthController类

import cn.chinaelink.im.mcvboot.dto.UserLoginDto;
import cn.chinaelink.im.mcvboot.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Optional;
import java.util.Random;
import java.util.UUID;

@Controller
@Slf4j
@RequestMapping("/api/auth")
public class AuthController {
    @PostMapping("/login")
    @ResponseBody
    public String login(@RequestBody UserLoginDto userLoginDto) {
        JSONObject resJson = new JSONObject();
        if (Optional.ofNullable(userLoginDto.getUsername()).isPresent() &&
                ("ant.design".equals(userLoginDto.getPassword()) ||
                        "admin".equals(userLoginDto.getUsername()))
        ) {
            UserVo userVo = getAdminUserVo();
            resJson.put("result",JSONObject.fromObject(userVo).toString());
            resJson.put("message","认证成功");
            resJson.put("code",200);
            resJson.put("_status", 200);
            resJson.put("token",userVo.getToken());
            return resJson.toString();
        } else if(Optional.ofNullable(userLoginDto.getMobile()).isPresent()){
            UserVo userVo =  getAdminUserVo();
            resJson.put("result",JSONObject.fromObject(userVo).toString());
            resJson.put("message","认证成功");
            resJson.put("code",200);
            resJson.put("_status", 200);
            resJson.put("token",userVo.getToken());
            return resJson.toString();
        }
        JSONObject result = new JSONObject();
        result.put("isLogin", true);
        resJson.put("result",result);
        resJson.put("message","错误的用户名和密码,请确认后重试!");
        resJson.put("code",401);
        resJson.put("_status", 401);
        return resJson.toString();
    }

    @PostMapping("/2step-code")
    @ResponseBody
    public JSONObject twoFactor() {
        JSONObject resJson = new JSONObject();
        JSONObject dataJson = new JSONObject();
        dataJson.put("stepCode",new Random().nextInt(1));
        resJson.put("result", dataJson);
        return resJson;
    }

    @PostMapping("/logout")
    @ResponseBody
    public JSONObject logout() {
        JSONObject data = new JSONObject();
        data.put("result", new JSONObject());
        data.put("message", "");
        return data;
    }

    private UserVo getAdminUserVo() {
        UserVo userVo = new UserVo();
        userVo.setId(UUID.randomUUID().toString());
        userVo.setName("超级管理员");
        userVo.setUsername("admin");
        userVo.setAvatar("https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png");
        userVo.setStatus(1);
        userVo.setLastLoginTime(System.currentTimeMillis());
        userVo.setCreatorId("admin");
        userVo.setCreateTime(System.currentTimeMillis());
        userVo.setRoleId("admin");
        userVo.setLang("zh-CN");
        userVo.setToken("4291d7da9005377ec9aec4a71ea837f");
        return userVo;
    }
}

6.创建用户(/api/user/)接口响应处理类

package cn.chinaelink.im.mcvboot.controller.api;

import cn.chinaelink.im.mcvboot.vo.menu.MenuMetaVo;
import cn.chinaelink.im.mcvboot.vo.menu.MenuVo;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;

@Controller
@Slf4j
@RequestMapping("/api/user")
public class UserController {
    @RequestMapping("/info")
    @ResponseBody
    public JSONObject info(){
        JSONObject userInfoJson = new JSONObject();

        userInfoJson.put("id", "4291d7da9005377ec9aec4a71ea837f");
        userInfoJson.put("name", "天野远子");
        userInfoJson.put("username", "admin");
        userInfoJson.put("password", "");
        userInfoJson.put("avatar", "/avatar2.jpg'");
        userInfoJson.put("status", 1);
        userInfoJson.put("telephone", "");
        userInfoJson.put("lastLoginIp", "27.154.74.117");
        userInfoJson.put("lastLoginTime", 1534837621348L);
        userInfoJson.put("creatorId", "admin'");
        userInfoJson.put("createTime", 1497160610259L);
        userInfoJson.put("merchantCode", "TLif2btpzg079h15bk'");
        userInfoJson.put("deleted", 0);
        userInfoJson.put("roleId", "admin'");

        JSONObject roleObj = new JSONObject();
        roleObj.put("id","admin");
        roleObj.put("name","管理员");
        roleObj.put("describe","拥有所有权限");
        roleObj.put("status", 1);
        roleObj.put("creatorId","system");
        roleObj.put("createTime",1497160610259L);
        roleObj.put("deleted", 0);
        JSONArray permissionArray = new JSONArray();
        JSONObject permission1 = new JSONObject();
        permission1.put("roleId","admin");
        permission1.put("permissionId","dashboard");
        permission1.put("permissionName","仪表盘");
        permission1.put("actions","[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]");

        JSONArray actionEntitySet = new JSONArray();
        JSONObject actionEntity1 = new JSONObject();
        actionEntity1.put("action", "add");
        actionEntity1.put("describe", "新增");
        actionEntity1.put("defaultCheck", false);
        actionEntitySet.add(actionEntity1);

        JSONObject actionEntity2 = new JSONObject();
        actionEntity2.put("action", "query");
        actionEntity2.put("describe", "查询");
        actionEntity2.put("defaultCheck", false);
        actionEntitySet.add(actionEntity2);

        JSONObject actionEntity3 = new JSONObject();
        actionEntity3.put("action", "get");
        actionEntity3.put("describe", "详情");
        actionEntity3.put("defaultCheck", false);
        actionEntitySet.add(actionEntity3);

        JSONObject actionEntity4 = new JSONObject();
        actionEntity4.put("action", "update");
        actionEntity4.put("describe", "修改");
        actionEntity4.put("defaultCheck", false);
        actionEntitySet.add(actionEntity4);

        JSONObject actionEntity5 = new JSONObject();
        actionEntity5.put("action", "delete");
        actionEntity5.put("describe", "删除");
        actionEntity5.put("defaultCheck", false);
        actionEntitySet.add(actionEntity5);

        permission1.put("actionEntitySet", actionEntitySet);
        permission1.put("actionList", null);
        permission1.put("dataAccess", null);
        permissionArray.add(permission1);

        JSONObject permission2 = new JSONObject();
        permission2.put("roleId","admin");
        permission2.put("permissionId","exception");
        permission2.put("permissionName","异常页面权限");
        permission2.put("actions","[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]");

        JSONArray actionEntitySet2 = new JSONArray();
        JSONObject actionEntity21 = new JSONObject();
        actionEntity21.put("action", "add");
        actionEntity21.put("describe", "新增");
        actionEntity21.put("defaultCheck", false);
        actionEntitySet2.add(actionEntity21);

        JSONObject actionEntity22 = new JSONObject();
        actionEntity22.put("action", "query");
        actionEntity22.put("describe", "查询");
        actionEntity22.put("defaultCheck", false);
        actionEntitySet2.add(actionEntity22);

        JSONObject actionEntity23 = new JSONObject();
        actionEntity23.put("action", "get");
        actionEntity23.put("describe", "详情");
        actionEntity23.put("defaultCheck", false);
        actionEntitySet2.add(actionEntity23);

        JSONObject actionEntity24 = new JSONObject();
        actionEntity24.put("action", "update");
        actionEntity24.put("describe", "修改");
        actionEntity24.put("defaultCheck", false);
        actionEntitySet2.add(actionEntity24);

        JSONObject actionEntity25 = new JSONObject();
        actionEntity25.put("action", "delete");
        actionEntity25.put("describe", "删除");
        actionEntity25.put("defaultCheck", false);
        actionEntitySet2.add(actionEntity25);

        permission2.put("actionEntitySet", actionEntitySet2);
        permission2.put("actionList", null);
        permission2.put("dataAccess", null);
        permissionArray.add(permission2);
        roleObj.put("permissions", permissionArray);
        userInfoJson.put("role", roleObj);

        JSONObject body = new JSONObject();
        body.put("result", userInfoJson);
        return body;
    }
    @RequestMapping("/nav")
    @ResponseBody
    public JSONObject getUserMenus(){
        List<MenuVo> dataArray = new ArrayList<>();
        MenuVo menu1 = new MenuVo();
        menu1.setId(1);
        menu1.setParentId(0);
        menu1.setName("dashboard");
        menu1.setComponent("RouteView");
        menu1.setRedirect("/dashboard/workplace");
        MenuMetaVo meta1 = new MenuMetaVo();
        meta1.setTitle("menu.dashboard");
        meta1.setIcon("dashboard");
        meta1.setShow(true);
        menu1.setMeta(meta1);
        dataArray.add(menu1);

        MenuVo menu2 = new MenuVo();
        menu2.setId(7);
        menu2.setParentId(1);
        menu2.setName("workplace");
        menu2.setComponent("Workplace");
        MenuMetaVo meta2 = new MenuMetaVo();
        meta2.setTitle("menu.dashboard.monitor");
        meta2.setShow(true);
        menu2.setMeta(meta2);
        dataArray.add(menu2);

        MenuVo menu3 = new MenuVo();
        menu3.setId(3);
        menu3.setParentId(1);
        menu3.setName("monitor");
        menu3.setPath("https://www.baidu.com/");
        MenuMetaVo meta3 = new MenuMetaVo();
        meta3.setTitle("menu.dashboard.workplace");
        meta3.setTarget("_blank");
        meta3.setShow(true);
        menu3.setMeta(meta3);
        dataArray.add(menu3);

        MenuVo menu4 = new MenuVo();
        menu4.setId(2);
        menu4.setParentId(1);
        menu4.setName("Analysis");
        menu4.setComponent("Analysis");
        menu4.setPath("/dashboard/analysis");
        MenuMetaVo meta4 = new MenuMetaVo();
        meta4.setTitle("menu.dashboard.analysis");
        meta4.setShow(true);
        menu4.setMeta(meta4);
        dataArray.add(menu4);

        // Form
        MenuVo menu5 = new MenuVo();
        menu5.setId(10);
        menu5.setParentId(0);
        menu5.setName("form");
        menu5.setComponent("RouteView");
        menu5.setRedirect("/form/base-form");
        MenuMetaVo meta5 = new MenuMetaVo();
        meta5.setTitle("menu.form");
        meta5.setIcon("form");
        menu5.setMeta(meta5);
        dataArray.add(menu5);

        MenuVo menu6 = new MenuVo();
        menu6.setId(6);
        menu6.setParentId(10);
        menu6.setName("basic-form");
        menu6.setComponent("BasicForm");
        MenuMetaVo meta6 = new MenuMetaVo();
        meta6.setTitle("menu.form.basic-form");
        menu6.setMeta(meta6);
        dataArray.add(menu6);

        MenuVo menu7 = new MenuVo();
        menu7.setId(5);
        menu7.setParentId(10);
        menu7.setName("step-form");
        menu7.setComponent("StepForm");
        MenuMetaVo meta7 = new MenuMetaVo();
        meta7.setTitle("menu.form.step-form");
        menu7.setMeta(meta7);
        dataArray.add(menu7);

        MenuVo menu8 = new MenuVo();
        menu8.setId(4);
        menu8.setParentId(10);
        menu8.setName("advanced-form");
        menu8.setComponent("AdvanceForm");
        MenuMetaVo meta8 = new MenuMetaVo();
        meta8.setTitle("menu.form.advanced-form");
        menu8.setMeta(meta8);
        dataArray.add(menu8);

        // List
        MenuVo menu9 = new MenuVo();
        menu9.setId(10010);
        menu9.setParentId(0);
        menu9.setName("list");
        menu9.setComponent("RouteView");
        menu9.setRedirect("/list/table-list");
        MenuMetaVo meta9 = new MenuMetaVo();
        meta9.setTitle("menu.list");
        meta9.setIcon("table");
        meta9.setShow(true);
        menu9.setMeta(meta9);
        dataArray.add(menu9);

        MenuVo menu10 = new MenuVo();
        menu10.setId(10011);
        menu10.setParentId(10010);
        menu10.setName("table-list");
        menu10.setComponent("TableList");
        menu10.setPath("/list/table-list/:pageNo([1-9]\\d*)?");
        MenuMetaVo meta10 = new MenuMetaVo();
        meta10.setTitle("menu.list.table-list");
        meta10.setShow(true);
        menu10.setMeta(meta10);
        dataArray.add(menu10);

        MenuVo menu11 = new MenuVo();
        menu11.setId(10012);
        menu11.setParentId(10010);
        menu11.setName("basic-list");
        menu11.setComponent("StandardList");
        MenuMetaVo meta11 = new MenuMetaVo();
        meta11.setTitle("menu.list.basic-list");
        meta11.setShow(true);
        menu11.setMeta(meta11);
        dataArray.add(menu11);

        JSONObject body = new JSONObject();
        body.put("result", dataArray);
        return body;
    }
}

7.创建Account(/api/account)接口响应处理类

package cn.chinaelink.im.mcvboot.controller.api;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.Random;

@Controller
@Slf4j
@RequestMapping("/api/account")
public class AccountController {

    @RequestMapping("/sms")
    @ResponseBody
    public String smsCaptcha() {
        Random random = new Random();
        int num = random.nextInt(89999) + 10000;
        JSONObject data = new JSONObject();
        data.put("captcha", num);

        JSONObject response = new JSONObject();
        response.put("result", data);
        return response.toString();
    }
}

四、验证

1.启动服务端

在这里插入图片描述

启动成功后可以通过浏览器访问http://127.0.0.1:8080/

2.启动前端

在命令行进入前端代码所在目录后,执行下面的命令

D:\work\JavaTeam\workspace\IdeaProjects\antDesignPro\antdvPromc> yarn run serve

在这里插入图片描述

3.访问前端画面

在这里插入图片描述
在这里插入图片描述

说明:
通过访问,前端已正常通过http://192.168.0.100:8080这个后端服务接口登录认证成功,并成功的获取到后台返回的菜单(只返回了两项一级菜单)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

老杜095

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

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

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

打赏作者

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

抵扣说明:

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

余额充值