Vue Element Ui + Springboot前后端分离 CRUD(增删查改)、分页查询 Demo

最近两天刚刚学习完Springboot,决定做一个demo整合一下学习到的知识。由于前端所知甚少,所以前端会有一些小bug,但总的来说不影响功能。

技术栈

后端:

框架:Springboot、Mybatis、PageHelper(分页小工具)

工具:IDEA、Maven

数据库:Mysql 5

前端:

框架:Vue、axios、qs、element ui

工具:VS、npm、webpack

开发过程中遇到的问题:

  1. 跨域问题
    • 因为前后端工程在不同的服务器上,端口不同所以存在跨域问题
    • 解决方法: 代理服务器
  2. 参数传递问题
    • axios默认的请求参数时json格式的,后端接受的可能是单独的参数如String name等
    • 解决方法:qs

后端开发过程

  1. 搭建工程
    • 利用mybatis逆向工程生成实体类、Dao接口、mapper文件
    • 在springboot配置文件中配置数据库信息、端口号等
  2. 编写controller
    • 先确定接口的请求参数、响应数据
    • 最终的接口有:
      • 分页查询:使用pageHelper,
        • 请求参数为pageNum、pageSize即页码和页面大小,页面大小由前端控制
        • 响应数据为json数组,数组中存储的为多个实体类的信息
      • 添加:请求参数为实体类对象,响应数据为json字符串:成功或失败
      • 删除:请求参数为主键id值,响应数据为json字符串:成功或失败
      • 修改:请求参数为实体类对象,响应数据为json字符串:成功或失败
      • 获取数据库的总条数:无请求参数,响应数据为json字符串:数据库的数据总条数,用于前端获取总页数
  3. 根据controller编写service
  4. 根据service在dao中增加方法

后端代码

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.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wm</groupId>
    <artifactId>springboot-crud-demo</artifactId>
    <version>1.0.0</version>
    <name>springboot-crud-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--thymeleaf依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--springboot起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mybatis集成springboot依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>

        <!--分页依赖-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.13</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <!--指定mapper文件位置-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>

        <plugins>
            <!--逆向工程插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <configuration>
                    <configurationFile>generatorConfig.xml</configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
            <!--springboot打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

server.port=9090

#设置连接数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf-8&amp;useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

StudentController.java

package com.wm.controller;

import com.wm.model.Student;
import com.wm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;

@RequestMapping("/student")
@Controller
public class StudentController {
    @Autowired
    StudentService studentService;


    @RequestMapping(value = "/pageQuery")
    @ResponseBody
    public List<Student> pageQuery(Integer pageNum, Integer pageSize, HttpServletResponse response){
        response.setHeader("Access-Control-Allow-Origin", "*");

        return studentService.pageQueryStudent(pageNum, pageSize);

    }

    @ResponseBody
    @RequestMapping(value = "/insertStudent")
    public String insertStudent(Student student){
        Boolean flag = studentService.insertStudent(student);
        return flag? "添加成功" : "添加失败";
    }

    @ResponseBody
    @RequestMapping(value = "/deleteStudent")
    public String deleteStudent(Integer id){
        Boolean flag = studentService.deleteStudent(id);
        return flag? "删除成功" : "删除失败";
    }

    @ResponseBody
    @RequestMapping("/getTotal")
    public Integer getTotal(){
        return studentService.getTotal();
    }

    @ResponseBody
    @RequestMapping(value = "/updataStudent")
    public String deleteStudent(Student student){
        Boolean flag = studentService.updataStudent(student);
        return flag? "更新成功" : "更新失败";
    }
}

StudentServiceImpl.java

package com.wm.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wm.mapper.StudentMapper;
import com.wm.model.Student;
import com.wm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Override
    public List<Student> pageQueryStudent(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Student> studentList = studentMapper.selectAll();
        return studentList;
    }

    @Override
    public Boolean insertStudent(Student student) {
        int i = studentMapper.insertSelective(student);

        return i>0 ? true:false;
    }

    @Override
    public Boolean deleteStudent(Integer id) {
        int i = studentMapper.deleteByPrimaryKey(id);
        return i>0 ? true:false;
    }

    @Override
    public Integer getTotal() {
        return studentMapper.getTotal();
    }

    @Override
    public Boolean updataStudent(Student student) {

        int i = studentMapper.updateByPrimaryKeySelective(student);
        return i > 0 ? true : false;

    }
}

StudentMapper.java

package com.wm.mapper;

