SpringBoot+VUE实战项目-后台管理系统

背景

笔记为学习青戈大佬 从0开始带你手撸一套SpringBoot+Vue后台管理系统(2022年最新版)所总结笔记,瑞斯拜~

软件安装

项目所使用软件及版本如↓

软件包自取:

链接: https://pan.baidu.com/s/10UEXF10CuMSA8zFNrLBYBw?pwd=rb9d 提取码: rb9d

vue安装

还需要安装vue-cli(==这里和视频版本不一致,有问题检查版本==),教程戳vue-cli(vue脚手架)安装 详细教程

抄作业,步骤如下:

(1)命令行工具输入

1
npm install webpack -g

安装完成后输入

1
webpack -v

检查

(2)命令行输入

1
npm install --global vue-cli

安装完成后输入

1
vue -V

检查

tips:项目中根目录依据所建项目文件夹灵活变动,不一定和该文章保持完全一致

在F:/代码/后台管理系统 下新建vue项目

1
vue create vue

设置属性如下图,版本选择2.X,接下来分别选择Y→json→n

创建完毕:

idea打开刚新建项目vue

命令行中在F:/代码/后台管理系统/vue 下执行

1
npm run serve

本地访问 http://localhost:8080/能够访问到刚刚构建的前端项目

element框架安装

项目中后台管理系统使用element框架

element官方安装教程

F:/代码/后台管理系统/vue 下执行

1
npm i element-ui -S

安装完成后依据Quick Start指引

在main.js下引入element

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false
Vue.use(ElementUI, {size: "small"});

new Vue({
router,
render: h => h(App)
}).$mount('#app')

HomeView.vue下进行test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div class="home">
<el-button>{{msg}}</el-button>
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'HomeView',
components: {
HelloWorld
},
data(){
return{
msg: "Hello Sliu"
}
}
}
</script>

前端页面修改

前端页面的编写快速带过,静态资源github自取

第一部分

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false

Vue.use(ElementUI, { size: "small" });

new Vue({
router,
render: h => h(App)
}).$mount('#app')

Home.vu(第一节)

1
2
3
4
5
6
7
8
9
10
11
12
13
 <el-button type="danger">{{ msg }}</el-button>

export default {
name: 'Home',
components: {
HelloWorld
},
data() {
return {
msg: "hello 青哥哥"
}
}
}

第二部分

Home.vue(第二节)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<template>
<div>
<el-container>
<el-aside width="200px" style="background-color: rgb(238, 241, 246);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>导航二</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>导航三</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>

<el-container>

<el-header style="text-align: right; font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>

<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>

</el-container>
</el-container>
</div>
</template>

<script>

export default {
name: 'Home',
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(20).fill(item),
msg: "hello 青哥哥"
}
}
}
</script>

App.vue(第二节)

1
2
3
4
5
6
7
8
9
10
11
<template>
<div id="app">
<router-view/>
</div>
</template>

<style>
#app{
min-height: 100vh;
}
</style>

gloable.css

1
2
3
4
5
html,body,div{
margin: 0;
padding: 0;
box-sizing: border-box;
}

在main.js 引入:import './assets/gloable.css'

第三部分

gloable.css

1
2
3
4
5
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}

App.vue

1
2
3
4
5
<template>
<div id="app">
<router-view/>
</div>
</template>

Home.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<template>
<el-container style="min-height: 100vh">
<el-aside :width="sideWidth + 'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48, 65, 86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px; line-height: 60px; text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px; position: relative; top: 5px; margin-right: 5px">
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>

<el-container>

<el-header style="font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px; display: flex">
<div style="flex: 1; font-size: 20px">
<span :class="collapseBtnClass" style="cursor: pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

</el-header>

<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>

</el-container>
</el-container>
</template>

<script>

export default {
name: 'Home',
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item),
msg: "hello 青哥哥",
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true
}
},
methods: {
collapse() { // 点击收缩按钮触发
this.isCollapse = !this.isCollapse
if (this.isCollapse) { // 收缩
this.sideWidth = 64
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
} else { // 展开
this.sideWidth = 200
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
}
}
}
</script>

第四部分

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import './assets/gloable.css'

Vue.config.productionTip = false

Vue.use(ElementUI, { size: "mini" });

new Vue({
router,
render: h => h(App)
}).$mount('#app')

gloable.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}

