前言
这一章就是在上一章提到的的简易后台管理系统的后端部分了,学习!冲冲冲!
创建SpringBoot工程
创建一个Module:
选择Spring initializr
配置好这些东西,点击next:
选择我们需要的jar包依赖:
给这个Module取个名字,我们就叫springboot好了,点击finish:
可以看到,此时已经创建完了springboot项目:
准备一下数据库(其中id为主键自增):
第一件事情需要做的就是我们的前端Vue默认的端口是8080,后端springboot默认的也是8080,所以我们需要改一下后端的端口号在application.yml中:
在主程序中启动运行springboot项目,访问9090端口可以看到:
说明正常。
然后我们在程序包下创建一个common类,这个包作为我们常用的配置类;对了,还要用到mybatis-plus,引入一下mp的依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
然后在common包下写上我们的第一个分页配置的类:MybatisPlusConfig
然后在这个包下再写一个Result的配置类,这个类的作用就是返回给前台数据的一个包装类,因为后台返回给前台的数据一般都是json格式,json里面会包含这么几个数据,一个是code,code告诉前台这次返回的数据呢是成功还是失败,如果失败呢code就不会是0,因为我们定义的0是成功,非0则是失败;还有一个就是msg,这个就是告知前台每个码对应的成功或者失败的信息,data则就是拿来包装各种类型的信息。
package com.why.demo.common;
public class Result<T> {
private String code;
private String msg;
private T data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Result(){
}
public Result(T data) {
this.data = data;
}
public static Result success(){
Result result = new Result<>();
result.setCode("0");
result.setMsg("成功");
return result;
}
public static <T> Result<T> success(T data){
Result<T> result = new Result<>(data);
result.setCode("0");
result.setMsg("成功");
return result;
}
public static Result error(String code,String msg){
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
return result;
}
}
然后我们需要在MybatisPlusConfig这个配置类中加上包扫描,专门扫描另一个包(mapper,同样创建在demo包下)下的东西:
创建一个web层的controller包,位于demo包下,并写上一个UserController的控制类:
这个时候因为新增的用户数据是从前台通过json字符串格式传过来的,所以必然要先转化为一个实体才能封装到我们后台的数据库当中,所以我们还需要创建一个实体包entity,在包中写上User对应数据库中的数据表的字段:
现在我们可以返回去写我们的controller层的东西了:
现在我们要做的就是将上传过来的数据插入数据库了,依然使用Mp的一些语法操作,先定义一个UserMapper接口继承BaseMapper:
然后我们就可以使用Mp为我们准备的CRUD的操作了:
现在后台的一个接口就已经写好了,我们接下来就去前台进行相应的配置。因为前台的Home.vue中还有很多杂乱的数据,所以我们先整理一下,让其变成我们需要的样子:
<template>
<!--padding设置一点内边距-->
<div style="padding: 10px">
<!--功能区域-->
<div style="margin: 10px 0">
<el-button type="primary">新增</el-button>
<el-button type="primary">导入</el-button>
<el-button type="primary">导出</el-button>
</div>
<!--搜索区域-->
<div style="margin: 10px 0">
<el-input v-model="search" placeholder="请输入关键字" style="width: 20%"/>
<el-button type="primary" style="margin-left: 5px">搜索</el-button>
</div>
<!--后面的width可以不写,浏览器会自适应
stripe是斑马纹效果-->
<el-table :data="tableData" border stripe style="width: 100%">
<!--sortable让日期排序-->
<el-table-column prop="id" label="ID" sortable/>
<el-table-column prop="username" label="用户名"/>
<el-table-column prop="nickName" label="昵称" />
<el-table-column prop="age" label="年龄"/>
<el-table-column prop="sex" label="性别"/>
<el-table-column prop="address" label="地址"/>
<el-table-column fixed="right" label="操作">
<template #default="scope">
<el-button size="mini" @click="handleEdit(scope.$index,scope.row)">编辑</el-button>
<!--弹出消息确认框-->
<el-popconfirm
confirm-button-text="是的,没错"
cancel-button-text="妈的,我再想想"
icon="el-icon-info"
icon-color="red"
title="确定删除吗?">
<template #reference>
<el-button size="mini" type="danger" @click="handleDelete(scope.$index,scope.row)">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--分页功能区域-->
<div style="margin: 10px 0">
<el-pagination
v-model:currentPage="currentPage4"
:page-sizes="[5,10,20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange">
</el-pagination>
</div>
</div>
</template>
<script>
export default {
name: 'Home',
components: {
},
data() {
return {
search: '',
//当前页
currentPage4: 1,
total: 10,
tableData: [
],
}
},
methods: {
handleEdit(){
},
handleDelete(){
},
handleSizeChange(){
// 改变页码时触发函数
},
handleCurrentChange(){
// 当前页改变时触发代码
}
}
}
</script>
此时访问:
现在整理完之后,我们去写刚刚在后台写的用户插入接口对应的前台需要执行的操作。首先为“新增”按钮绑定事件add:
<el-button type="primary" @click="add">新增</el-button>
然后在下面的方法区写上add:
新增时我们应该需要有一个弹窗,新增的操作就放在这个弹窗里面,也就是录入数据,依旧是老方法去copy样式,然后放进来就行了。调试这个的过程也很繁杂,所以我直接贴出源码了,反正调到最后自己满意了的就行:
<template>
<!--padding设置一点内边距-->
<div style="padding: 10px">
<!--功能区域-->
<div style="margin: 10px 0">
<el-button type="primary" @click="add">新增</el-button>
<el-button type="primary">导入</el-button>
<el-button type="primary">导出</el-button>
</div>
<!--搜索区域-->
<div style="margin: 10px 0">
<el-input v-model="search" placeholder="请输入关键字" style="width: 20%"/>
<el-button type="primary" style="margin-left: 5px">搜索</el-button>
</div>
<!--后面的width可以不写,浏览器会自适应
stripe是斑马纹效果-->
<el-table :data="tableData" border stripe style="width: 100%">
<!--sortable让日期排序-->
<el-table-column prop="id" label="ID" sortable/>
<el-table-column prop="username" label="用户名"/>
<el-table-column prop="nickName" label="昵称" />
<el-table-column prop="age" label="年龄"/>
<el-table-column prop="sex" label="性别"/>
<el-table-column prop="address" label="地址"/>
<el-table-column fixed="right" label="操作">
<template #default="scope">
<el-button size="mini" @click="handleEdit(scope.$index,scope.row)">编辑</el-button>
<!--弹出消息确认框-->
<el-popconfirm
confirm-button-text="是的,没错"
cancel-button-text="妈的,我再想想"
icon="el-icon-info"
icon-color="red"
title="确定删除吗?">
<template #reference>
<el-button size="mini" type="danger" @click="handleDelete(scope.$index,scope.row)">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!--分页功能区域-->
<div style="margin: 10px 0">
<el-pagination
v-model:currentPage="currentPage4"
:page-sizes="[5,10,20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange">
</el-pagination>
</div>
<!--弹窗输入用户信息-->
<el-button type="text" @click="dialogVisible = true">click to open the Dialog</el-button>
<el-dialog v-model="dialogVisible" title="提示" width="30%">
<!--定义表单在这个弹出框内以收集新增的用户信息-->
<el-form :model="form" label="用户名">
<el-form-item label="用户名">
<el-input v-model="form.username" style="width: 80%"></el-input>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickName" style="width: 80%"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input v-model="form.age" style="width: 80%"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-radio v-model="form.sex" labei="男">男</el-radio>
<el-radio v-model="form.sex" labei="女">女</el-radio>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address" style="width: 80%"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Home',
components: {
},
data() {
return {
form: {},
dialogVisible: false,
search: '',
//当前页
currentPage4: 1,
total: 10,
tableData: [
],
}
},
methods: {
add(){
this.dialogVisible = true;
//清空表单域
this.form = {};
},
save(){
//这里我们就需要将保存起来的数据传入到后台中,运用Axios
},
handleEdit(){
},
handleDelete(){
},
handleSizeChange(){
// 改变页码时触发函数
},
handleCurrentChange(){
// 当前页改变时触发代码
}
}
}
</script>
现在就涉及到了前后端交互了,是一个重点,也就是上面代码中的save方法内部应该有与后端交互的功能,接下来就是实现这个事情。
第一步我们在Vue项目下新建一个文件夹叫utils,一个工具类的文件夹,在里面写上一个文件夹叫request.js,这个js文件就是我们用来封装处理前后端交互请求的文件:
交互功能的实现我们一般情况下使用Axios,但是在使用这个之前我们需要先安装一个Axios组件,打开控制器端,输入命令安装Axios:
等待安装完后,我们就可以在request.js文件中写代码了,内容如下一般都是固定的变化不大:
import axios from 'axios'
const request = axios.create({
timeout: 5000
})
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
// config.headers['token'] = user.token; // 设置请求头
return config
}, error => {
return Promise.reject(error)
});
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default request
然后我们现在可以去写用户数据保存下来的逻辑了,在save方法中:
save(){
//这里我们就需要将保存起来的数据传入到后台中,运用Axios
request.post("http://localhost:9090/user",this.form).then(res =>{
console.log(res)
})
},
但是直接访问的话,会报跨域错误:
而Vue已经给我们提供好了关于跨域错误的解决方案,我们要做的就是创建一个vue.config.js的配置文件就可以了。
这个文件我们要创建在Vue项目的文件夹下,和src文件夹同级才行。
这段代码也是固定死的,直接copy拿来用就好了。
// 跨域配置
module.exports = {
devServer: { //记住,别写错了devServer//设置本地默认端口 选填
port: 9876,
proxy: { //设置代理,必须填
'/api': { //设置拦截器 拦截器格式 斜杠+拦截器名字,名字可以自己定
target: 'http://localhost:9999', //代理的目标地址
changeOrigin: true, //是否设置同源,输入是的
pathRewrite: { //路径重写
'/api': '' //选择忽略拦截器里面的单词
}
}
}
}
}
注意上面的代理地址要改成自己后端程序设置的端口,比如我们这里的是9090,那么上面的端口9999就应该改成9090,同理原来的save方法中前面的那一段localhost就不再需要了,改变成/api:
因为新增了vue.config.js文件,所以需要重新启动,并且重启之后我们也不能通过访问8080端口来进入页面了,需要通过上面设置的本地默认端口9876,记得同时springboot项目也要启动,这样两个进程之间才可以进行通信,否则就报错(一开始我还为了这个找了好久bug),访问之后可以看到页面。然后点击新增按钮,输入用户信息:
可以看到数据库中已经出现了被插入的数据:
至此我们就已经完成阶段性胜利啦!由于篇幅过长,剩下的将在下一章节进行展示。