刚学完SpringBoot基础开发步骤,为了巩固,独立完成案例
页面功能:
基础的增删改查、分页、分页查询
技术选型:
前端:vue、Element UI、axios
后端:springboot、SpringMvc、Mybatis Plus、Druid以及一些小组件
数据库:mysql
测试:浏览器、postman
原型展示:
主页面
新建消息框
添加成功
修改消息框
删除提示
删除成功
分页查询
目录结构:
前端页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书馆理</title>
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../css/style.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
.pagiantion {
text-align: right;
padding: 15px;
}
</style>
</head>
<body>
<div id="app">
<div style="text-align: center;color: deepskyblue; font-weight: bold">
<h1>琛叔SSMP小型图书管理整合案例</h1>
</div>
<!--查询表单开始-->
<el-form :inline="true" :model="pagination" class="demo-form-inline" style="padding-left: 20%">
<el-form-item label="图书类别">
<el-input v-model="pagination.type" placeholder="图书类别"></el-input>
</el-form-item>
<el-form-item label="图书名">
<el-input v-model="pagination.name" placeholder="图书名"></el-input>
</el-form-item>
<el-form-item label="图书描述">
<el-input v-model="pagination.description" placeholder="图书描述"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getAll()" round>查询</el-button>
<el-button type="success" round @click="create">新增</el-button>
</el-form-item>
</el-form>
<!--查询表单结束-->
<!--信息列表开始-->
<el-table
:data="dataList"
style="width: 100%"
:row-class-name="tableRowClassName" current-row-key="id">
<el-table-column
type="index"
label="编号"
width="180"
align="center">
</el-table-column>
<el-table-column
prop="type"
label="图书类别"
width="180"
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" size="mini" @click="update(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 信息列表结束-->
<!-- 新建信息框-->
<el-dialog
title="新建"
:visible.sync="dialogVisible"
width="70%">
<span>请输入新建书籍的信息</span>
<span slot="footer" class="dialog-footer">
<el-form :inline="true" :model="formData" class="demo-form-inline">
<el-form-item label="类别" prop="type">
<el-input v-model="formData.type" placeholder="类别"></el-input>
</el-form-item>
<el-form-item label="书名" prop="name">
<el-input v-model="formData.name" placeholder="书名"></el-input>
</el-form-item>
<el-form-item label="描述">
<el-input type="textarea" v-model="formData.description"></el-input>
</el-form-item>
<el-button @click="cancel()">取消</el-button>
<el-button type="primary" @click="createSubmit()">确定</el-button>
</el-form>
</span>
</el-dialog>
<!-- 新建信息框结束-->
<!-- 修改信息框-->
<el-dialog
title="修改"
:visible.sync="dialogVisibleUpdate"
width="70%"
>
<span>请输入修改书籍的信息</span>
<span slot="footer" class="dialog-footer">
<el-form :inline="true" :model="formData" class="demo-form-inline" rules="rules" label-position="right">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"></el-input>
</el-form-item>
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input type="textarea" v-model="formData.description"></el-input>
</el-form-item>
<el-form-item >
<el-button @click="cancel()" >取消</el-button>
<el-button type="primary" @click="updateSubmit">提交</el-button>
</el-form-item>
</el-form>
</span>
</el-dialog>
<!-- 修改信息框结束-->
<!-- 分页开始-->
<div class="pagination-container">
<!-- 分页结束-->
<el-pagination
class="pagiantion"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-size="pagination.pageSize"
layout="total, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</div>
</div>
</body>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script type="text/javascript" src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/axios-0.18.0.js"></script>
<script>
let vue = new Vue({
el: '#app',
data() {
return {
dataList: [],
formData: {},
dialogVisible: false,
dialogVisibleUpdate: false,
pagination: {
currentPage: 1,
pageSize: 10,
total: 0,
type: "",
name: "",
description: ""
},
}
},
mounted() {
this.getAll()
},
methods: {
//入口函数
tableRowClassName({row, rowIndex}) {
if (rowIndex % 2 === 0) {
return 'success-row';
}
},
getAll() {
let _this = this;
let type = this.pagination.type;
let name = this.pagination.name;
let description = this.pagination.description;
let param = "/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize + "?query";
if (type != null) {
param += ("&type=" + type);
}
if (name != null) {
param += ("&name=" + name);
}
if (description != null) {
param += ("&description=" + description);
}
axios.get(param).then((resp) => {
_this.dataList = resp.data.data.records;
this.pagination.currentPage = resp.data.data.current;
this.pagination.pageSize = resp.data.data.size;
this.pagination.total = resp.data.data.total;
})
},
create() {
this.dialogVisible = true;
this.formData = {};
},
cancel() {
this.dialogVisible = false;
this.dialogVisibleUpdate = false;
this.formData = {};
this.$message.info("操作已取消");
},
createSubmit() {
let _this = this;
axios.post("/books", _this.formData).then(function (resp) {
if (resp.data.flag) {
_this.dialogVisible = false;
_this.$message.success(resp.data.msg);
} else {
_this.dialogVisible = false;
_this.$message.error(resp.data.msg);
}
}).finally(() => {
this.getAll();
})
},
handleCurrentChange(currentPage) {
this.pagination.currentPage = currentPage;
this.getAll();
},
handleDelete(row) {
let _this = this;
this.$confirm("此操作将永久删除当前信息,是否继续?", "提示", {type: "info"}).then(() => {
axios.delete("/books/" + row.id).then((resp) => {
if (resp.data.flag) {
_this.$message.success(resp.data.msg);
} else {
_this.$message.error(resp.data.msg);
}
}).finally(() => {
this.getAll();
})
}).catch(() => {
_this.$message.info("已取消");
})
},
update(row) {
let _this = this;
axios.get("/books/" + row.id).then((resp) => {
if (resp.data.flag && resp.data.data != null) {
this.dialogVisibleUpdate = true;
_this.formData = resp.data.data;
} else {
this.$message.error("数据同步失败,自动刷新")
}
}).finally()
{
this.getAll();
}
},
updateSubmit() {
let _this = this;
axios.put("/book/" , _this.formData)
.then((resp) => {
let msg = resp.data.msg;
if (resp.data.flag) {
this.dialogVisibleUpdate = false;
_this.$message.success(msg);
} else {
_this.$message.error(msg);
}
}).finally(() => {
this.getAll();
})
}
}
})
</script>
</html>
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 http://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.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itchen</groupId>
<artifactId>springboot_ssmp_myself</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
</project>
application.yml:
# 应用服务 WEB 访问端口
server:
port: 80
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?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
启动类:
package com.itchen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 张家琛
* @version 1.0
* @date 2022/3/26 22:57
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
Book Bean:
package com.itchen.domain;
import lombok.Data;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 8:22
*/
@Data
public class Book {
private Long id;
private String type;
private String name;
private String description;
}
前后端传输协议数据对象:
package com.itchen.controller.utils;
import lombok.Data;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 8:35
*/
@Data
public class R {
private Boolean flag;
private Object data;
private String msg;
public R(Boolean flag, Object data, String msg) {
this.flag = flag;
this.data = data;
this.msg = msg;
}
public R(Boolean flag) {
this.flag = flag;
}
public R(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
public R(Boolean flag, String msg) {
this.flag = flag;
this.msg = msg;
}
public R(Object data, String msg) {
this.data = data;
this.msg = msg;
}
}
异常处理类:
package com.itchen.controller.utils;
import com.itchen.controller.utils.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/9 8:24
*/
@RestControllerAdvice
public class ExceptionHandlerMyself {
@ExceptionHandler(Exception.class)
public R exception(Exception e){
e.printStackTrace();
return new R(false,"服务器错误");
}
}
mybatis Plus拦截器:
package com.itchen.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 13:05
*/
@Configuration
public class MpInterceptor {
@Bean
public MybatisPlusInterceptor interceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
bookController:
package com.itchen.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.itchen.domain.Book;
import com.itchen.service.IBookService;
import com.itchen.controller.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author 张家琛
* @version 1.0
* @date 2022/3/26 22:59
*/
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService bookService;
@GetMapping("{currentPage}/{pageSize}")
public R getByPage(@PathVariable Integer currentPage, @PathVariable Integer pageSize, Book book) {
IPage<Book> byPage = bookService.getByPage(currentPage, pageSize, book);
if (currentPage > byPage.getPages()) {
byPage=bookService.getByPage((int)byPage.getPages(),pageSize,book);
}
R r = new R(true, byPage, "最新数据已更新");
return r;
}
@PutMapping
public R update(@RequestBody Book book) {
return null;
}
@GetMapping("{id}")
public R getById(@PathVariable Integer id) {
Book bookById = bookService.getById(id);
return new R(true,bookById,bookById!=null?"^_^修改成功":"-_-!修改失败了");
}
@PostMapping
public R create(@RequestBody Book book) {
boolean flag = bookService.save(book);
return new R(flag, flag ? "添加成功^_^" : "添加失败-_-!");
}
@DeleteMapping("{id}")
public R deleteById(@PathVariable Integer id) {
boolean flag = bookService.removeById(id);
return new R(flag, flag ? "删除成功" : "删除失败");
}
}
IBookService:
package com.itchen.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itchen.domain.Book;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 9:09
*/
public interface IBookService extends IService<Book> {
IPage<Book> getByPage(Integer currentPage,Integer pageSize,Book book);
}
BookService:
package com.itchen.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itchen.domain.Book;
import com.itchen.dao.BookDao;
import com.itchen.service.IBookService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 9:10
*/
@Service
public class BookService extends ServiceImpl<BookDao, Book> implements IBookService {
@Autowired
private BookDao bookDao;
@Override
public IPage<Book> getByPage(Integer currentPage, Integer pageSize, Book book) {
LambdaQueryWrapper<Book> queryWrapper=new LambdaQueryWrapper<Book>();
queryWrapper.like(!Strings.isEmpty(book.getType()),Book::getType,book.getType());
queryWrapper.like(!Strings.isEmpty(book.getName()),Book::getName,book.getName());
queryWrapper.like(!Strings.isEmpty(book.getDescription()),Book::getDescription,book.getDescription());
IPage<Book> page=new Page<Book>(currentPage,pageSize);
return bookDao.selectPage(page,queryWrapper);
}
}
BookDao:MP直接用
package com.itchen.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itchen.domain.Book;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 张家琛
* @version 1.0
* @date 2022/4/8 9:09
*/
@Mapper
public interface BookDao extends BaseMapper<Book> {
}