.ml-5 {
margin-left: 5px;
}
.mr-5 {
margin-right: 5px;
}
.pd-10 {
padding: 10px 0;
}

Home.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<template>
<el-container style="min-height: 100vh">

<el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 35%);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48, 65, 86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px; line-height: 60px; text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px; position: relative; top: 5px; right: 5px">
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>

<el-container>
<el-header style="font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px; display: flex">
<div style="flex: 1; font-size: 20px">
<span :class="collapseBtnClass" style="cursor: pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown" >
<el-dropdown-item style="font-size: 14px; padding: 5px 0">个人信息</el-dropdown-item>
<el-dropdown-item style="font-size: 14px; padding: 5px 0">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

</el-header>

<el-main>
<div style="margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>

<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search"></el-input>
<el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5"></el-input>
<el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>

<div style="margin: 10px 0">
<el-button type="primary">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger">批量删除 <i class="el-icon-remove-outline"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-bottom"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-top"></i></el-button>
</div>

<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="success">编辑 <i class="el-icon-edit"></i></el-button>
<el-button type="danger">删除 <i class="el-icon-remove-outline"></i></el-button>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination

:page-sizes="[5, 10, 15, 20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</el-main>

</el-container>
</el-container>
</template>

<script>

export default {
name: 'Home',
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(10).fill(item),
msg: "hello 青哥哥",
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
headerBg: 'headerBg'
}
},
methods: {
collapse() { // 点击收缩按钮触发
this.isCollapse = !this.isCollapse
if (this.isCollapse) { // 收缩
this.sideWidth = 64
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
} else { // 展开
this.sideWidth = 200
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
}
}
}
</script>

<style>
.headerBg {
background: #eee!important;
}
</style>

效果图

SpringBoot框架搭建

新建spring项目

导入插件

application.properties下配置数据源

1
2
3
4
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2b8
spring.datasource.username=root
spring.datasource.password=123456

打开Navicat新建数据库sliu(数据库名随意,无须保持一致)

修改application.properties数据源

1
spring.datasource.url=jdbc:mysql://localhost:3306/sliu?serverTimezone=GMT%2b8

由于前端页面下,构建vue项目时所使用端口号也是8080,在application.properties下修改spring项目端口号为9090,以避免冲突

1
server.port=9090

添加vue的启动方式

配置完成后前后端项目能够实现同时启动

SpringBoot集成Mybatis

application.properties中存在大量重复项,新建application.yaml替换它

1
2
3
4
5
6
7
8
9
server:
port: 9090

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sliu?serverTimezone=GMT%2b8
username: root
password: 123456

新建user表用于测试数据库连接

表字段如下:

其中create_time默认值设置为CURRENT_TIMESTAMP

新增列

新建一个entity目录,该目录下用于封装实体类,新建User类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.sliu.springboot.entity;

import javax.xml.crypto.Data;

/**
* @PackageName:com.sliu.springboot.entity
* @ClassName:User
* @Description:
* @author:sliu
* @data 2022/5/29 15:24
*/

@lombok.Data
public class User {
private Integer id;
private String username;
private String password;
private String nickname;
private String email;
private String phone;
private String address;
private Data createTime;
}

新建mapper目录,该目录下保存数据库访问接口,新建UserMapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();
}

其中@Mapper接口用于将接口注入到容器中,用于完成后续自动注入

新建controller文件夹,该文件夹用于处理前台发送的请求。新建UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/
@RestController
public class UserController {

@Autowired
UserMapper userMapper;

@GetMapping("/")
public List<User> printAllUser(){
return userMapper.findAllUser();
}
}

修改SpringbootApplication用于测试数据库查询是否成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.sliu.springboot;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@SpringBootApplication
public class SpringbootApplication {
@Autowired
private UserMapper userMapper;

public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}

@GetMapping("/")
public List<User> toIndex(){
return userMapper.findAllUser();
}

}

修改SpringbootApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.sliu.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}

rebuild项目,访问http://localhost:9090

SpringBoot增删改查

通常,查询数据库使用get请求,而对于数据库的修改,例如增删改使用post请求

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@PostMapping
public Integer save(@RequestBody User user){
return userMapper.insertUser(user);
}

@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

}

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);
}

rebuild项目

打开postman,发送post请求用于测试

继续改进UserController,当前save()方法下仅能够实现插入一条新数据,实际应用场景下,应当先判断该条id的数据在数据库中是否以及存在。不存在时插入,存在时应当执行的是更新操作。

