Vue-admin-template+SpringBoot+MyBatisPlus实现图书的增删改查功能

Vue-admin-template+SpringBoot+MyBatisPlus实现图书的增删改查功能(前后端分离)

由于最近学完Vue、MyBatisPlus、Vue-admin-template模板的使用,为了方便在后面的开发过程中更好的复习。特此在这里写一篇博客来记录,也方便编程学习者来借鉴。由于是初学,可能写的不怎么好,还望大神指导指导。

一、所需资料官网

[1] Vue-element-admin官网
[2] Vue.js官网
[3] MyBatisPlus官网

二、开发工具

IntelliJ IDEA Ultimate 2021.1.3
SpringBoot 2.6.2
MyBatisPlus 3.5.1
Vue-admin-template 4.4.0
apache-maven 3.8.3
MySQL 8.0.27
JDK 1.8.0_311

三、下载并安装Vue-Admin-Template模板

1、下载运行

1、克隆这个项目
(1)从github上克隆:
git clone https://github.com/PanJiaChen/vue-admin-template.git
(2)从gitee上克隆:
git clone https://gitee.com/panjiachen/vue-admin-template.git
2、进入项目目录
cd vue-admin-template
3、安装依赖
npm install
4、安装淘宝镜像
npm install --registry=https://registry.npm.taobao.org
5、启动服务
npm run dev

浏览器访问:http://localhost:9528

2、启动成功后的效果图

在这里插入图片描述

3、项目结构的介绍

在这里插入图片描述

4、配合后端使用改造前端项目

4.1、注释掉main.js中的mock的引用

在这里插入图片描述

4.2、注释掉vue.config.js中关于lint的语法检查

在这里插入图片描述

4.3、关注开发环境配置文件中关于请求前缀部分

在这里插入图片描述

4.4、在vue.config.js中添加路由表配置解决跨域问题

在这里插入图片描述

4.5、注释掉vue.config.js中关于mock的配置项,不然添加或修改时出现超时问题

在这里插入图片描述

proxy: {
      '/dev-api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: {
          '^/dev-api': ''
        }
      }
    }
4.6、查看登录成功后的数据返回格式以及查看用户信息时返回的格式

在这里插入图片描述
在这里插入图片描述

4.7、修改router/index.js文件(根据自己需要)

在这里插入图片描述

4.8、在views目录下新建book/index.vue文件
<template>
  <div class="app-container">

    <el-button type="success" icon="el-icon-plus" @click="handleEdit">添加</el-button>

    <el-table
      :data="books"
      :header-cell-style="{'text-align':'center'}"
      :cell-style="{'text-align':'center'}"
      style="width: 100%"
    >
      <el-table-column
        label="书籍编号"
        prop="bookId"
        width="280"
      />
      <el-table-column
        label="书籍名称"
        prop="bookName"
        width="280"
      />
      <el-table-column
        label="书籍数量"
        prop="bookCounts"
        width="280"
      />
      <el-table-column
        label="书籍描述"
        prop="detail"
        width="280"
      />
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button
            size="mini"
            @click="handleEdit(scope.row)"
          >编辑
          </el-button>
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(scope.row)"
          >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      :page-size="pageSize"
      :current-page="page"
      :page-sizes="[5, 10, 15, 20]"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
    <el-dialog :title="title" :visible.sync="dialogFormVisible">
      <el-form :model="book">
        <el-form-item label="书籍名称" :label-width="formLabelWidth">
          <el-input v-model="book.bookName" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="书籍数量" :label-width="formLabelWidth">
          <el-input v-model="book.bookCounts" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="书籍描述" :label-width="formLabelWidth">
          <el-input v-model="book.detail" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="save">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getList, edit, del } from '@/api/book'

