springboot+vue+springsecurity前后端权限管理系统
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
由于字数限制,请阅读原文,原文附源码和sql以及项目演示地址和项目资料。
环境:
win10、idea22023.2、vscode1.7、maven3.5、jdk8、Redis
技术:
-
springboot2.5.9
-
springsecurity
-
Redis
-
mybatis plus
-
mysql5.7.38
-
swagger
-
jwt
-
vue2
-
element ui
-
vuex
-
vue-router
-
axios
-
mockjs
-
echarts
-
less
模块:
-
登录页面
-
首页
-
权限管理
1.用户管理
2.角色管理
3.菜单管理
功能要点:
-
从0到1实现项目前后端搭建
-
vuex实现面包屑和Tag功能
-
vuex+localStorage动态路由和菜单(重点)
-
封装一个ECharts组件
-
封装Table表格
-
树形表格和CheckBox的使用
-
封装统一返回类
-
两种方式实现代码生成,解放双手
-
jwt、swagger、Redis封装
-
权限管理(重点)
项目截图
1、登录页面
2、首页
3、用户管理
4、角色管理
5、分配权限
6、菜单管理
7、根据权限动态加载菜单和按钮
8、部分主要代码
登录
<template>
<el-form
ref="form"
label-width="70px"
:inline="true"
class="login-container"
:model="form"
:rules="rules"
>
<h3 class="login_title">系统登录</h3>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="form.password"
placeholder="请输入密码"
></el-input>
</el-form-item>
<el-form-item label="验证码" prop="code">
<el-input v-model="form.code" maxlength="6"></el-input>
</el-form-item>
<el-form-item>
<el-image
:src="captchaImg"
class="captchaImg"
style="margin-left: 15px"
@click="getCaptcha"
></el-image>
</el-form-item>
<el-form-item>
<el-button
@click="submit"
style="margin-left: 105px; margin-top: 10px"
type="primary"
:loading="loading"
>登录</el-button
>
<!-- <el-button
@click="submit1"
style="margin-left: 105px; margin-top: 10px"
type="primary"
:loading="loading"
>登录1</el-button
> -->
</el-form-item>
</el-form>
</template>
<script>
// import Mock from 'mockjs'
// import Cookie from 'js-cookie'
// import { getMenu } from '../api'
import qs from "qs";
import http from "@/utils/request";
export default {
data() {
return {
captchaImg: "",
loading: false,
form: {
username: "admin",
password: "111111",
token: "aaaaa",
code: "",
},
rules: {
username: [
{ required: true, trigger: "blur", message: "请输入用户名" },
],
password: [{ required: true, trigger: "blur", message: "请输入密码" }],
},
};
},
created() {
this.getCaptcha();
},
methods: {
submit1() {},
getCaptcha() {
http.get("/captcha").then((res) => {
if(res.code === 20000){
console.log("/captcha");
console.log(res);
this.form.token = res.data.data.token;
this.captchaImg = res.data.data.captchaImg;
//this.form.code = "";
}
});
},
// 登录
submit() {
let that = this;
that.$refs.form.validate((valid) => {
if (valid) {
this.loading = true;
this.$store
.dispatch("Login", this.form)
.then((res) => {
if (res.code != 20000) {
that.$message({
type: "warning",
message: res.message,
});
this.loading = false;
return false;
}
this.loading = false;
this.$router.push({ path: "/home" });
})
.catch(() => {
this.loading = false;
});
// http
// .post("/login?" + qs.stringify(this.form))
// .then((res) => {
// if (res.code != 20000) {
// that.$message({
// type: "warning",
// message: res.message,
// });
// }
// console.log(res);
// const jwt = res.data.authorization;
// this.$store.commit("SET_TOKEN", jwt);
// //
// this.$router.push("/home");
// })
// .catch((e) => {});
//this.loading = true;
// that.$store
// .dispatch("Login", that.form)
// .then(() => {
// //this.loading = false;
// that.$router.push({ path: "/" });
// })
// .catch(() => {
// //this.loading = false;
// });
} else {
console.log("error submit!!");
return false;
}
});
// // token信息
// const token = Mock.Random.guid()
// 校验通过
// this.$refs.form.validate((valid) => {
// if (valid) {
// getMenu(this.form).then(({ data }) => {
// console.log(data)
// if (data.code === 20000) {
// // token信息存入cookie用于不同页面间的通信
// Cookie.set('token', data.data.token)
// // 获取菜单的数据,存入store中
// this.$store.commit('setMenu', data.data.menu)
// this.$store.commit('addMenu', this.$router)
// // 跳转到首页
// this.$router.push('/home')
// } else {
// this.$message.error(data.data.message);
// }
// })
// }
// })
},
},
};
</script>
<style lang="less" scoped>
.login-container {
width: 650px;
border: 1px solid #eaeaea;
margin: 180px auto;
padding: 35px 35px 15px 35px;
background-color: #fff;
border-radius: 15px;
box-shadow: 0 0 25px #cac6c6;
box-sizing: border-box;
.login_title {
text-align: center;
margin-bottom: 40px;
color: #505458;
}
.el-input {
width: 198px;
}
}
</style>
菜单
<template>
<div>
<el-table
:data="tableData"
style="width: 100%; margin-bottom: 20px"
row-key="id"
border
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column prop="name" label="名称" sortable min-width="20%">
</el-table-column>
<el-table-column prop="path" label="访问路径" sortable min-width="15%">
</el-table-column>
<el-table-column
prop="component"
label="组件路径"
sortable
min-width="15%"
>
</el-table-column>
<el-table-column
prop="permissionValue"
label="权限值"
sortable
min-width="15%"
>
</el-table-column>
<el-table-column prop="status" label="状态" sortable min-width="10%">
</el-table-column>
<el-table-column prop="icon" label="图标" sortable min-width="10%">
</el-table-column>
<el-table-column label="操作" min-width="15%">
<template slot-scope="scope">
<!-- 第一层和第二层可以添加菜单,第三层添加功能,第四层修改功能 -->
<el-button
v-if="scope.row.level === 1 || scope.row.level === 2"
type="text"
size="mini"
@click="addOrEditMenuDialog(scope.row, 'add')"
>添加菜单</el-button
>
<el-button
v-if="scope.row.level === 3"
type="text"
size="mini"
@click="
() => {
dialogPermissionFormVisible = true;
permissionForm = { ...PERMISSION_FORM };
permissionForm.pid = scope.row.id;
permissionTitle = '添加功能';
}
"
>
添加功能</el-button
>
<el-button
v-if="scope.row.level === 4"
type="text"
size="mini"
@click="updatePermissionDialog(scope.row)"
>修改功能</el-button
>
<el-button
v-if="scope.row.level !== 1 && scope.row.level !== 4"
type="text"
size="mini"
@click="addOrEditMenuDialog(scope.row, 'edit')"
>修改</el-button
>
<el-button
v-if="scope.row.level !== 1"
@click="deleteSubmit(scope.row)"
type="text"
size="mini"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 添加菜单的窗口 -->
<el-dialog
:title="title"
:label-position="labelPosition"
:visible.sync="dialogFormVisible"
>
<el-form
ref="menuForm"
:model="menuForm"
:rules="menuFormRules"
label-width="120px"
>
<el-form-item label="菜单名称" prop="name">
<el-input v-model="menuForm.name"></el-input>
</el-form-item>
<el-form-item label="访问路径" prop="path" v-if="showFlag">
<el-input v-model="menuForm.path"></el-input>
</el-form-item>
<el-form-item label="组件路径" prop="component" v-if="showFlag">
<el-input v-model="menuForm.component"></el-input>
</el-form-item>
<!-- <el-form-item label="权限值" prop="permissionValue">
<el-input v-model="menuForm.permissionValue"></el-input>
</el-form-item> -->
<el-form-item label="图标" prop="icon">
<el-input v-model="menuForm.icon"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetMenu()">取 消</el-button>
<el-button type="primary" @click="addMenuFormSubmit()">确 定</el-button>
</div>
</el-dialog>
<!-- 添加功能的窗口 -->
<el-dialog
:title="permissionTitle"
:label-position="labelPosition"
:visible.sync="dialogPermissionFormVisible"
>
<el-form
ref="permissionForm"
:model="permissionForm"
:rules="permissionFormRules"
label-width="120px"
>
<el-form-item label="功能名称" prop="name">
<el-input v-model="permissionForm.name"></el-input>
</el-form-item>
<el-form-item label="访问路径" prop="path">
<el-input v-model="permissionForm.path"></el-input>
</el-form-item>
<el-form-item label="组件路径" prop="component">
<el-input v-model="permissionForm.component"></el-input>
</el-form-item>
<el-form-item label="功能权限值" prop="permissionValue">
<el-input v-model="permissionForm.permissionValue"></el-input>
</el-form-item>
<el-form-item label="图标" prop="icon">
<el-input v-model="permissionForm.icon"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetPermission()">取 消</el-button>
<el-button type="primary" @click="addPermissonFormSubmit()"
>确 定</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { getData, updateMenuSubmit, deleteSubmit } from "@/api/permission.js";
import http from "@/utils/request";
const MENU_FORM = {
name: "",
path: "",
component: "",
// status: 0,
icon: "setting",
pid: 0,
type: "1",
id: "",
};
const PERMISSION_FORM = {
name: "",
path: "",
component: "",
permissionValue: "",
// status: 0,
icon: "setting",
pid: 0,
type: "2",
id: "",
};
export default {
data() {
return {
showFlag: true,
labelPosition: "left",
tableData: [], //获取递归取得的全部菜单
dialogFormVisible: false, //添加修改菜单窗口开关
dialogPermissionFormVisible: false, //添加修改功能窗口开关
title: "添加菜单", //添加修改菜单标题
permissionTitle: "添加功能", //添加修改菜单标题
menuForm: MENU_FORM, //添加修改菜单内容
permissionForm: PERMISSION_FORM, //添加修改功能内容
//表单验证
menuFormRules: {
name: [
{ required: true, message: "请输入菜单名称", trigger: "blur" },
{
min: 3,
max: 30,
message: "长度在 3 到 30 个字符",
trigger: "blur",
},
],
path: [
{ message: "请输入访问路径", trigger: "blur" },
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
component: [
{ message: "请输入组件路径", trigger: "blur" },
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
},
//功能表单验证
permissionFormRules: {
name: [
{ required: true, message: "请输入菜单名称", trigger: "blur" },
{ min: 3, max: 8, message: "长度在 3 到 8 个字符", trigger: "blur" },
],
permissionValue: [
{ required: true, message: "请输入权限值", trigger: "blur" },
{
min: 3,
max: 18,
message: "长度在 3 到 18 个字符",
trigger: "blur",
},
],
},
};
},
created() {
//获取递归取得的全部菜单
this.getAllMenuList();
},
methods: {
//修改功能
updatePermissionDialog(val) {
this.dialogPermissionFormVisible = true;
this.permissionForm = val;
this.permissionTitle = "修改功能";
},
//取消菜单添加或修改
resetMenu() {
this.dialogFormVisible = false;
this.menuForm = {};
},
//取消功能添加或修改
resetPermission() {
this.dialogPermissionFormVisible = false;
this.permissionForm = {};
},
//添加修改下级功能
addPermissonFormSubmit() {
let that = this;
this.$refs.permissionForm.validate((valid) => {
if (valid) {
if (that.permissionForm.id) {
//修改
updateMenuSubmit(that.permissionForm).then((res) => {
if (res.code === 20000) {
that.$message({
type: "success",
message: "修改功能成功",
});
//刷新页面
that.getAllMenuList();
that.dialogPermissionFormVisible = false;
that.permissionForm = { ...PERMISSION_FORM };
}
});
} else {
//新增
//let permission = that.menuForm;
http({
url: "/permission/save",
method: "post",
data: that.permissionForm,
}).then((res) => {
if (res.code === 20000) {
that.$message({
type: "success",
message: "添加功能成功",
});
//刷新页面
that.getAllMenuList();
that.dialogPermissionFormVisible = false;
that.permissionForm = { ...PERMISSION_FORM };
}
});
}
} else {
return false;
}
});
},
//删除
deleteSubmit(val) {
let that = this;
this.$confirm("此操作将永久删除该记录,是否继续?", "提升", {
distinguishCancelAndClose: true,
confirmButtonText: "确定",
cancelButtonText: "取消",
})
.then(() => {
deleteSubmit(val.id).then((res) => {
if (res.code === 20000) {
that.$message({
type: "success",
message: "删除成功",
});
//刷新页面
that.getAllMenuList();
}
});
this.$message({
type: "info",
message: "保存修改",
});
})
.catch((action) => {
this.$message({
type: "info",
message:
action === "cancel" ? "放弃保存并离开页面" : "停留在当前页面",
});
});
// let that = this;
// this.$confirm("此操作将永久删除该记录,是否继续?", "提升", {
// cofirmButtonText: "确定",
// cancelButtonText: "取消",
// type: "warning",
// }).then(() => {
// deleteSubmit(val.id).then((res) => {
// if (res.code === 20000) {
// that.$message({
// type: "success",
// message: "删除成功",
// });
// //刷新页面
// that.getAllMenuList();
// }
// });
// });
},
//修改
updateMenuSubmit() {
let that = this;
updateMenuSubmit(that.menuForm).then((res) => {
if (res.code === 20000) {
that.$message({
type: "success",
message: "修改菜单成功",
});
//刷新页面
that.getAllMenuList();
that.dialogFormVisible = false;
}
});
},
//新增
addMenuSubmit() {
let that = this;
//let permission = that.menuForm;
http({
url: "/admin/sys/permission/save",
method: "post",
data: that.menuForm,
}).then((res) => {
if (res.code === 20000) {
that.$message({
type: "success",
message: "添加菜单成功",
});
//刷新页面
that.getAllMenuList();
that.dialogFormVisible = false;
}
});
},
//提交添加菜单的数据
addMenuFormSubmit() {
let that = this;
this.$refs.menuForm.validate((valid) => {
if (valid) {
if (that.menuForm.id) {
that.title = "修改菜单";
//修改
that.updateMenuSubmit();
} else {
that.title = "添加菜单";
//新增
that.addMenuSubmit();
}
} else {
return false;
}
});
},
//显示添加菜单
addOrEditMenuDialog(val, flag) {
if (val.level === 1) {
this.showFlag = false;
} else {
this.showFlag = true;
}
if ("add" === flag) {
//新增的话,页面的值初始化为定义好的常量
this.menuForm = { ...MENU_FORM };
//新增的话,新增的菜单的pid为当前选中的行的id
this.menuForm.pid = val.id;
this.title = "添加菜单";
} else {
this.title = "修改菜单";
//修改的话,页面的值初始化为列表的具体的内容
Object.assign(this.menuForm, val);
//修改
if (val.level === 2) {
this.showFlag = false;
}
}
this.dialogFormVisible = true;
},
//获取递归取得的全部菜单
getAllMenuList() {
getData().then((res) => {
if (res.code === 20000 && res.data) {
this.tableData = res.data.data;
//console.log('JSON.stringify(this.tableData) ==='+JSON.stringify(this.tableData))
}
});
},
},
};
</script>
分配权限
<template>
<div style="margin: 29px">
<el-tree
ref="tree"
:data="data"
show-checkbox
default-expand-all
node-key="id"
highlight-current
:props="defaultProps"
/>
<el-button :disabled="saveBtnDisabled" type="primary" @click="save"
>保存</el-button
>
</div>
</template>
<script>
import {
toAssign,
doAssign,
} from "@/api/permission";
export default {
data() {
return {
saveBtnDisabled: false,
data: [],
roleId: "",
defaultProps: {
children: "children",
label: "name",
},
};
},
watch: {
$route(to, from) {
this.init();
},
},
created() {
this.init();
},
methods: {
init() {
if (this.$route.params && this.$route.params.id) {
this.roleId = this.$route.params.id;
this.getDataList(this.roleId);
}
},
getDataList(roleId) {
toAssign(roleId).then((res) => {
if (res.code === 20000 && res.data.data) {
this.data = res.data.data;
var list = [];
var jsonList = JSON.parse(JSON.stringify(this.data));
var llll = JSON.stringify(this.data);
console.log("this.data========================= " + this.data);
console.log("jsonList========================= " + jsonList);
console.log(
"JSON.stringify(this.data)========================= " +
JSON.stringify(this.data)
);
this.getJsonList(list, jsonList[0]["children"]);
this.$refs.tree.setCheckedKeys(list);
}
});
},
//获取所有的角色的权限
getJsonList(list, jsonList) {
for (var i = 0; i < jsonList.length; i++) {
if (
jsonList[i]["hasSelect"] == true &&
jsonList[i]["children"].length === 0
) {
list.push(jsonList[i]["id"]);
}
if (jsonList[i]["children"].length > 0) {
this.getJsonList(list, jsonList[i]["children"]);
}
}
},
save() {
this.saveBtnDisabled = true;
var beforeIds = this.$refs.tree.getHalfCheckedKeys().join(",");
var afterIds = this.$refs.tree.getCheckedKeys().join(",");
var ids = beforeIds + "," + afterIds;
if (ids === ",") {
ids = [];
}
console.log(ids);
doAssign(this.roleId, ids).then((res) => {
if (res.code === 20000 && res.success) {
this.$message({
type: "info",
message: "保存成功!",
});
this.$router.push({ path: "/role" });
} else {
this.$message({
type: "info",
message: "保存失败!",
});
}
});
},
},
};
</script>
<style>
</style>
路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
import User from '@/views/sys/user/User.vue'
import Main from '@/views/Main.vue'
import store from '@/store'
import { getToken } from '@/utils/auth'
import { login, logout, getInfo } from '@/api/login'
Vue.use(VueRouter)
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue')
},
//主路由
// {
// path: '/',
// component: Main,
// redirect: '/home',
// children: [
// //子路由
// { path: 'home', name: "home", component: Home },//首页
// // { path: 'user', name: "user", component: User },//用户管理
// // { path: 'role', name: "role", component: () => import("@/views/sys/Role.vue") },//角色管理
// // { path: 'menu', name: "menu", component: () => import("@/views/sys/Menu.vue") },//菜单管理管理
// ]
// },
// {
// path: '/user',
// name: 'User',
// component: User
// },
]
// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
mode: 'history', // 去掉url中的#
routes // (缩写) 相当于 routes: routes
})
// 4. 创建和挂载根实例。挂载到main.js的根节点
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
// const app = new Vue({
// router
// }).$mount('#app')
// 防止连续点击多次路由报错
// 获取原型对象push函数
const originalPush = VueRouter.prototype.push
// 获取原型对象replace函数
const originalReplace = VueRouter.prototype.replace
// 修改原型对象中的push函数
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
// 修改原型对象中的replace函数
VueRouter.prototype.replace = function replace(location) {
return originalReplace.call(this, location).catch(err => err)
}
//模拟菜单数据
//const authoritys = ['sys:user:list', "sys:user:save", "sys:user:delete"]
const menuData1 = [
// {
// path: "/",
// name: "home",
// label: "首页",
// icon: "s-home",
// url: "Home/Home",
// },
{
label: "权限管理",
name: "system",
icon: "location",
children: [
{
path: "/user",
name: "user",
label: "用户管理",
icon: "setting",
component: "sys/user/User",
},
{
path: '/sys/role/distribution/:id',
name: '角色权限',
component: 'sys/role/roleForm',
meta: { title: '角色权限', icon: 'table' },
hidden: true
},
{
path: '/userForm/:id',
name: '角色权限',
component: 'sys/user/userForm',
meta: { title: '角色权限', icon: 'table' },
hidden: true
},
{
path: "/role",
name: "role",
label: "角色管理",
icon: "setting",
component: "sys/role/Role",
},
{
path: "/menu",
name: "menu",
label: "菜单管理",
icon: "setting",
component: "sys/menu/Menu",
},
],
},
]
// 拼装动态路由
const manageRoute = {
path: '/',
component: Main,
redirect: '/login',
children: [
//子路由
{ path: 'home', name: "home", component: Home },//首页
]
}
//获取数据
//菜单
// store.commit('setMenuList', menuData1)
//权限用户
//localStorage.setItem("menus1", JSON.stringify(menuData1))
// 注意:刷新页面会导致页面路由重置
const setRoutes = () => {
//const storeMenus = localStorage.getItem("menus");
const storeMenus = localStorage.getItem("menus");
if (storeMenus) {
// 获取当前的路由对象名称数组
const currentRouteNames = router.getRoutes().map(v => v.name)
if (!currentRouteNames.includes('home')) {
const menus = JSON.parse(storeMenus)
menus.forEach(item => {
if (item.path) { // 当且仅当path不为空的时候才去设置路由
let flag = false;
if (item.hidden) {
flag = true;
}
let itemMenu = {
path: item.path,
name: item.name,
hidden: flag,
component: () => import('../views/' + item.component + '.vue')
}
manageRoute.children.push(itemMenu)
} else if (item.children.length) {
item.children.forEach(item => {
let flag = false;
if (item.hidden) {
flag = true;
}
if (item.path) {
let itemMenu = {
path: item.path,
name: item.name,
hidden: flag,
component: () => import('../views/' + item.component + '.vue')
}
manageRoute.children.push(itemMenu)
}
})
}
})
// 动态添加到现在的路由对象中去
router.addRoute(manageRoute)
}
}
}
// 重置我就再set一次路由
setRoutes()
//转成路由
// const menuToRoute = (item) => {
// if (!item.component) {
// return null
// }
// // let route = {
// // name: item.name,
// // path: item.path.replace("/", ""),
// // meta: {
// // icon: item.icon,
// // title: item.title,
// // }
// // }
// // route.component= () => import('../views/' + item.component + '.vue')
// // route.component=()=>import('@/views/'+item.component+'.vue');
// // route.component = () => import('@/views/' + item.component + '.vue')
// let route = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.component + '.vue') }
// return route
// }
// router.beforeEach((to, from, next) => {
// let that = this
// getInfo(store.state.token).then(response => {
// const data = response.data
// if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
// store.commit('SET_ROLES', data.roles)
// }
// const buttonAuthList = []
// menuData = data.permissionList
//
// data.permissionValueList.forEach(button => {
// if (button) {
// buttonAuthList.push(button)
// }
// })
// store.commit('SET_NAME', data.name)
// //commit('SET_AVATAR', data.avatar)
// store.commit('SET_BUTTONS', buttonAuthList)
// }).catch(error => {
// })
// next()
// })
export default router
权限
import router from './router'
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import http from "@/utils/request";
import qs from "qs";
import store from './store'
router.beforeEach(async (to, from, next) => {
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next()
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const response = await store.dispatch('GetInfo')
if (response.code === 20000) {
const data = response.data
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
store.commit('SET_ROLES', data.roles)
}
const buttonAuthList = []
const menuData = data.permissionList
store.commit('setMenuList', menuData)
//权限用户
localStorage.setItem("menus", JSON.stringify(menuData))
data.permissionValueList.forEach(button => {
if (button) {
buttonAuthList.push(button)
}
})
store.commit('SET_NAME', data.name)
//commit('SET_AVATAR', data.avatar)
store.commit('SET_BUTTONS', buttonAuthList)
}
}
}
}
next()
})
mixin
import Vue from "vue"
Vue.mixin({
methods: {
hasAuth(perm) {
var authority = this.$store.state.user.buttons
return authority.indexOf(perm) > -1
}
}
})
security配置
package com.stu.myserver.config;
import com.stu.myserver.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/******************************
* 用途说明: Security配置
* 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
* 创建时间: 2022-07-27 23:16
******************************/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
LoginFailureHandler loginFailureHandler;
@Autowired
LoginSuccessHandler loginSuccessHandler;
@Autowired
CaptchaFilter captchaFilter;
@Autowired
JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
JwtAccessDeniedHandler jwtAccessDeniedHandler;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
JwtLogoutSuccessHandler jwtLogoutSuccessHandler;
@Bean
JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
return jwtAuthenticationFilter;
}
// @Bean
// BCryptPasswordEncoder bCryptPasswordEncoder() {
// return new BCryptPasswordEncoder();
// }
private static final String[] URL_WHITELIST = {
"/user/register",
"/js/**",
"/login",
"/logout",
"/captcha",
"/favicon.ico",
"/login**",
"/login#/login",
"/home/getData",
"captcha/getUserInfo"
};
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable() // 登录配置
.formLogin()
.successHandler(loginSuccessHandler)
.failureHandler(loginFailureHandler)
.and()
.logout()
.logoutSuccessHandler(jwtLogoutSuccessHandler)
// 禁用session
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// 配置拦截规则
.and()
.authorizeRequests()
.antMatchers(URL_WHITELIST).permitAll()
.anyRequest().authenticated()
// 异常处理器
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
// 配置自定义的过滤器
.and()
.addFilter(jwtAuthenticationFilter())
.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
Redis配置
package com.stu.myserver.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/******************************
* 用途说明: redis配置
* 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
* 创建时间: 2022-07-27 23:16
******************************/
@Configuration
public class RedisConfig {
@Bean
RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
}
跨域配置
package com.stu.myserver.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/******************************
* 用途说明: 跨域
* 作者姓名: 公众号:小明的学习圈子 https://www.stucoding.com/
* 创建时间: 2022-07-27 23:16
******************************/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addExposedHeader("Authorization");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
// .allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
PermissionServiceImpl
package com.stu.myserver.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stu.myserver.entity.Permission;
import com.stu.myserver.entity.RolePermission;
import com.stu.myserver.mapper.PermissionMapper;
import com.stu.myserver.service.IPermissionService;
import com.stu.myserver.service.IRolePermissionService;
import com.stu.myserver.service.IUserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.stu.myserver.entity.User;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 权限 服务实现类
* </p>
*
* @author 程序员小明1024
* @since 2023-08-07
*/
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {
@Autowired
private IRolePermissionService rolePermissionService;
@Autowired
private IUserService userService;
/***********************************
* 用途说明:获取全部菜单
* 返回值说明:
* @return List<Permission>
***********************************/
@Override
public List<Permission> listPermissions() {
QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
//把查询的所有菜单用递归的方式生成结构化菜单
return buildPermissions(baseMapper.selectList(queryWrapper));
}
/***********************************
* 用途说明:获取全部菜单
* 返回值说明:
* @return List<Permission>
***********************************/
private List<Permission> buildPermissions(List<Permission> list) {
//创建rootList集合,最终数据封装
List<Permission> rootList = new ArrayList<>();
//遍历所有菜单,得到顶层菜单 pid==0,设置leve =1
for (Permission permission : list) {
//获取顶层菜单,pid=0
if ("0".equals(permission.getPid())) {
//设置level = 1
permission.setLevel(1);
//根据顶层菜单,添加子菜单,封装到rootList
rootList.add(selectChildrenMenu(permission, list));
}
}
return rootList;
}
/***********************************
* 用途说明:递归查询下级菜单
* @param root
* @param list
* 返回值说明:
* @return com.stu.myserver.entity.Permission
***********************************/
private Permission selectChildrenMenu(Permission root, List<Permission> list) {
//因为要往下级菜单房新的菜单,需要初始化
root.setChildren(new ArrayList<Permission>());
//遍历所有菜单,比较当前对象的id和遍历的子菜单的pid是否相同
for (Permission permission : list) {
if (root.getId().equals(permission.getPid())) {
permission.setLevel(root.getLevel() + 1);
//递归,查询出来的子菜单放到父菜单里
root.getChildren().add(selectChildrenMenu(permission, list));
}
}
return root;
}
/***********************************
* 用途说明:查询所有权限菜单
* 返回值说明:
* @return java.util.List<com.stu.service.acl.entity.Permission>
***********************************/
@Override
public List<Permission> ListAllPermissions() {
QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
return bulidPermission(baseMapper.selectList(queryWrapper));
}
/***********************************
* 用途说明:把返回所有菜单list集合进行封装的方法
* @param list
* 返回值说明:
* @return java.util.List<com.stu.service.acl.entity.Permission>
***********************************/
private List<Permission> bulidPermission(List<Permission> list) {
//创建list集合,用于数据最终封装
List<Permission> finalNode = new ArrayList<>();
//把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
for (Permission permission : list) {
//得到顶层菜单 pid=0菜单
if ("0".equals(permission.getPid())) {
permission.setLevel(1);
//根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
finalNode.add(selectChildren(permission, list));
}
}
return finalNode;
}
/***********************************
* 用途说明:递归查询下级菜单
* @param permission
* @param list
* 返回值说明:
* @return com.stu.service.acl.entity.Permission
***********************************/
private Permission selectChildren(Permission permission, List<Permission> list) {
//1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
permission.setChildren(new ArrayList<Permission>());
//2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
for (Permission child : list) {
if (permission.getId().equals(child.getPid())) {
child.setLevel(permission.getLevel() + 1);
if (child.getChildren() == null) {
child.setChildren(new ArrayList<>());
}
// permission.getChildren().add(child);
// selectChildren(child,list);
permission.getChildren().add(selectChildren(child, list));
}
}
return permission;
}
/***********************************
* 用途说明:递归删除菜单
* @param id
* 返回值说明:
* @return boolean
***********************************/
@Override
public boolean removeChildById(String id) {
List<String> idList = new ArrayList<>();
selectChildListById(id, idList);
idList.add(id);
return baseMapper.deleteBatchIds(idList) > 0;
}
/***********************************
* 用途说明:根據角色獲取菜單
* @param id
* 返回值说明:
* @return java.util.List<com.stu.service.acl.entity.Permission>
***********************************/
@Override
public List<Permission> listAllMenu(String id) {
//获取所有菜单
List<Permission> allPermissionList = baseMapper.selectList(new QueryWrapper<>());
//根据角色id呼气角色权限列表
List<RolePermission> rolePermissionsList = rolePermissionService
.list(new QueryWrapper<RolePermission>().eq("role_id", id));
//遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
List<String> permissionIdList = rolePermissionsList.stream().map(e -> e.getPermissionId()).collect(Collectors.toList());
allPermissionList.forEach(permission -> {
if (permissionIdList.contains(permission.getId())) {
permission.setHasSelect(true);
} else {
permission.setHasSelect(false);
}
});
/*for (int i = 0; i < allPermissionList.size(); i++) {
Permission permission = allPermissionList.get(i);
for (int m = 0; m < rolePermissionList.size(); m++) {
RolePermission rolePermission = rolePermissionList.get(m);
if(rolePermission.getPermissionId().equals(permission.getId())) {
permission.setSelect(true);
}
}
}*/
return bulidPermission(allPermissionList);
}
/***********************************
* 用途说明:给角色分配菜单权限
* @param roleId
* @param permissionId
* 返回值说明:
* @return boolean
***********************************/
@Override
public boolean saveRolePermissionrelationShip(String roleId, String[] permissionId) {
//删除旧的权限
boolean ttt = rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));
if (null != permissionId && permissionId.length > 0) {
List<RolePermission> list = new ArrayList<>();
for (String id : permissionId) {
RolePermission rolePermission = new RolePermission();
rolePermission.setRoleId(roleId);
rolePermission.setPermissionId(id);
list.add(rolePermission);
}
return rolePermissionService.saveBatch(list);
}
return true;
}
/***********************************
* 用途说明:根据用户id查询有权限的菜单
* @param id
* 返回值说明:
* @return java.util.List<java.lang.String>
***********************************/
@Override
public List<String> selectPermissionValueListByUserId(String id) {
List<String> list;
if (checkAdmin(id)) {
//如果是超级管理员获取所有权限
list = baseMapper.selectAllPermissionValue();
} else {
//根据用户id查询所有权限
list = baseMapper.selectPermissionValueByUserId(id);
}
return list;
}
/***********************************
* 用途说明:根据用户id查询所有权限的菜单详细列表
* @param userId
* 返回值说明:
* @return java.util.List<org.json.JSONObject>
***********************************/
@Override
public List<JSONObject> selectPermissionByUserId(String userId) {
List<Permission> selectPermissionList = null;
if (checkAdmin(userId)) {
//如果是超级管理员获取所有权限
selectPermissionList = baseMapper.selectList(null);
} else {
//根据用户id查询所有权限
selectPermissionList = baseMapper.selectPermissionByUserId(userId);
}
//先转换成树状
List<Permission> permissionList = bulidPermission(selectPermissionList);
//然后转化成前端需要的格式
List<JSONObject> result = bulidJson(permissionList);
return result;
}
/***********************************
* 用途说明:转化成前端需要的格式
* @param permissionList
* 返回值说明:
* @return java.util.List<org.json.JSONObject>
***********************************/
private List<JSONObject> bulidJson(List<Permission> permissionList) {
List<JSONObject> menus = new ArrayList<>();
if (permissionList.size() == 1) {
Permission topNode = permissionList.get(0);
//组建左侧一级菜单
List<Permission> oneMenuList = topNode.getChildren();
for (Permission one : oneMenuList) {
JSONObject oneMenu = new JSONObject();
oneMenu.put("path", one.getPath());
oneMenu.put("component", one.getComponent());
oneMenu.put("redirect", "noredirect");//第一级不需要重定向
oneMenu.put("name", "name_" + one.getId());
oneMenu.put("title", one.getName());
oneMenu.put("label", one.getName());
oneMenu.put("icon", one.getIcon());
oneMenu.put("hidden", false);//一级不需要因此,3级需要
JSONObject oneMeta = new JSONObject();
oneMeta.put("title", one.getName());
oneMeta.put("icon", one.getIcon());
oneMenu.put("meta", oneMeta);
List<JSONObject> children = new ArrayList<>();
List<Permission> twoMenuList = one.getChildren();//二级菜单
for (Permission two : twoMenuList) {
JSONObject twoMenu = new JSONObject();
twoMenu.put("path", two.getPath());
twoMenu.put("component", two.getComponent());
twoMenu.put("title", two.getName());
twoMenu.put("label", two.getName());
twoMenu.put("icon", two.getIcon());
// twoMenu.put("redirect", "noredirect");//第一级不需要重定向
twoMenu.put("name", "name_" + two.getId());
twoMenu.put("hidden", false);//一级不需要因此,3级需要
JSONObject twoMeta = new JSONObject();
twoMeta.put("title", two.getName());
twoMeta.put("icon", two.getIcon());
twoMenu.put("meta", twoMeta);
children.add(twoMenu);
//功能按钮
List<Permission> threeMenuList = two.getChildren();
for (Permission three : threeMenuList) {
if (StringUtils.isEmpty(three.getPath())) {
continue;
}
JSONObject threeMenu = new JSONObject();
threeMenu.put("path", three.getPath());
threeMenu.put("component", three.getComponent());
// threeMenu.put("redirect", "noredirect");//第一级不需要重定向
threeMenu.put("name", "name_" + three.getId());
threeMenu.put("title", three.getName());
threeMenu.put("label", three.getName());
threeMenu.put("icon", three.getIcon());
threeMenu.put("hidden", true);//一级不需要因此,3级需要
JSONObject threeMeta = new JSONObject();
threeMeta.put("title", three.getName());
threeMeta.put("icon", three.getIcon());
threeMenu.put("meta", threeMeta);
children.add(threeMenu);
}
}
oneMenu.put("children", children);
menus.add(oneMenu);
}
}
return menus;
}
/***********************************
* 用途说明:判断是否管理员
* @param id
* 返回值说明:
* @return boolean
***********************************/
private boolean checkAdmin(String id) {
User user = userService.getById(id);
if (user != null && "admin".equals(user.getUsername())) {
return true;
}
return false;
}
/***********************************
* 用途说明:根据当前菜单id查询他的子子孙孙id,封装到list集合
* @param id
* @param idList
* 返回值说明:
***********************************/
private void selectChildListById(String id, List<String> idList) {
//查询当前菜单的下级
QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("pid", id);
queryWrapper.select("id");
List<Permission> childList = baseMapper.selectList(queryWrapper);
//把childIdList里面菜单id值获取出来,封装idList里面,做递归查询
childList.forEach(item -> {
idList.add(item.getId());
selectChildListById(item.getId(), idList);
});
}
}
IndexServiceImpl
package com.stu.myserver.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.stu.myserver.entity.Role;
import com.stu.myserver.entity.User;
import com.stu.myserver.exception.CustomException;
import com.stu.myserver.service.IPermissionService;
import com.stu.myserver.service.IRoleService;
import com.stu.myserver.service.IUserService;
import com.stu.myserver.service.IndexService;
import com.stu.myserver.utils.ResultCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/******************************
* 用途说明:
* 作者姓名: Administrator
* 创建时间: 2022-09-01 22:34
******************************/
@Service
public class IndexServiceImpl implements IndexService {
@Autowired
private IUserService userService;
@Autowired
private IRoleService roleService;
@Autowired
private IPermissionService permissionService;
@Autowired
private RedisTemplate redisTemplate;
/***********************************
* 用途说明:根据用户明获取用户登录信息
* @param userName
* 返回值说明:
* @return java.util.Map<java.lang.String, java.lang.Object>
***********************************/
@Override
public Map<String, Object> getUserInfo(String userName) {
Map<String, Object> result = new HashMap<>();
User user = userService.selectByUserName(userName);
if (user == null) {
throw new CustomException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
//根据用户id获取角色
List<Role> roleList = roleService.selectRoleByUserId(user.getId());
//转换成角色名称列表
List<String> roleNameList = roleList.stream()
.map(item -> item.getRoleName()).collect(Collectors.toList());
//前端框架必须返回一个角色,否则报错,如果没有角色,返回一个空角色
if (roleNameList.size() == 0) {
roleNameList.add("");
}
List<String> permissionValueList = permissionService.selectPermissionValueListByUserId(user.getId());
redisTemplate.opsForValue().set(userName, permissionValueList);
List<String> permissionValueLisst = (List<String>) redisTemplate.opsForValue().get(userName);
result.put("name", user.getUsername());
result.put("roles", roleNameList);
result.put("permissionValueList", permissionValueList);
return result;
}
/***********************************
* 用途说明:根据用户动态获取菜单
* @param userName
* 返回值说明:
* @return java.util.List<org.json.JSONObject>
***********************************/
@Override
public List<JSONObject> getMenu(String userName) {
User user = userService.selectByUserName(userName);
if (user == null) {
throw new CustomException(ResultCodeEnum.FETCH_USERINFO_ERROR);
}
//根据用户动态获取菜单
return permissionService.selectPermissionByUserId(user.getId());
}
}
RoleServiceImpl
package com.stu.myserver.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stu.myserver.entity.Role;
import com.stu.myserver.entity.UserRole;
import com.stu.myserver.mapper.RoleMapper;
import com.stu.myserver.service.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stu.myserver.service.IUserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author 程序员小明1024
* @since 2023-06-28
*/
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
@Autowired
private IUserRoleService userRoleService;
/***********************************
* 用途说明:根据用户获取角色
* @param userId
* 返回值说明:
* @return java.util.List<com.stu.service.acl.entity.Permission>
***********************************/
@Override
public Map<String, Object> findRoleByUserId(String userId) {
//获取所有角色
List<Role> allRoleList = baseMapper.selectList(new QueryWrapper<>());
//根据用户id获取角色列表
List<UserRole> existUserRoleList = userRoleService
.list(new QueryWrapper<UserRole>().eq("user_id", userId).select("role_id"));
//遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
List<String> existRoleLists = existUserRoleList.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
List<Role> assignRoles = new ArrayList<>();
allRoleList.forEach(role -> {
if (existRoleLists.contains(role.getId())) {
assignRoles.add(role);
}
});
Map<String, Object> roleMap = new HashMap<>();
roleMap.put("assignRoles", assignRoles);
roleMap.put("allRoleList", allRoleList);
return roleMap;
}
/***********************************
* 用途说明:给用户分配角色权限
* @param userId
* @param roleIds
* 返回值说明:
* @return boolean
***********************************/
@Override
public boolean saveUserRelationShip(String userId, String[] roleIds) {
//删除旧的所有角色权限
userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId));
List<UserRole> list = new ArrayList<>();
for (String id : roleIds) {
UserRole rolePermission = new UserRole();
rolePermission.setRoleId(id);
rolePermission.setUserId(userId);
list.add(rolePermission);
}
return userRoleService.saveBatch(list);
}
/***********************************
* 用途说明:根据userid获取用户信息
* @param userId
* 返回值说明:
* @return java.util.List<com.stu.service.acl.entity.Role>
***********************************/
@Override
public List<Role> selectRoleByUserId(String userId) {
//根据用户id获取角色列表
List<UserRole> userRoleList = userRoleService
.list(new QueryWrapper<UserRole>().eq("user_id", userId).select("role_id"));
//遍历所有菜单,获取每一项,看是否在权限列表,如果在,就标记
List<String> roleIdLists = userRoleList.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
List<Role> roleList = new ArrayList<>();
if (roleIdLists.size() > 0) {
roleList = baseMapper.selectBatchIds(roleIdLists);
}
return roleList;
}
}
CodeGenerator
package com.stu.myserver.utils;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.fill.Column;
import java.util.Collections;
/******************************
* 用途说明:
* 作者姓名:公众号:程序员小明1024
* 创建时间: 2023-06-23 14:52
******************************/
public class CodeGenerator {
public static void main(String[] args) {
generate();
}
private static void generate() {
String projectPath = System.getProperty("user.dir");
FastAutoGenerator.create("jdbc:mysql://localhost:3306/2023Java?serverTimezone=Asia/Shanghai", "root", "study")
.globalConfig(builder -> {
builder.author("公众号 小明的学习圈子") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(projectPath + "/src/main/java"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.stu.myserver") // 设置父包名
.moduleName(null) // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mapper")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.entityBuilder().enableLombok()
.addTableFills(new Column("gmt_create", FieldFill.INSERT))
.addTableFills(new Column("gmt_modified", FieldFill.INSERT_UPDATE));;
// builder.mapperBuilder().enableMapperAnnotation().build();
builder.controllerBuilder().enableHyphenStyle() // 开启驼峰转连字符
.enableRestStyle(); // 开启生成@RestController 控制器
builder.addInclude("acl_user_role") // 设置需要生成的表名
.addTablePrefix("acl_", "sys_"); // 设置过滤表前缀
})
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
ResponseUtil
package com.stu.myserver.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/******************************
* 用途说明:需要寫入response的數據
* 作者姓名: Administrator
* 创建时间: 2022-09-01 20:44
******************************/
public class ResponseUtil {
/*这段代码是一个用于在Java Web应用中向客户端发送JSON响应的方法。让我逐行解释其功能:
1. `public static void out(HttpServletResponse response, R r)`:
这是一个公共静态方法,它接受两个参数,一个是`HttpServletResponse`对象,
另一个是泛型`R`的对象`r`。`HttpServletResponse`对象用于设置HTTP响应的状态码、内容类型和写入响应数据。
2. `ObjectMapper mapper = new ObjectMapper();`:在方法内部创建了一个Jackson库
的`ObjectMapper`对象。Jackson库是用于在Java对象和JSON之间进行序列化和反序列化的流行库。
这个`ObjectMapper`对象将用于将`r`对象转换为JSON格式。
3. `response.setStatus(HttpStatus.OK.value());`:设置HTTP响应的状态码为200 OK。这表示请求已成功处理。
4. `response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);`:
设置HTTP响应的内容类型为"application/json;charset=UTF-8",表示响应体将包含JSON数据,并且使用UTF-8字符编码。
5. `mapper.writeValue(response.getWriter(), r);`:使用`ObjectMapper`
将`r`对象序列化为JSON格式,并将其写入`HttpServletResponse`的输出流(通过`response.getWriter()`
获得的输出流)。这样,JSON数据将作为HTTP响应的内容发送给客户端。
总之,这段代码的目的是将一个Java对象`r`序列化为JSON格式,并将其作为HTTP响应的内容发送给客户端,
同时设置响应的状态码和内容类型。这通常用于Web应用程序中的API端点,以便向客户端提供结构化的数据响应。
*/ public static void out(HttpServletResponse response, R r) {
ObjectMapper mapper = new ObjectMapper();
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
try {
mapper.writeValue(response.getWriter(), r);
} catch (IOException e) {
e.printStackTrace();
}
}
}
更多内容阅读原文
GitHub 加速计划 / vu / vue
83
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
9e887079
[skip ci] 3 个月前
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
更多推荐
已为社区贡献9条内容
所有评论(0)