新建service文件夹,存放业务逻辑操作,并将操作完成的数据返回给view层,展现给用户。新建UserService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.sliu.springboot.service;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
* @PackageName:com.sliu.springboot.service
* @ClassName:UserService
* @Description:
* @author:sliu
* @data 2022/5/29 16:41
*/
@Service
public class UserService {
@Autowired
UserMapper userMapper;

public int save(User user){
//传入user无id,表示为新增
if(user.getId() == null){
return userMapper.insertUser(user);
}else {//否则更新
return userMapper.updateUser(user);
}
}
}

修改UserMapper,新增update方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

@Update("update user set username=#{username}, password=#{password}, nickname=#{nickname}, email=#{email}, " +
"phone=#{phone}, address=#{address} where id=#{id}")
int updateUser(User user);
}

修改UserController中save方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@Autowired
UserService userService;

@PostMapping
public Integer save(@RequestBody User user){
return userService.save(user);
}

@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

}

rebuild项目并利用postman发送请求,测试

这样存在的问题是,在执行更新操作时,update SQL语句下更新的是全部字段,当仅仅想要修改数据库的一个字段时,需要传入所有的实体类字段,否则会将其它字段全部置为Null(例如欲修改用户jjwang的邮箱时,post请求仅仅传入一个email字段,那么其它字段会全部置为Null)

动态SQL就用于解决该类问题

安装MyBatisX插件

在resources文件夹下新建mapper/User.xml用于封装动态数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sliu.springboot.mapper.UserMapper">
<update id="updateUser">
update user
<set>
<if test="username != null">
username=#{username},
</if>
<if test="password != null">
password=#{password},
</if>
<if test="nickname != null">
nickname=#{nickname},
</if>
<if test="email != null">
email=#{email},
</if>
<if test="phone != null">
phone=#{phone},
</if>
<if test="address != null">
address=#{address}
</if>
</set>
<where>
id=#{id}
</where>
</update>
</mapper>

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

int updateUser(User user);
}

application.yml文件下引入该mapper,同时配置打印日志

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 9090

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sliu?serverTimezone=GMT%2b8
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

rebuild项目,postman下进行test

CRUD还有删除没有实现

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@Autowired
UserService userService;

//新增和修改User
@PostMapping
public Integer save(@RequestBody User user){
return userService.save(user);
}

//查询全部User
@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

//依据id删除User
@DeleteMapping("/{id}")
public Integer deleteUserById(@PathVariable Integer id){
return userMapper.deleteUserById(id);
}

}

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

int updateUser(User user);

@Delete("delete from user where id=#{id}")
int deleteUserById(@Param("id") Integer id);
}

rebuild项目,postman下进行test

SpringBoot实现分页查询

分页查询的实质就是利用SQL语句中Limit关键字完成对数据的分割查询,以一个简单的例子入手

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@Autowired
UserService userService;

//新增和修改User
@PostMapping
public Integer save(@RequestBody User user){
return userService.save(user);
}

//查询全部User
@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

//依据id删除User
@DeleteMapping("/{id}")
public Integer deleteUserById(@PathVariable Integer id){
return userMapper.deleteUserById(id);
}

//分页查询打印所有user信息,pageNum为页码数,pageSize为每页展示数据
@GetMapping("/page")
public List<User> printUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize){
pageNum = (pageNum - 1) * pageSize;
return userMapper.printUserByPage(pageNum, pageSize);
}

}

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {
//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

int updateUser(User user);

@Delete("delete from user where id=#{id}")
Integer deleteUserById(@Param("id") Integer id);

@Select("SELECT * from user limit #{pageNum}, #{pageSize}")
List<User> printUserByPage(Integer pageNum, Integer pageSize);
}

rebuild项目,postman下进行test

除了依据PageNum和PageSize返回所对应页码的数据,还应当获取当前表格下全部数据条数,以便于通过计算得到总页数。以Map结构同时保存数据data,和总数据条数totalNum

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@Autowired
UserService userService;

//新增和修改User
@PostMapping
public Integer save(@RequestBody User user){
return userService.save(user);
}

//查询全部User
@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

//依据id删除User
@DeleteMapping("/{id}")
public Integer deleteUserById(@PathVariable Integer id){
return userMapper.deleteUserById(id);
}