import com.wm.model.Student;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper
public interface StudentMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Student record);

    int insertSelective(Student record);

    Student selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Student record);

    int updateByPrimaryKey(Student record);

    List<Student> selectAll();

    Integer getTotal();
}

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wm.mapper.StudentMapper">
  <resultMap id="BaseResultMap" type="com.wm.model.Student">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="age" jdbcType="INTEGER" property="age" />
    <result column="address" jdbcType="VARCHAR" property="address" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name, age, address
  </sql>

  <select id="getTotal" resultType="java.lang.Integer">
    select count(id) from student
  </select>

  <select id="selectAll" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from student
  </select>

  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from student
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from student
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.wm.model.Student">
    insert into student (id, name, age, 
      address)
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, 
      #{address,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.wm.model.Student">
    insert into student
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="age != null">
        age,
      </if>
      <if test="address != null">
        address,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        #{age,jdbcType=INTEGER},
      </if>
      <if test="address != null">
        #{address,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.wm.model.Student">
    update student
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        age = #{age,jdbcType=INTEGER},
      </if>
      <if test="address != null">
        address = #{address,jdbcType=VARCHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.wm.model.Student">
    update student
    set name = #{name,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER},
      address = #{address,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

Student.java

package com.wm.model;

import java.io.Serializable;

public class Student implements Serializable {
    private Integer id;

    private String name;

    private Integer age;

    private String address;

    private static final long serialVersionUID = 1L;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address == null ? null : address.trim();
    }
}

SpringbootCrudDemoApplication.java

package com.wm;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = "com.wm.mapper")
public class SpringbootCrudDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCrudDemoApplication.class, args);
    }
}

前端开发过程

  1. 搭建工程
    • 通过vue ui 创建工程
    • 安装axios、element ui、qs
    • 在项目目录下创建vue.config.js 用于配置端口和解决跨域问题
  2. 利用element ui 官网,复制粘贴你需要的组件
  3. 给组件添加事件,利用axios发生ajax请求接受响应数据并展示

前端代码

src\components\HelloWorld.vue

