SpringBoot-Vue整合的小demo

发布时间 2023-07-07 15:26:58作者: 布布布丁

参考:https://github.com/Aizhuxueliang/springboot-vue

主要通过后端SpringBoot技术和前端Vue技术来整合一个小demo,实现简单的增删改查、分页功能以及了解Springboot搭配vue完成前后端分离项目的开发流程。

2023.7.7

一、创建数据库表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `userId` int(20) NOT NULL AUTO_INCREMENT,
  `userDate` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `userName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `userAddress` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`userId`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 71 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (15, '2019-09-29T03:17:12.000Z', '王老三', '上海市普陀区金沙江路 1515 弄');
INSERT INTO `user` VALUES (16, '2019-09-29T03:27:05.000Z', '张小四', '上海市普陀区金沙江路 1514 弄');
INSERT INTO `user` VALUES (17, '2019-09-29T03:30:04.000Z', '王老五', '上海市普陀区金沙江路 1513弄');
INSERT INTO `user` VALUES (18, '2019-09-29T03:33:15.000Z', '小六子', '上海市普陀区金沙江路 1512弄');
INSERT INTO `user` VALUES (20, '2019-09-29T03:33:15.000Z', '王老八', '上海市普陀区金沙江路 1512弄');
INSERT INTO `user` VALUES (21, '2019-09-29T05:42:52.000Z', '王大拿', '上海市普陀区金沙江路 1511弄');
INSERT INTO `user` VALUES (22, '2019-09-29T05:43:50.000Z', '小九九', '上海市普陀区金沙江路 1510弄');
INSERT INTO `user` VALUES (23, '2019-09-29T05:43:50.000Z', '刘诗诗', '上海市普陀区金沙江路 1499弄');
INSERT INTO `user` VALUES (24, '2019-09-29T05:46:07.000Z', '扎昂四四', '上海市大湾区科技路');
INSERT INTO `user` VALUES (25, '2019-09-29T05:46:07.000Z', '扎昂四四新东方', '上海市大湾区科技路2001号');
INSERT INTO `user` VALUES (26, '2019-09-29T05:46:07.000Z', '王小虎', '上海市大湾区科技路2002号');
INSERT INTO `user` VALUES (27, '2019-09-29T05:46:07.000Z', '抽拉吧唧', '上海市大湾区科技路2003号');
INSERT INTO `user` VALUES (28, '2019-09-29T05:46:07.000Z', '年啦编辑', '上海市大湾区科技路2004号');
INSERT INTO `user` VALUES (29, '2019-09-29T05:46:07.000Z', '你多少', '上海市普陀区金沙江路 1211弄');
INSERT INTO `user` VALUES (30, '2019-09-29T05:46:07.000Z', '反发达', '上海市普陀区金沙江路 1212弄');
INSERT INTO `user` VALUES (31, '2019-09-29T05:51:20.000Z', '发官方', '上海市普陀区金沙江路 1213弄');
INSERT INTO `user` VALUES (32, '2019-09-29T05:51:20.000Z', '方还有', '上海市普陀区金沙江路 1214弄');
INSERT INTO `user` VALUES (33, '2019-09-29T05:51:20.000Z', '过不分', '上海市普陀区金沙江路 1498弄');
INSERT INTO `user` VALUES (34, '2019-09-29T05:51:20.000Z', '菜市场', '上海市普陀区金沙江路 1497弄');
INSERT INTO `user` VALUES (35, '2019-09-29T05:51:20.000Z', '权威的', '上海市普陀区金沙江路 1496弄');
INSERT INTO `user` VALUES (36, '2019-09-29T05:55:09.000Z', '冈反对的', '上海市大湾区科技路2001号');
INSERT INTO `user` VALUES (37, '2019-09-29T05:55:09.000Z', '冈反对', '上海市大湾区科技路2003号');
INSERT INTO `user` VALUES (38, '2019-09-29T05:55:09.000Z', '偶哦里面', '上海市大湾区科技路2004号');
INSERT INTO `user` VALUES (39, '2019-09-29T05:55:09.000Z', '偶哦韩大苏打', '上海市大湾区科技路2005号');
INSERT INTO `user` VALUES (40, '2019-09-29T05:55:09.000Z', '偶哦匀', '上海市大湾区科技路2006号');
INSERT INTO `user` VALUES (41, '2019-09-29T05:55:09.000Z', '敢哦匀', '上海市大湾区科技路2006号');
INSERT INTO `user` VALUES (42, '2019-09-29T05:55:09.000Z', '敢孩', '上海市大湾区科技路2006号');
INSERT INTO `user` VALUES (43, '2019-09-29T05:55:09.000Z', '敢女孩', '上海市大湾区科技路2007号');
INSERT INTO `user` VALUES (45, '2019-09-29T05:55:09.000Z', '工行行', '上海市大湾区科技路2008号');
INSERT INTO `user` VALUES (46, '2019-09-29T05:55:09.000Z', '家好吗', '上海市大湾区科技路2008号');
INSERT INTO `user` VALUES (47, '2019-09-29T05:55:09.000Z', '的程度', '上海市大湾区科技路2009号');
INSERT INTO `user` VALUES (48, '2019-09-29T05:55:09.000Z', '称得上', '上海市大湾区科技路2009号');
INSERT INTO `user` VALUES (49, '2019-09-29T05:55:09.000Z', '韩国和', '上海市大湾区科技路2010号');
INSERT INTO `user` VALUES (50, '2019-09-29T05:55:09.000Z', '韩好', '上海市大湾区科技路2010号');
INSERT INTO `user` VALUES (51, '2019-09-29T05:55:09.000Z', '韩吧', '上海市大湾区科技路2011号');
INSERT INTO `user` VALUES (52, '2019-09-29T05:55:09.000Z', '韩吧吧', '上海市大湾区科技路2012号');
INSERT INTO `user` VALUES (53, '2019-09-29T05:55:09.000Z', '长度是', '上海市大湾区科技路2013号');
INSERT INTO `user` VALUES (54, '2019-09-29T05:55:09.000Z', '比如合', '上海市大湾区科技路2014号');
INSERT INTO `user` VALUES (55, '2019-09-29T05:55:09.000Z', '如合境', '上海市大湾区科技路2015号');
INSERT INTO `user` VALUES (56, '2019-09-29T05:55:09.000Z', '如合国', '上海市大湾区科技路2016号');
INSERT INTO `user` VALUES (57, '2019-09-29T05:55:09.000Z', '如更好', '上海市大湾区科技路2017号');
INSERT INTO `user` VALUES (58, '2019-09-29T05:55:09.000Z', '如更法', '上海市大湾区科技路2018号');
INSERT INTO `user` VALUES (59, '2019-09-29T05:55:09.000Z', '反对', '上海市大湾区科技路2019号');
INSERT INTO `user` VALUES (60, '2019-09-29T05:55:09.000Z', '如国部', '上海市大湾区科技路2019号');
INSERT INTO `user` VALUES (61, '2019-09-29T06:04:15.000Z', '奇热网', '上海市普陀区金沙江路 1496弄');
INSERT INTO `user` VALUES (62, '2019-09-29T06:04:33.000Z', '反对法', '上海市普陀区金沙江路 1495弄');
INSERT INTO `user` VALUES (63, '2019-09-29T06:04:33.000Z', '的风格', '上海市普陀区金沙江路 1494弄');
INSERT INTO `user` VALUES (64, '2019-09-29T06:04:33.000Z', '广泛同', '上海市大湾区科技路2020号');
INSERT INTO `user` VALUES (65, '2019-09-10T06:04:33.000Z', '但仍然', '上海市普陀区金沙江路 1493弄');
INSERT INTO `user` VALUES (66, '2019-09-29T06:10:28.000Z', 'vdfv', '放到电饭锅的');
INSERT INTO `user` VALUES (67, '2019-09-14T16:00:00.000Z', '朱老六', '上海市高新区上海中心');
INSERT INTO `user` VALUES (69, '2019-09-10T16:00:00.000Z', '是的', ' 学生的三十四分');
INSERT INTO `user` VALUES (70, '2019-09-29T07:51:44.000Z', '张小子', '上海市浦东区1234号');

SET FOREIGN_KEY_CHECKS = 1;

二、后端开发环境搭建

  1. 首先新建一个SpringBoot的项目,勾选Spring Web、JDBC、MySQL驱动以及Mybatis框架支持(如果没有勾选Mybatis则需要自己添加mybatis的包)

  1. 配置pom.xml,看还有没有项目中需要的包,把它们添加进来(这里我额外添加了两个包:lombok和junit)
<?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.13</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xyy</groupId>
    <artifactId>springboot-vue-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-vue-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  1. 配置application.yml(一开始踩了个坑:如果在创建项目的时候勾选了jdbc、mysql这些,一定要配置数据源,否则在测试项目是否搭建成功时,比如说写一个返回hello的Controller,会报错Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.)
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123

server:
  port: 8081

mybatis:
  type-aliases-package: com.xyy.pojo
  mapper-locations: classpath:mapper/*.xml
  1. 写一个HelloController看基本环境是否搭建成功
package com.xyy.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello world";
    }
}

能正常返回hello world,基本环境搭建成功,继续往下

  1. 在和启动类SpringbootVueDemoApplication.java建pojo包,pojo包下新建User实体类,要和数据库字段保持一致
package com.xyy.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {

    private int userId;
    private String userDate;
    private String userName;
    private String userAddress;

}
  1. 新建一个mapper包,在包下创建UserMapper接口
package com.xyy.mapper;

import com.xyy.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserMapper {
    List<User> findUserByName(@Param("userName") String userName);

    List<User> ListUser();

    // 假定一页5个
    List<User> queryPage(@Param("startRows") int startRows);

    int getRowCount();

    int insertUser(User user);

    int delete(@Param("userId") int userId);

    int update(User user);
}
  1. 在resources目录下新建mapper目录(和前面配置的yml文件中的路径保持一致),在mapper目录下新建UserMapper.xml,UserMapper.xml中编写sql语句实现UserMapper中的接口
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC
        "-//mybatis.org//DTD com.example.Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xyy.mapper.UserMapper">

    <select id="findUserByName" parameterType="string" resultType="User">
        select * from test.user
        where userName like concat(concat('%',#{userName}),'%')
        order by userId desc;
    </select>

    <select id="ListUser" resultType="User">
        select * from test.user;
    </select>

    <select id="queryPage" parameterType="int" resultType="User">
        select * from test.user
        limit #{startRows}, 5;
    </select>

    <select id="getRowCount" resultType="int">
        select count(1) from test.user;
    </select>

    <insert id="insertUser" parameterType="User">
        insert into test.user (userId, userDate, userName, userAddress)
        values (#{userId}, #{userDate}, #{userName}, #{userAddress});
    </insert>

    <delete id="delete" parameterType="int">
        delete from test.user where userId = #{userId};
    </delete>

    <!--set userDate = #{userDate}, userName = #{userName}, userAddress = #{userAddress}-->
    <update id="update" parameterType="User">
        update test.user

        <set>
            <if test="userDate != null">
                userDate = #{userDate},
            </if>
            <if test="userName != null">
                userName = #{userName},
            </if>
            <if test="userAddress != null">
                userAddress = #{userAddress}
            </if>
        </set>

        where userId = #{userId};
    </update>

</mapper>
  1. 新建service包,编写UserService业务类(本来可能要接口和接口实现类,但是这里是个简单的demo所以省略这个)
package com.xyy.service;

import com.xyy.mapper.UserMapper;
import com.xyy.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired(required = false)
//    @Autowired()
    private UserMapper userMapper;

    public List<User> findByName(String userName) {
        return userMapper.findUserByName(userName);
    }

    public List<User> queryPage(Integer startRows) {
        return userMapper.queryPage(startRows);
    }

    public int getRowCount() {
        return userMapper.getRowCount();
    }

    public User insertUser(User user) {
        userMapper.insertUser(user);
        return user;
    }

    public List<User> ListUser(){
        return userMapper.ListUser();
    }

    public int update(User user){
        return userMapper.update(user);
    }

    public int delete(int userId){
        return userMapper.delete(userId);
    }
}
  1. 编写UserController
package com.xyy.controller;

import com.xyy.pojo.User;
import com.xyy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class UserController {

    @Autowired(required = false)
    private UserService userService;

    @PostMapping("/delete")
    public Integer delete(Integer userId) {
        System.out.println(userId);
        int result = userService.delete(userId);
        return result;
    }

    @PostMapping("/update")
    public String update(User user) {
        int result = userService.update(user);
        if (result >= 1) {
            return "修改成功";
        } else {
            return "修改失败";
        }
    }

    @PostMapping("/insert")
    public User insert(User user) {
        return userService.insertUser(user);
    }

    @PostMapping("/ListUser")
    public List<User> ListUser() {
        return userService.ListUser();
    }

    @PostMapping("/ListByName")
    public List<User> ListUserByName(String userName) {
        return userService.findByName(userName);
    }

    @PostMapping("/page")
    public List<User> page(Integer page){
        int pageNow = page == null ? 1 : page;
        int pageSize = 5;
        int startRows = pageSize*(pageNow-1);
        List<User> list = userService.queryPage(startRows);
        return list;
    }

    @PostMapping("/rows")
    public int rows(){
        return userService.getRowCount();
    }
}
  1. 启动项目,在浏览器中输入对应的访问路径名,如果每个都能正确出结果说明代码没有问题,后端整体结构如下:

三、前端开发环境搭建

  1. 进入一个项目目录(我是放在这个springboot项目下,方便用IDEA统一运行),在命令行中执行命令:vue init webpack 项目名

  2. 进入该项目名下的目录:cd 项目名,安装依赖:npm install

  1. 启动运行:npm run dev

  1. 打开浏览器输入:http://localhost:8080,效果如图:

  1. 在项目根目录安装axios执行命令:npm install axios

  1. 安装element ui 执行命令:npm i element-ui -S

  1. 更新App.vue
<template>
  <div id="app">
    <el-row type="flex" justify="center">
      <el-col :xs="24" :sm="22" :md="20" :lg="20" :xl="18">
        <router-view/>
      </el-col>
    </el-row>
  </div>
</template>

<script>
  export default {
    name: 'App',
    data() {
      return {
      }
    },
    methods: {
    }
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    margin: 0px;
    padding: 0px;
  }
</style>
  1. 更新main.js(如果报错Import declarations are not supported by current JavaScript version,调一下当前IDEA的js版本,改成ES6)
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
// 如果报错Import declarations are not supported by current JavaScript version,调一下当前IDEA的js版本,改成ES6
import Vue from 'vue'
import App from './App'
import router from './router'
import elementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'element-ui/lib/theme-chalk/display.css'

Vue.use(elementUI);

import axios from 'axios'
Vue.prototype.axios = axios;

// qs处理 HTTP 请求中的数据序列化
// 当你需要向后端发送 POST 请求时,通常需要将请求数据转换为特定的格式,
// 比如 URL 查询字符串或 JSON 对象。这就是 qs 库的作用。
import qs from 'qs';
Vue.prototype.qs = qs;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
});
  1. 更新HelloWorld.vue
<template>
  <div>
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input
          v-model="search"
          class="search_name"
          size="mini"
          placeholder="输入姓名查询">
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-button
          type="text"
          @click="onSearch()"
          class="el-icon-search">查询
        </el-button>
      </el-form-item>
      <el-form-item>
        <el-button
          class="el-icon-refresh"
          type="text"
          @click="refreshData">刷新
        </el-button>
      </el-form-item>
      <el-form-item>
        <el-button
          class="el-icon-circle-plus-outline"
          type="text"
          @click="dialogVisible = true">添加
        </el-button>
      </el-form-item>
    </el-form>
    <el-table
      :data="tableData"
      highlight-current-row
      border
      style="width: 100%">
      <el-table-column
        label="编号">
        <template slot-scope="scope">
          <span>{{ scope.row.userId }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="日期">
        <template slot-scope="scope">
          <i class="el-icon-time hidden-sm-and-down"></i>
          <span>{{ scope.row.userDate }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="姓名">
        <template slot-scope="scope">
          <el-popover trigger="hover" placement="right">
            <p>姓名: {{ scope.row.userName }}</p>
            <p>住址: {{ scope.row.userAddress }}</p>
            <p>日期:{{ scope.row.userDate }}</p>
            <div slot="reference" class="name-wrapper">
              <el-button type="text">{{ scope.row.userName }}</el-button>
            </div>
          </el-popover>
        </template>
      </el-table-column>
      <el-table-column
        label="住址">
        <template slot-scope="scope">
          <span>{{ scope.row.userAddress }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        fixed="right"
        width="200">
        <template slot-scope="scope">
          <el-button
            size="mini"
            icon="el-icon-edit"
            @click="handleEdit(scope.$index, scope.row)">编辑
          </el-button>
          <el-button
            size="mini"
            type="danger"
            icon="el-icon-delete"
            @click="handleDelete(scope.$index, scope.row)">删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" size="medium">
      <el-dialog
        title="添加"
        :append-to-body='true'
        :visible.sync="dialogVisible"
        width="80%"
        :before-close="handleClose">
        <el-input type="hidden" v-model="ruleForm.userId"/>
        <el-form-item label="时间" prop="userDate">
          <el-date-picker type="datetime" placeholder="选择日期" v-model="ruleForm.userDate" style="width: 100%;"></el-date-picker>
        </el-form-item>
        <el-form-item label="姓名" prop="userName">
          <el-input v-model="ruleForm.userName"></el-input>
        </el-form-item>
        <el-form-item label="住址" prop="userAddress">
          <el-input v-model="ruleForm.userAddress"></el-input>
        </el-form-item>

        <span slot="footer" class="dialog-footer">
            <el-button @click="cancel()" size="medium">取 消</el-button>
            <el-button @click="addUser()" type="primary" size="medium">确 定</el-button>
          </span>
      </el-dialog>
    </el-form>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" size="medium">
      <el-dialog
        title="编辑"
        :append-to-body='true'
        :visible.sync="dialogUpdate"
        width="80%"
        :before-close="handleClose">
        <el-input type="hidden" v-model="ruleForm.userId"/>
        <el-form-item label="时间" prop="userDate">
          <el-date-picker type="datetime" placeholder="选择日期" v-model="ruleForm.userDate" style="width: 100%;"></el-date-picker>
        </el-form-item>
        <el-form-item label="姓名" prop="userName">
          <el-input v-model="ruleForm.userName"></el-input>
        </el-form-item>
        <el-form-item label="住址" prop="userAddress">
          <el-input v-model="ruleForm.userAddress"></el-input>
        </el-form-item>

        <span slot="footer" class="dialog-footer">
            <el-button @click="cancel()" size="medium">取 消</el-button>
            <el-button @click="updateUser()" type="primary" size="medium">确 定</el-button>
          </span>
      </el-dialog>
    </el-form>
    <br>
    <div class="pages">
      <el-pagination
        background
        :disabled = "disablePage"
        :current-page.sync="currentPage"
        small
        layout="prev, pager, next"
        :page-size="pageSize"
        :total="total"
        @current-change="handleCurrentChange">
      </el-pagination>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        ruleForm: {
          userId: '',
          userName: '',
          userDate: '',
          userAddress: ''
        },
        rules: {
          userName: [
            { required: true, message: '请输入姓名', trigger: 'blur' },
            { min: 2, max: 7, message: '长度在 2 到 7 个字符', trigger: 'blur' }
          ],
          userAddress: [
            { required: true, message: '请输入住址', trigger: 'blur' },
            { min: 5, message: '长度大于 5 个字符', trigger: 'blur' }
          ],
        },
        tableData: [],
        search: '',
        dialogVisible: false,
        dialogUpdate: false,
        pageSize: 5,
        currentPage: 1,
        total: 0,
        disablePage: false
      }
    },
    methods: {
      handleEdit(index, row) {
        this.dialogUpdate = true;
        this.ruleForm = Object.assign({}, row); //这句是关键!!!
      },
      handleDelete(index, row) {
        console.log(index, row);
        this.$confirm('删除操作, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          let postData = this.qs.stringify({
            userId: row.userId,
          });
          this.axios({
            method: 'post',
            url:'/delete',
            data:postData
          }).then(response =>
          {
            this.getPages();
            this.currentPage = 1;
            this.axios.post('/page').then(response =>
            {
              this.tableData = response.data;
            }).catch(error =>
            {
              console.log(error);
            });
            this.$message({
              type: 'success',
              message: '删除成功!'
            });
            console.log(response);
          }).catch(error =>
          {
            console.log(error);
          });

        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      },
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
      handleCurrentChange() {
        console.log(`当前页: ${this.currentPage}`);
        let postData = this.qs.stringify({
          page: this.currentPage
        });
        this.axios({
          method: 'post',
          url:'/page',
          data:postData
        }).then(response =>
        {
          this.tableData = response.data;
        }).catch(error =>
        {
          console.log(error);
        });
      },
      cancel() {
        this.dialogUpdate = false;
        this.dialogVisible = false;
        this.emptyUserData();
      },
      emptyUserData(){
        this.ruleForm = {
          userName: '',
          userDate: '',
          userAddress: ''
        }
      },
      addUser() {
        let postData = this.qs.stringify({
          userDate: this.ruleForm.userDate,
          userName: this.ruleForm.userName,
          userAddress: this.ruleForm.userAddress
        });
        // console.log(typeof this.ruleForm.userDate);
        // console.log(111);
        this.axios({
          method: 'post',
          url: '/insert',
          data: postData
        }).then(response => {
          this.axios.post('/page').then(response =>
          {
            this.tableData = response.data;
            this.currentPage = 1;
            this.$message({
              type: 'success',
              message: '已添加!'
            });
          }).catch(error => {
            console.log(error);
          });
          this.getPages();
          this.dialogVisible = false;
          console.log(response);
        }).catch(error =>
        {
          console.log(error);
        });
      },
      updateUser() {
        let postData = this.qs.stringify({
          userId: this.ruleForm.userId,
          userDate: this.ruleForm.userDate,
          userName: this.ruleForm.userName,
          userAddress: this.ruleForm.userAddress
        });
        this.axios({
          method: 'post',
          url:'/update',
          data:postData
        }).then(response =>
        {
          this.handleCurrentChange();
          this.cancel();
          this.$message({
            type: 'success',
            message: '更新成功!'
          });
          console.log(response);
        }).catch(error =>
        {
          this.$message({
            type: 'success',
            message: '更新失败!'
          });
          console.log(error);
        });
      },
      onSearch() {
        let postData = this.qs.stringify({
          userName: this.search
        });
        this.axios({
          method: 'post',
          url: '/ListByName',
          data: postData
        }).then(response =>
        {
          this.tableData = response.data;
          this.disablePage = true;
        }).catch(error =>
        {
          console.log(error);
        });
      },
      getPages() {
        this.axios.post('/rows').then(response =>
        {
          this.total = response.data;
        }).catch(error =>
        {
          console.log(error);
        });
      },
      refreshData() {
        location.reload();
      }
    },
    created() {
      /*this.axios.get('static/user.json').then(response =>
      {
          this.tableData = response.data.tableData;
          this.total = response.data.tableData.length;
          // console.log(JSON.parse(JSON.stringify(response.data))['tableData'])
      });*/
      this.axios.post('/page').then(response =>
      {
        this.tableData = response.data;
      }).catch(error =>
      {
        console.log(error);
      });

      this.axios.post('/rows').then(response =>
      {
        this.total = response.data;
      }).catch(error =>
      {
        console.log(error);
      });

    },
  }
</script>
<style scoped>
  .search_name{
    width: 200px;
  }
  .pages{
    margin: 0px;
    padding: 0px;
    text-align: right;
  }
</style>
  1. 在IDEA中配置npm(package.json选择当前项目下的,Scripts选择dev)

四、前后端整合

方式一:把config\index.js文件中的dev中的proxyTable{}替换为如下:

proxyTable: {
      '/': {
        target:'http://localhost:8081', // 你请求的第三方接口
        changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
        pathRewrite:{  // 路径重写,
          '^/': ''  // 替换target中的请求地址
        }
      }
    },

方式二(还没尝试) :在vue-cli项目根目录执行命令npm run build,编译完成后将dist/static文件夹copy至springboot项目的src/main/resources/static目录下然后直接启动springboot项目就OK了。

五、实现效果

打开浏览器输入localhost:8080,测试增删改查和分页这五个功能,五个功能均正常