//分页查询打印所有user信息,pageNum为页码数,pageSize为每页展示数据
@GetMapping("/page")
public Map<String, Object> printUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize){
pageNum = (pageNum - 1) * pageSize;
List<User> data = userMapper.printUserByPage(pageNum, pageSize);
Integer totalUserNum = userMapper.selectTotal();
Map<String, Object> res = new HashMap<>();
res.put("data", userMapper.printUserByPage(pageNum, pageSize));
res.put("total", totalUserNum);
return res;
}

}

修改userMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {


//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

//插入一条数据
@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

//更新数据
int updateUser(User user);

//删除数据
@Delete("delete from user where id=#{id}")
Integer deleteUserById(@Param("id") Integer id);

//分页查询
@Select("SELECT * from user limit #{pageNum}, #{pageSize}")
List<User> printUserByPage(Integer pageNum, Integer pageSize);

//获取数据库中总数据条数
@Select("SELECT count(*) from user")
Integer selectTotal();
}

rebuild项目,postman下test,此时返回数据中包含有数据库总条数的信息

前端页面项目部署在8080端口,而后台服务则在9090端口,当前端页面要获取后台数据用于展示时,会出现跨域问题

SpringBoot项目下新建config文件夹,新建CorsConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.sliu.springboot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
* @PackageName:com.sliu.springboot.config
* @ClassName:CorsConfig
* @Description:
* @author:sliu
* @data 2022/5/31 15:37
*/
@Configuration
public class CorsConfig {

//当前跨域请求最大有效时长,默认一天
private static final long MAX_AGE = 24 * 60 * 60;

@Bean
public CorsFilter corsFilter(){
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://localhost:8080"); //1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); //2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); //3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration); //4 对接口配置跨域设置
return new CorsFilter(source);
}
}

User下对password属性添加注解,防止密码外泄

1
2
3
4
5
6
7
8
9
10
11
12
@lombok.Data
public class User {
private Integer id;
private String username;
@JsonIgnore
private String password;
private String nickname;
private String email;
private String phone;
private String address;
private Data createTime;
}

将数据渲染到前端页面Home.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<template>
<el-container style="min-height: 100vh">

<el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 35%);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48, 65, 86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px; line-height: 60px; text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px; position: relative; top: 5px; right: 5px">
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>

<el-container>
<el-header style="font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px; display: flex">
<div style="flex: 1; font-size: 20px">
<span :class="collapseBtnClass" style="cursor: pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item style="font-size: 14px; padding: 5px 0">个人信息</el-dropdown-item>
<el-dropdown-item style="font-size: 14px; padding: 5px 0">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

</el-header>

<el-main>
<div style="margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>

<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search"></el-input>
<el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5"></el-input>
<el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5"></el-input>
<el-button class="ml-5" type="primary">搜索</el-button>
</div>

<div style="margin: 10px 0">
<el-button type="primary">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger">批量删除 <i class="el-icon-remove-outline"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-bottom"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-top"></i></el-button>
</div>

<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="id" label="ID" width="80">
</el-table-column>
<el-table-column prop="username" label="用户名" width="140">
</el-table-column>
<el-table-column prop="nickname" label="昵称" width="120">
</el-table-column>
<el-table-column prop="email" label="邮箱">
</el-table-column>
<el-table-column prop="phone" label="电话">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="success">编辑 <i class="el-icon-edit"></i></el-button>
<el-button type="danger">删除 <i class="el-icon-remove-outline"></i></el-button>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-main>