<template>
  <div>
    <el-container>
      <el-header>
        <el-row :gutter="20">
          <el-col :span="5">
            <el-input v-model="addStudentInfo.name" placeholder="请输入姓名"></el-input>
          </el-col>
          <el-col :span="5">
            <el-input v-model="addStudentInfo.age" placeholder="请输入年龄"></el-input>
          </el-col>
          <el-col :span="5">
            <el-input v-model="addStudentInfo.address" placeholder="请输入地址"></el-input>
          </el-col>
          <el-col :span="4">
            <el-button type="primary" @click="addStudent">添加</el-button>
          </el-col>
          <el-col :span="4">
            <el-button type="danger">删除</el-button>
          </el-col>
        </el-row>
      </el-header>
      <el-main>
        <el-table :data="tableData" style="width: 100%">
          <el-table-column type="selection" width="55"></el-table-column>
          <el-table-column prop="id" label="序号" width="180"></el-table-column>
          <el-table-column prop="name" label="姓名" width="180"></el-table-column>
          <el-table-column prop="age" label="年龄" width="180"></el-table-column>
          <el-table-column prop="address" label="地址"></el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button type="primary" icon="el-icon-edit" circle @click="updataDialog(scope.$index, scope.row)"></el-button>
              <el-dialog title="修改信息" :visible.sync="dialogFormVisible">

                <el-form :model="updataStudentInfo">
                  <el-form-item label="姓名">
                    <el-input v-model="updataStudentInfo.name" placeholder="请输入姓名"></el-input>
                  </el-form-item>
                  <el-form-item label="年龄">
                    <el-input v-model="updataStudentInfo.age" placeholder="请输入年龄"></el-input>
                  </el-form-item>
                  <el-form-item label="地址">
                    <el-input v-model="updataStudentInfo.address" placeholder="请输入地址"></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="updataStudent()">确 定</el-button>
                </div>
              </el-dialog>

              <el-popconfirm title="这是一段内容确定删除吗?" @onConfirm="deleteStudent(scope.$index, scope.row)">
                <el-button type="danger" icon="el-icon-delete" circle slot="reference"></el-button>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination background layout="prev, pager, next" :total="total" :page-size="pageSize"
          @current-change="pageChange" :current-page.sync="currentPage">
        </el-pagination>
      </el-main>
    </el-container>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        addStudentInfo: {
          name: null,
          age: null,
          address: null,
        },
        updataStudentInfo: {
          di: null,
          name: null,
          age: null,
          address: null,
        },
        tableData: [{
          id: null,
          name: null,
          age: null,
          address: null,
        }, ],
        pageSize: 4,
        currentPage: null,
        total: null,
        //控制编辑按钮 弹出from表单,true为弹出
        dialogFormVisible: false,
      };
    },
    mounted() {

      this.getTotal();
      this.pageChange();

    },
    methods: {
      //更新信息
      updataStudent(){
        if (this.updataStudentInfo.name == null ||
          this.updataStudentInfo.age == null ||
          this.updataStudentInfo.address == null) {
          this.$message.error('请完整输入信息');
          return
        } else if (!/^[0-9]*$/.test(this.updataStudentInfo.age)) {
          this.$message.error('年龄只能为数字');
          return
        }
        let postData = this.qs.stringify({
          id: this.updataStudentInfo.id,
          name: this.updataStudentInfo.name,
          age: this.updataStudentInfo.age,
          address: this.updataStudentInfo.address,
        });
        this.axios({
            method: 'post',
            url: '/student/updataStudent',
            data: postData,
          })
          .then(response => (
            this.$message(response.data)
          ))
          .catch(function (error) {
            console.log(error);
          })
        this.pageChange();
        this.dialogFormVisible = false;
      },
      

      //弹出更新信息框
      updataDialog(index, row){

        this.dialogFormVisible = true;
        this.updataStudentInfo = {
          id: row.id,
          name: row.name,
          age: row.age,
          address: row.address
        }
      },
      //删除学生
      deleteStudent(index, row) {

        let postData = this.qs.stringify({
          id: row.id
        });
        this.axios({
            method: 'post',
            url: '/student/deleteStudent',
            data: postData,
          })
          .then(response => (
            this.$message(response.data)
          ))
          .catch(function (error) {
            console.log(error);
          })
        this.pageChange();
      },


      //添加学生
      addStudent() {
        if (this.addStudentInfo.name == null ||
          this.addStudentInfo.age == null ||
          this.addStudentInfo.address == null) {
          this.$message.error('请完整输入信息');
          return
        } else if (!/^[0-9]*$/.test(this.addStudentInfo.age)) {
          this.$message.error('年龄只能为数字');
          return
        }
        let postData = this.qs.stringify({
          name: this.addStudentInfo.name,
          age: this.addStudentInfo.age,
          address: this.addStudentInfo.address,
        });
        this.axios({
            method: 'post',
            url: '/student/insertStudent',
            data: postData,
          })
          .then(response => (
            this.$message(response.data)
          ))
          .catch(function (error) {
            console.log(error);
          })
        this.getTotal();
        this.pageChange();
        this.addStudentInfo = {
          name: null,
          age: null,
          address: null,
        }
      },


      //获取数据库中的总数的方法
      getTotal() {
        this.axios({
            method: 'post',
            url: '/student/getTotal',
          })
          .then(response => (this.total = response.data))
          .catch(function (error) {
            console.log(error);
          })
      },
      //分页查询,改变页数时会执行的方法
      pageChange() {
        let postData = this.qs.stringify({
          pageNum: this.currentPage,
          pageSize: this.pageSize
        });
        this.axios({
            method: 'post',
            url: '/student/pageQuery',
            data: postData,
          })
          .then(response => (this.tableData = response.data))
          .catch(function (error) {
            console.log(error);
          })
      }
    }
  };
</script>


<style>
</style>

src\views\Home.vue

<template>
  <div class="home">
    <HelloWorld msg="首页"/>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  }
}
</script>

src\App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">首页</router-link> |
      <router-link to="/about">关于</router-link>
    </div>
    <router-view/>
  </div>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

src\main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import axios from 'axios'
import 'element-ui/lib/theme-chalk/index.css';
import VueAxios from 'vue-axios'
import qs from 'qs'

Vue.use(VueAxios, axios, qs)
Vue.config.productionTip = false
Vue.use(ElementUI);

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

vue.config.js

解决跨域问题最关键的一步

module.exports = {
    devServer: {
        host: 'localhost',
        port: 8084,
        //以上的ip和端口是我们本机的;下面为需要跨域的
        proxy: { //配置跨域
            '/student': {
                target: 'http://localhost:9090', //这里后台的地址模拟的;应该填写你们真实的后台接口
                changOrigin: true, //允许跨域
            }
        }
    }
}

实现效果:
在这里插入图片描述

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值