export default {
  data() {
    return {
      books: [],
      book: {},
      page: 1,
      pageSize: 5,
      total: 20,
      dialogFormVisible: false,
      title: '添加书籍',
      formLabelWidth: '120'
    }
  },
  created() {
    this.findAll()
  },
  methods: {
    // 分页查询全部书籍信息
    findAll() {
      getList(this.page, this.pageSize).then(res => {
        this.books = res.data.records
        this.total = res.data.total
      })
    },
    // 编辑操作
    handleEdit(row) {
      // 判断是否是添加或修改
      if (row.bookId) {
        this.title = '修改书籍'
        this.book = row
      } else {
        this.title = '添加书籍'
        this.book = {}
      }
      // 打开对话框
      this.dialogFormVisible = true
    },
    // 保存数据
    async save() {
      // 设置添加url
      let url = '/book/addBook'
      // 判断是否是修改
      if (this.book.bookId) {
        url = '/book/editBook'
      }
      // 保存到数据库中
      const data = await edit(url, JSON.stringify(this.book))
      console.log('编辑状态:' + data.code)
      if (data.code === 20000) {
        // 关闭对话框
        this.dialogFormVisible = false
        // 刷新数据
        this.findAll()
      } else {
        this.$message.error({
          showClose: true,
          message: data.message
        })
      }
    },
    // 删除操作
    handleDelete(row) {
      console.log(row)
      this.$confirm(`您真的要删除书籍${row.bookName}吗?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async() => {
        const data = await del(row.bookId)
        if (data.code === 20000) {
          this.$message({
            type: 'success',
            message: '删除成功!',
            duration: 1000,
            onClose: () => {
              // 页数跳转到第一页
              this.handleCurrentChange(1)
              // 总条数-1
              this.total--
            }
          })
        } else {
          this.$message({
            type: 'info',
            message: '删除失败!'
          })
        }
      })
    },
    // 处理页数的改变
    handleCurrentChange(page) {
      this.page = page
      getList(page, this.pageSize).then(res => {
        this.books = res.data.records
      })
      console.log(`当前${page}页`)
    },
    // 处理每页显示条数的改变
    handleSizeChange(pageSize) {
      this.pageSize = pageSize
      console.log(`当前${pageSize}页`)
      // 重新发请求查询数据
      this.handleCurrentChange(this.page)
    }
  }
}
</script>
<style>
.el-pagination {
  margin-top: 20px;
  float: right;
}
</style>

4.9、在api目录下新建book.js
import request from '@/utils/request'

export function getList(current, pageSize) {
  return request({
    url: `/book/list/${current}/${pageSize}`,
    method: 'get'
  })
}

export function edit(url, book) {
  return request({
    url: url,
    method: 'post',
    data: book,
    headers: {
      'Content-type': 'application/json'
    }
  })
}

export function del(bookId) {
  return request({
    url: `/book/delBook/${bookId}`,
    method: 'get'
  })
}

四、使用SpringBoot搭建后台项目

1、后台项目结构

在这里插入图片描述

2、加载依赖

<dependencies>
    <!--Web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--MyBatisPlus依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    <!--MySQL依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!--Lombok依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3、创建数据库

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for books
-- ----------------------------
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books`  (
  `bookId` int(0) NOT NULL AUTO_INCREMENT COMMENT '书id',
  `bookName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '书名',
  `bookCounts` int(0) NOT NULL COMMENT '数量',
  `detail` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '描述',
  PRIMARY KEY (`bookId`) USING BTREE,
  INDEX `bookID`(`bookId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of books
-- ----------------------------
INSERT INTO `books` VALUES (1, 'Java', 1, '从入门到放弃');
INSERT INTO `books` VALUES (2, 'MySQL', 10, '从删库到跑路');
INSERT INTO `books` VALUES (3, 'Linux', 5, '从进门到进牢');

SET FOREIGN_KEY_CHECKS = 1;

4、修改项目resources目录下application.yaml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ssmbuild?characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
server:
  port: 8080

5、编写pojo实体类

package com.example.pojo;

import lombok.Data;

@Data
public class User {
    private String username;
    private String password;
}
package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class Books {

    @TableId(type = IdType.AUTO)
    private Integer bookId;

    private String bookName;

    private Integer bookCounts;

    private String detail;
}

6、编写dao持久层

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.pojo.Books;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BooksMapper extends BaseMapper<Books> {

}

7、编写service服务层

package com.example.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dao.BooksMapper;
import com.example.pojo.Books;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BooksService {

    @Autowired
    private BooksMapper booksMapper;

    public Page<Books> findAll(Integer current,Integer size){
        Page<Books> page = new Page<>(current,size);
        return booksMapper.selectPage(page,null);
    }

    public int addBooks(Books books){
        return booksMapper.insert(books);
    }

    public int updateBooksById(Books books){
        return booksMapper.updateById(books);
    }

    public int deleteBooksById(Integer bookId){
        return booksMapper.deleteById(bookId);
    }
}

8、编写controller控制层

package com.example.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.pojo.Books;
import com.example.service.BooksService;
import com.example.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/book")
public class BooksController {

    @Autowired
    private BooksService booksService;

    @GetMapping("/list/{current}/{pageSize}")
    public R getAllBooks(@PathVariable int current, @PathVariable int pageSize) {
        Page<Books> booksList = booksService.findAll(current, pageSize);
        return new R(20000, "查询成功!", booksList);
    }

    @PostMapping("/addBook")
    public R addBooks(@RequestBody Books books) {
        int i = booksService.addBooks(books);
        return i == 1 ? new R().renderSuccess("添加成功") : new R().renderError("添加失败");
    }

    @PostMapping("/editBook")
    public R editBooks(@RequestBody Books books) {
        int i = booksService.updateBooksById(books);
        return i == 1 ? new R().renderSuccess("修改成功") : new R().renderError("修改失败");
    }

    @GetMapping("/delBook/{bookId}")
    public R delBooks(@PathVariable Integer bookId) {
        int i = booksService.deleteBooksById(bookId);
        return i == 1 ? new R().renderSuccess("删除成功") : new R().renderError("删除失败");
    }
}
package com.example.controller;

import com.example.pojo.User;
import com.example.utils.R;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;

@RestController
public class UserController {

    @PostMapping("/user/login")
    public R userLogin(@RequestBody User user) {
        HashMap<String, Object> map = new HashMap<>();
        if (user.getUsername().equals("admin")&&user.getPassword().equals("111111")){
            map.put("token", "admin-token");
        }else {
            map.put("token", "editor-token");
        }
        return new R(20000,"登录成功", map);
    }

    @GetMapping("/user/info")
    public R userInfo(@RequestParam("token") String token) {
        HashMap<String, Object> map = new HashMap<>();
        if (token.equals("admin-token")){
            map.put("roles", "admin");
            map.put("name", "Super Admin");
        }else {
            map.put("roles", "editor");
            map.put("name", "Normal Editor");
        }
        map.put("avatar", "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        return new R(20000,"查看用户信息", map);
    }

    @PostMapping("/user/logout")
    public R userLogout(){
        return new R(20000,"退出成功!");
    }
}

9、编写MyBatisPlusConfig配置类

package com.example.utils;

import com.baomidou.mybatisplus.annotation.DbType;
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;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //添加分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

10、编写json格式结果返回类

package com.example.utils;

import lombok.Data;

@Data
public class R {

    private Integer code;

    private String message;

    private Object data;

    public R(){}

    public R(Integer code,String message){
        this.code=code;
        this.message=message;
    }

    public R(Integer code,Object data){
        this.code=code;
        this.data=data;
    }

    public R(Integer code,String message,Object data){
        this.code=code;
        this.message=message;
        this.data=data;
    }

    public R renderSuccess(String message){
        return new R(20000,message);
    }

    public R renderError(String message){
        return new R(20001,message);
    }
}

五、效果展示

1、登录页面

在这里插入图片描述

2、首页

在这里插入图片描述

3、书籍展示页面

在这里插入图片描述

4、添加书籍页面

在这里插入图片描述

5、修改书籍页面

在这里插入图片描述

6、删除书籍页面

在这里插入图片描述

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值