</el-container>
</el-container>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data() {
return {
tableData: [],
total: 0,
pageNum: 1,
pageSize: 2,
msg: "hello sliu",
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
headerBg: 'headerBg'
}
},
created() {
//请求分页查询数据
fetch( "http://localhost:9090/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize)
.then(res => res.json()).then(res => {
console.log(res)
this.tableData=res.data
this.total=res.total
})
},
methods: {
collapse() { // 点击收缩按钮触发
this.isCollapse = !this.isCollapse
if (this.isCollapse) { // 收缩
this.sideWidth = 64
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
} else { // 展开
this.sideWidth = 200
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
},
load(){
fetch( "http://localhost:9090/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize)
.then(res => res.json()).then(res => {
console.log(res)
this.tableData=res.data
this.total=res.total
})
},
handleSizeChange(pageSize){
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum){
console.log(pageNum)
this.pageNum = pageNum
this.load()
}
}
}
</script>

<style>
.headerBg {
background: #eee !important;
}
</style>

rebuild前后端项目,访问localhost:8080,搞定√

基于以上查询实现以username的模糊查询

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.sliu.springboot.controller;

import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserMapper userMapper;

@Autowired
UserService userService;

//新增和修改User
@PostMapping
public Integer save(@RequestBody User user){
return userService.save(user);
}

//查询全部User
@GetMapping
public List<User> printAllUser(){
return userMapper.findAllUser();
}

//依据id删除User
@DeleteMapping("/{id}")
public Integer deleteUserById(@PathVariable Integer id){
return userMapper.deleteUserById(id);
}

//分页查询打印所有user信息,pageNum为页码数,pageSize为每页展示数据
@GetMapping("/page")
public Map<String, Object> printUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
@RequestParam String username){
pageNum = (pageNum - 1) * pageSize;
List<User> data = userMapper.printUserByPage(pageNum, pageSize, username);
Integer totalUserNum = userMapper.selectTotal(username);
Map<String, Object> res = new HashMap<>();
res.put("data", data);
res.put("total", totalUserNum);
return res;
}

}

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

@Mapper
public interface UserMapper {


//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

//插入一条数据
@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

//更新数据
int updateUser(User user);

//删除数据
@Delete("delete from user where id=#{id}")
Integer deleteUserById(@Param("id") Integer id);

//分页查询
@Select("SELECT * from user where username like concat('%', #{username}, '%') limit #{pageNum}, #{pageSize}")
List<User> printUserByPage(Integer pageNum, Integer pageSize, String username);

//获取数据库中总数据条数
@Select("SELECT count(*) from user where username like concat('%', #{username}, '%')")
Integer selectTotal(String username);
}

rebuild项目,postman下进行test

渲染到前端页面Home.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<template>
<el-container style="min-height: 100vh">

<el-aside :width="sideWidth + 'px'" style="box-shadow: 2px 0 6px rgb(0 21 41 / 35%);">
<el-menu :default-openeds="['1', '3']" style="min-height: 100%; overflow-x: hidden"
background-color="rgb(48, 65, 86)"
text-color="#fff"
active-text-color="#ffd04b"
:collapse-transition="false"
:collapse="isCollapse"
>
<div style="height: 60px; line-height: 60px; text-align: center">
<img src="../assets/logo.png" alt="" style="width: 20px; position: relative; top: 5px; right: 5px">
<b style="color: white" v-show="logoTextShow">后台管理系统</b>
</div>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-message"></i>
<span slot="title">导航一</span>
</template>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</template>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</template>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>

<el-container>
<el-header style="font-size: 12px; border-bottom: 1px solid #ccc; line-height: 60px; display: flex">
<div style="flex: 1; font-size: 20px">
<span :class="collapseBtnClass" style="cursor: pointer" @click="collapse"></span>
</div>
<el-dropdown style="width: 70px; cursor: pointer">
<span>王小虎</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item style="font-size: 14px; padding: 5px 0">个人信息</el-dropdown-item>
<el-dropdown-item style="font-size: 14px; padding: 5px 0">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

</el-header>

<el-main>
<div style="margin-bottom: 30px">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>用户管理</el-breadcrumb-item>
</el-breadcrumb>
</div>

<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="username"></el-input>
<!-- <el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5"></el-input>-->
<!-- <el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5"></el-input>-->
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
</div>

<div style="margin: 10px 0">
<el-button type="primary">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-button type="danger">批量删除 <i class="el-icon-remove-outline"></i></el-button>
<el-button type="primary">导入 <i class="el-icon-bottom"></i></el-button>
<el-button type="primary">导出 <i class="el-icon-top"></i></el-button>
</div>

<el-table :data="tableData" border stripe :header-cell-class-name="headerBg">
<el-table-column prop="id" label="ID" width="80">
</el-table-column>
<el-table-column prop="username" label="用户名" width="140">
</el-table-column>
<el-table-column prop="nickname" label="昵称" width="120">
</el-table-column>
<el-table-column prop="email" label="邮箱">
</el-table-column>
<el-table-column prop="phone" label="电话">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="success">编辑 <i class="el-icon-edit"></i></el-button>
<el-button type="danger">删除 <i class="el-icon-remove-outline"></i></el-button>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-main>

