文章目录
- 前言
- 后端关键代码
- 前端关键代码
- 完整代码
前言
1、项目不使用前后端分离。
2、在创建SpringBoot
的时候要注意各个插件间的版本问题。
3、后端技术SpringBoot
+MyBatisPlus
+MySql
。
4、前端技术vue2
+elementUi
。
后端关键代码
简单介绍
1、数据库名称
ssm_db
2、表名称tbl_book
数据表对象文件(Book.java)
package com.example.domain; import lombok.Data; @Data public class Book { private Integer id; private String type; private String name; private String description; }
配置文件(application.yml)
server: port: 80 spring: datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC username: root password: root mybatis-plus: global-config: db-config: table-prefix: tbl_ id-type: auto configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
创建项目后,在
resources
文件夹下把application
的后缀名改为yml
。
接口文件(BookController.java)
写到这个文件就可以使用
Postman
进行接口测试了。
package com.example.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.controller.utils.R;
import com.example.domain.Book;
import com.example.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService bookService;
@GetMapping
public R getAll() {
return new R(true, bookService.list());
}
@PostMapping
public R save(@RequestBody Book book) throws IOException {
// R r = new R();
// boolean flag = bookService.save(book);
// r.setFlag(flag);
// 上面的三行代表这一行
// new R(bookService.save(book));
// return r;
// 抛出异常测试
// if (book.getName().equals("123")) throw new IOException();
boolean flag = bookService.save(book);
return new R(flag, flag ? "添加成功^_^!" : "添加失败-_-!");
}
@PutMapping
public R update(@RequestBody Book book) throws IOException {
boolean flag = bookService.modify(book);
return new R(flag, flag ? "编辑成功^_^!" : "编辑失败-_-!");
}
@DeleteMapping("{id}")
public R delete(@PathVariable Integer id) {
boolean flag = bookService.delete(id);
return new R(flag, flag ? "删除成功^_^!" : "数据同步失败,自动刷新-_-!");
}
@GetMapping("{id}")
public R getById(@PathVariable Integer id) {
// 数据同步失败,自动刷新
return new R(true, bookService.getById(id));
}
// 分页
// @GetMapping("{currentPage}/{pageSize}")
// public R getPage(@PathVariable int currentPage, @PathVariable int pageSize) {
// IPage<Book> page = bookService.getPage(currentPage, pageSize);
// if (currentPage > page.getPages()) {
// page = bookService.getPage((int) page.getPages(), pageSize);
// }
// return new R(true, page, "查询成功^_^!");
// }
// 分页加查询
@GetMapping("{currentPage}/{pageSize}")
// 可以单独接收,也可以使用集合
// public R getPage(@PathVariable int currentPage, @PathVariable int pageSize, String name, Book book) {
// 直接使用集合接收参数
public R getPage(@PathVariable int currentPage, @PathVariable int pageSize, Book book) {
IPage<Book> page = bookService.getPage(currentPage, pageSize, book);
if (currentPage > page.getPages()) {
page = bookService.getPage((int) page.getPages(), pageSize, book);
}
System.out.println(page);
return new R(true, page);
}
}
技术整合文件(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.15</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>singleFableFullStack</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
前端关键代码
<!DOCTYPE html>
<html>
<head>
<!-- 页面meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SpringBoot+MyBatisPlus整合的SSM案例</title>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../css/style.css">
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>图书管理</h1>
</div>
<div class="app-container">
<div class="box">
<div class="filter-container">
<el-input placeholder="图书类别" v-model="pagination.type" style="width: 200px;"
class="filter-item" clearable @input="handleInput($event,'type')"></el-input>
<el-input placeholder="图书名称" v-model="pagination.name" style="width: 200px;"
class="filter-item" clearable @input="handleInput($event,'name')"></el-input>
<el-input placeholder="图书描述" v-model="pagination.description" style="width: 200px;"
class="filter-item" clearable @input="handleInput($event,'description')"></el-input>
<el-button type="info" plain class="dalfBut" @click="handleSearch">查询</el-button>
<el-button type="success" plain class="butT" @click="handleDialog(undefined, '1')">新建
</el-button>
</div>
<el-table
size="small"
current-row-key="id"
:data="dataList"
stripe
highlight-current-row
>
<el-table-column type="index" align="center" label="序号"></el-table-column>
<el-table-column prop="type" label="图书类别" align="center"></el-table-column>
<el-table-column prop="name" label="图书名称" align="center"></el-table-column>
<el-table-column prop="description" label="描述" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="primary" plain size="mini" @click="handleDialog(scope.row, '2')">编辑
</el-button>
<el-button type="danger" plain size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<div class="pagination-container">
<el-pagination
class="pagiantion"
@current-change="handleCurrentChange"
@size-change="handlePageSize"
:current-page="pagination.currentPage"
:page-size="pagination.pageSize"
:page-sizes="[5, 10, 15, 30]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</div>
<!-- 新增/编辑标签弹层 -->
<div class="add-form">
<el-dialog :title="dialogTitle==='1'?'新增图书':'编辑图书'" :visible.sync="isDialogAddEdit"
@close="handleClose">
<el-form :model="formData" :rules="rules" ref="refForm" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="isDialogAddEdit=false">取消</el-button>
<el-button type="primary" @click="handleSave()">保存</el-button>
</div>
</el-dialog>
</div>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script>
new Vue({
el: '#app',
data: {
// 当前页要展示的列表数据
dataList: [],
// 添加表单是否可见
isDialogAddEdit: false,
dialogTitle: '1',
// 表单数据
formData: {},
// 校验规则
rules: {
type: [
{
required: true,
message: '图书类别为必填项',
trigger: 'blur'
}
],
name: [
{
required: true,
message: '图书名称为必填项',
trigger: 'blur'
}
]
},
// 分页相关模型数据
pagination: {
// 当前页码
currentPage: 1,
// 每页显示的记录数
pageSize: 5,
// 总记录数
total: 0,
type: '',
name: '',
description: ''
},
// 整页加载
fullPageLoading: undefined
},
// 钩子函数,VUE对象初始化完成后自动执行
created() {
// 调用查询全部数据的操作
this.getAll();
},
methods: {
// 列表加分页查询
getAll() {
let {
currentPage,
pageSize,
type,
name,
description
} = this.pagination,
param = '';
param += `?type=${type}&name=${name}&description=${description}`;
this.handleFullPageLoading('start');
// 发送异步请求
axios.get(`/books/${currentPage}/${pageSize}${param}`)
.then(({data: {flag, data: {records, total, size, current}}}) => {
if (flag) {
this.pagination.currentPage = current;
this.pagination.pageSize = size;
this.pagination.total = total;
this.dataList = records;
} else {
this.$message.error('出错了');
}
})
.finally(() => {
this.handleFullPageLoading('stopping');
})
.catch(() => {
this.$message.error('出错了');
});
},
// 整页(页面)加载
handleFullPageLoading(type) {
if (type === 'start') {
this.fullPageLoading = this.$loading({
lock: true,
text: '加载中',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.5)'
});
} else if (type === 'stopping' && this.fullPageLoading) {
this.fullPageLoading.close();
this.fullPageLoading = undefined;
}
},
// 打开新增/编辑面板
handleDialog(row, str) {
this.dialogTitle = str;
this.isDialogAddEdit = true;
if (str === '2') this.getById(row);
},
// 关闭新增/编辑面板
handleClose() {
this.$refs.refForm.resetFields();
this.$refs.refForm.clearValidate();
this.formData = {};
},
// 保存
handleSave() {
this.$refs.refForm.validate(valid => {
if (!valid) return this.$message.warning('必填项内容为空');
if (this.dialogTitle === '1') {
this.handleAdd();
} else {
this.handleEdit();
}
});
},
// 添加
handleAdd() {
axios.post("/books", this.formData)
.then(({data: {flag, msg}}) => {
if (flag) {
this.$message.success(msg);
this.getAll();
this.isDialogAddEdit = false
} else {
this.$message.error(msg);
}
})
.catch(() => {
this.$message.error('出错了');
});
},
// 删除
handleDelete(row) {
this.$confirm(
'此操作永久删除当前信息,是否继续?',
'提示',
{
type: "warning"
}
)
.then(() => {
axios.delete("/books/" + row.id)
.then(({data: {flag, msg}}) => {
// 判断当前操作是否成功
if (flag) {
this.$message.success(msg);
this.getAll();
} else {
this.$message.error(msg);
}
})
.catch(() => {
this.$message.error('出错了');
});
})
.catch(() => {
this.$message.info('已取消');
});
},
// 通过id获取数据
getById(row) {
axios.get('/books/' + row.id)
.then(({data: {flag, data}}) => {
if (flag && data !== null) {
this.formData = data;
} else {
this.$message.error('出错了');
}
})
.catch(() => {
this.$message.error('出错了');
});
},
// 编辑
handleEdit() {
axios.put("/books", this.formData)
.then(({data: {flag, msg}}) => {
// 判断当前操作是否成功
if (flag) {
this.$message.success(msg);
this.getAll();
this.isDialogAddEdit = false
} else {
this.$message.error(msg);
}
})
.catch(() => {
this.$message.error('出错了');
});
},
// 切换页码
handleCurrentChange(currentPage) {
if (this.pagination.currentPage === currentPage) return false;
this.pagination.currentPage = currentPage;
this.$nextTick(() => this.getAll());
},
// 页码大小
handlePageSize(pageSize) {
if (this.pagination.pageSize === pageSize) return false;
this.pagination.pageSize = pageSize;
this.$nextTick(() => this.getAll());
},
// 搜索输入框值变化
handleInput(e, searchField) {
if (!e) {
this.pagination[searchField] = e;
this.$nextTick(() => this.getAll());
}
},
// 查询
handleSearch() {
let {
type,
name,
description
} = this.pagination;
if (type || name || description) this.getAll();
}
}
});
</script>
</html>
完整代码
下载
git clone -b back-end-services https://gitee.com/mssj200224/open-resources.git
项目
1、找到仓库中名为
singleFableFullStack
文件夹复制出来。
2、使用idea
打开项目即可运行。