</el-container>
</el-container>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
name: 'Home',
data() {
return {
tableData: [],
username: "",
total: 0,
pageNum: 1,
pageSize: 2,
msg: "hello sliu",
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
headerBg: 'headerBg'
}
},
created() {
//请求分页查询数据
fetch( "http://localhost:9090/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize+"&username="+this.username)
.then(res => res.json()).then(res => {
console.log(res)
this.tableData=res.data
this.total=res.total
})
},
methods: {
collapse() { // 点击收缩按钮触发
this.isCollapse = !this.isCollapse
if (this.isCollapse) { // 收缩
this.sideWidth = 64
this.collapseBtnClass = 'el-icon-s-unfold'
this.logoTextShow = false
} else { // 展开
this.sideWidth = 200
this.collapseBtnClass = 'el-icon-s-fold'
this.logoTextShow = true
}
},
load(){
fetch( "http://localhost:9090/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize+"&username="+this.username)
.then(res => res.json()).then(res => {
console.log(res)
this.tableData=res.data
this.total=res.total
})
},
handleSizeChange(pageSize){
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum){
console.log(pageNum)
this.pageNum = pageNum
this.load()
}
}
}
</script>

<style>
.headerBg {
background: #eee !important;
}
</style>

访问localhost:8080

SpringBoot集成Mybatis-plus

利用Mybatis-plus实现分页查询

pom.xml下导入Mybatis-plus依赖

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>

application.yaml下修改Mybatis-plus日志打印方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server:
port: 9090

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sliu?serverTimezone=GMT%2b8
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

config文件夹下新建MybatisPlusConfig用于接管mapper注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.sliu.springboot.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.sliu.springboot.mapper")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

删除UserMapper上@mapper注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.sliu.springboot.mapper;

import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

//@Mapper
public interface UserMapper {


//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

//插入一条数据
@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

//更新数据
int updateUser(User user);

//删除数据
@Delete("delete from user where id=#{id}")
Integer deleteUserById(@Param("id") Integer id);

//分页查询
@Select("SELECT * from user where username like concat('%', #{username}, '%') limit #{pageNum}, #{pageSize}")
List<User> printUserByPage(Integer pageNum, Integer pageSize, String username);

//获取数据库中总数据条数
@Select("SELECT count(*) from user where username like concat('%', #{username}, '%')")
Integer selectTotal(String username);
}

rebuild项目,postman下进行test

使用mybatis_plus简化数据库crud

修改UserMapper继承BaseMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.sliu.springboot.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

//@Mapper
public interface UserMapper extends BaseMapper<User> {


//查询User表中所有数据
@Select("SELECT * from user")
List<User> findAllUser();

//插入一条数据
@Insert("Insert into user(username, password, nickname, email, phone, address) " +
"VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
int insertUser(User user);

//更新数据
int updateUser(User user);

//删除数据
@Delete("delete from user where id=#{id}")
Integer deleteUserById(@Param("id") Integer id);

//分页查询
@Select("SELECT * from user where username like concat('%', #{username}, '%') limit #{pageNum}, #{pageSize}")
List<User> printUserByPage(Integer pageNum, Integer pageSize, String username);

//获取数据库中总数据条数
@Select("SELECT count(*) from user where username like concat('%', #{username}, '%')")
Integer selectTotal(String username);
}

修改UserService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.sliu.springboot.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import org.springframework.stereotype.Service;

/**
* @PackageName:com.sliu.springboot.service
* @ClassName:UserService
* @Description:
* @author:sliu
* @data 2022/5/29 16:41
*/
@Service
public class UserService extends ServiceImpl<UserMapper, User> {

public boolean saveUser(User user){
return saveOrUpdate(user);
}
// @Autowired
// UserMapper userMapper;
//
// public int save(User user){
// //传入user无id,表示为新增
// if(user.getId() == null){
// return userMapper.insertUser(user);
// }else {//否则更新
// return userMapper.updateUser(user);
// }
// }
}

修改User类指定表名和列名,同时在数据库user表中新增一个字段avatar_url用于测试指定数据库列名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.sliu.springboot.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.xml.crypto.Data;

/**
* @PackageName:com.sliu.springboot.entity
* @ClassName:User
* @Description:
* @author:sliu
* @data 2022/5/29 15:24
*/

@lombok.Data
@TableName(value = "user")//指定数据库表名
public class User {
//指定数据库主键
@TableId(value = "id")
private Integer id;
private String username;
@JsonIgnore
private String password;
private String nickname;
private String email;
private String phone;
private String address;
private Data createTime;
@TableField(value = "avatar_url")//指定数据库列名
private String avatar;
}

rebuild项目,postman下进行测试

SpringBoot集成SwaggerUI

通过postman进行数据请求的测试比较麻烦,整合Swagger简化测试流程

pom.xml下导入依赖

1
2
3
4
5
6
<!-- 引入Swagger3依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

config文件夹下新建swaggerConfig配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.sliu.springboot.config;

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.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
* @PackageName:com.sliu.springboot.config
* @ClassName:SwaggerConfig
* @Description:
* @author:sliu
* @data 2022/6/10 21:17
*/
/**
* Swagger配置类
*/
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket docket(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo()).enable(true)
.select()
//apis: 添加swagger接口提取范围
.apis(RequestHandlerSelectors.basePackage("com.sliu.springboot.controller"))
//.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}

private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("sliu的项目接口文档")
.description("项目接口测试")
.contact(new Contact("sliu", "https://shunliu.xyz", "shunliu@csu.edu.cn"))
.version("1.0")
.build();
}
}

rebuild项目,访问localhost:9090/swagger-ui/index.html

继续改造UserMapper中数据操作,全部替换为mybatis-plus实现

修改UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.sliu.springboot.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sliu.springboot.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
* @PackageName:com.sliu.springboot.mapper
* @ClassName:UserMapper
* @Description:
* @author:sliu
* @data 2022/5/29 15:31
*/

//@Mapper
public interface UserMapper extends BaseMapper<User> {


// //查询User表中所有数据
// @Select("SELECT * from user")
// List<User> findAllUser();
//
// //插入一条数据
// @Insert("Insert into user(username, password, nickname, email, phone, address) " +
// "VALUES(#{username}, #{password}, #{nickname}, #{email}, #{phone}, #{address})")
// int insertUser(User user);
//
// //更新数据
// int updateUser(User user);
//
// //删除数据
// @Delete("delete from user where id=#{id}")
// Integer deleteUserById(@Param("id") Integer id);
//
// //分页查询
// @Select("SELECT * from user where username like concat('%', #{username}, '%') limit #{pageNum}, #{pageSize}")
// List<User> printUserByPage(Integer pageNum, Integer pageSize, String username);
//
// //获取数据库中总数据条数
// @Select("SELECT count(*) from user where username like concat('%', #{username}, '%')")
// Integer selectTotal(String username);
}

修改UserController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.sliu.springboot.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sliu.springboot.entity.User;
import com.sliu.springboot.mapper.UserMapper;
import com.sliu.springboot.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @PackageName:com.sliu.springboot.controller
* @ClassName:UserController
* @Description:
* @author:sliu
* @data 2022/5/29 15:46
*/
//@Api(tags="用户管理")
@RestController
@RequestMapping("/user")
public class UserController {

// @Autowired
// UserMapper userMapper;

@Autowired
UserService userService;

//新增和修改User
@PostMapping
public boolean save(@RequestBody User user){
return userService.saveUser(user);
}

//查询全部User
// @ApiOperation("用户列表")
@GetMapping
public List<User> printAllUser(){
return userService.list();
}

//依据id删除User
@DeleteMapping("/{id}")
public boolean deleteUserById(@PathVariable Integer id){
return userService.removeById(id);
}

//分页查询打印所有user信息,pageNum为页码数,pageSize为每页展示数据
// @GetMapping("/page")
// public Map<String, Object> printUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
// @RequestParam String username){
// pageNum = (pageNum - 1) * pageSize;
// List<User> data = userMapper.printUserByPage(pageNum, pageSize, username);
// Integer totalUserNum = userMapper.selectTotal(username);
// Map<String, Object> res = new HashMap<>();
// res.put("data", data);
// res.put("total", totalUserNum);
// return res;
// }
//mybatis-plus实现分页查询
@GetMapping("/page")
public IPage<User> printUserByPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
@RequestParam(defaultValue = "") String username,
@RequestParam(defaultValue = "") String nickname,
@RequestParam(defaultValue = "") String address){
IPage<User> page = new Page<>(pageNum, pageSize);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(!Strings.isEmpty(username),"username", username);
queryWrapper.like(!Strings.isEmpty(nickname),"nickname", nickname);
queryWrapper.like(!Strings.isEmpty(address),"address", address);
return userService.page(page, queryWrapper);
}
}

rebuild项目,swagger下进行test

Coming soon......