首页 > 编程语言 >Springboot+Vue 搭建简单的学生信息管理系统(附源码)

Springboot+Vue 搭建简单的学生信息管理系统(附源码)

时间:2024-08-13 12:53:55浏览次数:9  
标签:axios Vue Springboot 前端 接口 源码 user student data

前言

        本博客旨用最基础的知识来开发一个最简单的学生信息管理系统。通过使用Springboot+Vue+Mybatis-plus+axios技术,能帮助大家更好的了解前后端分离的大致流程和框架。文章末尾附有源码和启动项目的想法,赶时间的同学可以直接下载源码进行学习

一、技术栈

1. 前端

  • Vue2
  • element-ui
  • bootstrap5
  • axios

2. 后端

  • Springboot2
  • Mybatis-plus
  • Gson

3. 数据库

  • mysql

4.开发工具

  • IDEA

该文章默认读者已经掌握了基础的 html+css+js+java知识,了解这些基本的知识就够用于这个简单的学生信息管理系统的开发了

读者跟着小编一步一步做就可以实现如下页面

当然如果没时间跟着操作文章末尾也附了源码和sql表。

二、准备工作

1、Vue 脚手架

首先在一个非系统盘的盘下创建一个文件夹,然后在此打开终端

输入 vue create front 搭建前端vue脚手架,前端文件名为front,也可以自己命名

选择vue2 版本回车

回车后它等一些时间它就帮我们构造好脚手架了

2、创建数据库

启动数据库服务后,新建一个demo的数据库

(1)student 设计表

(2)user 设计表

(3)可以分别往表里面填一些数据

student表

user表

三、后端实现

1. 建立项目

1. 打开 IDEA,新建一个项目,如下图

找到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>

    <groupId>org.example</groupId>
    <artifactId>mybatis_plus01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <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.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
    </dependencies>
</project>

然后刷新一下maven,maven的配置我上一篇博客也有介绍,需要的同学可以自行查看

2. 新建 application.yaml 文件

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=UTF-8&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver

  3. 接下来我们根据层的思想,建立几个必要的软件包

首先是先建立一个启动类,帮助我们启动项目,是项目启动的入口如上图,代码如下。

package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication        // 标识为启动类
public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);
    }
}

然后建立几个“层”

(1)、pojo层 也称entity层,用于存放实体类的地方,里面新建了一个student实体类,里面的属性要和数据库中的属性值和类型一一对应

(2)、mapper 层,也称dao层,是数据持久层,与数据库交互,把数据访问代码也业务逻辑分离开来,增强可维护性

(3)、controller 层,主要负责接收和处理来自客户端的请求,并决定如何响应式这些请求。

2. 后端增删改查接口

首先在StudentController类下使用@Autowired 注解,把mapper包下的接口和实体类关联起来。@Autowired 注解,可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作。

再使用创建Gson对象 把查询出来的数据转成字符串

    @Autowired
    private StudentMapper studentMapper;

    private Gson gson = new Gson();

然后就可以写我们的增删改查的路由规则了

(1)、查询接口

 @GetMapping("/students")
    public String getStudents(){
        List<Student> students = studentMapper.selectList(null);
        return gson.toJson(students);
    }

代码解释 

查询接口使用 Get请求,定义路由的名字为students,使用Mybatis-plus插件中的BaseMapper类中的selectList方法,帮助我们查询出所有的数据。因为不需要包装,所以传一个null参数,然后用一个参数接收,最后以Json的类型返回出去到前端去接受

(2)、新增接口

 @PostMapping("/add")
    public void addStudents(@RequestBody Student student){
        studentMapper.insert(student);
    }

代码解释

使用Post发送请求,路由的名字为add,也是使用Mybatis-plus插件中的BaseMapper类中的insert方法帮我们把数据插入到数据库中;其中使用@RequestBody注解,接受前端发送过来的请求体的内容,自动转成一个Student对象。简化了数据绑定的过程。

(3)、删除接口

 @PostMapping("/delete")
    public void removeStudents(@RequestBody Student student){
        studentMapper.deleteById(student);
    }

删除、增加和更新的接口写法都差不多,只是用到不同的方法而已

(4)、更新接口

@PostMapping("/update")
    public void updataStudent(@RequestBody Student student){
        studentMapper.updateById(student);
    }

(5)、登录接口

@PostMapping("/login")
    public String loginStudent(@RequestBody User user){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.setEntity(user);
        User user_selected = userMapper.selectOne(userQueryWrapper);
        if(user_selected == null){
            return "0";           // 返回到前端去校验
        }
        return "1";
    }

 代码解释

userMapper.selectOne方法可以帮我们查到一条数据,它接收的参数是querywrapper,创建这个对象去实体类查找user,最后判断查出来的数据是否为空,返回到前端去判断校验

(6)、注册接口

@PostMapping("register")
    public void reqister(@RequestBody User user){
        userMapper.insert(user);
    }

注册接口其实就是类似于新增接口。可以在前端进行数据校验,再决定是否插入到数据库中

最后写好是这样子的

StudentController

UserController

最后在Application类中启动项目

注!!! 如果报如下错误

 该错误说明 你电脑的8080端口已经被其他的进程占用了,需要结束该8080端口的进程再启动项目

解决方法:

1.鸠占鹊巢。结束进程的方法在我上一篇博客有具体介绍,就是先输入

netstat -aon|findstr 8080 查看占用情况,记住 PID值 ,然后输入 taskkill /PID "查出来的PID值" /F 命令结束进程,注意,PID是一串数字。

2. 改变启动的端口号。在application.yaml 文件中加入如下代码再启动即可

3.测试接口

        写好后端接口和成功启动后端之后,我们使用 Postman 工具来帮我们测试一下写的接口对不对(读者如果按着上面的步骤一步一步来并且后端能启动成功基本是写对了)。如果读者比较赶时间则可以跳过这测试小节,去看 前端增删改查。

我们打开Postman工具,如下操作

1. 查询接口

报了405错误是因为发送的 http 请求和后端路由写的请求不一样,查询应该是 Get 请求

改一下请求方式即可查出,出现如上数据则表示我们写的路由没有问题。

小tips:

http请求常见有如下几种情况:

  • 200 -> 请求成功
  • 401 -> 没有足够的权限来访问资源,通常是用户没有登录成功
  • 403 -> 服务端设置不允许访问
  • 404 -> 请求的资源不存在,检查访问的路径是否正确
  • 405 -> 发送的http请求类型错误,可能是post类型的请求写成了get
  • 500 -> 服务端错误,后端代码出问题

2. 新增接口

接下来我们测试 add 接口

然后去看数据库中有没有成功插入数据,到数据库的demo中的student表中刷新一下

数据成功插入,表明add接口也没有什么问题

3. 更新接口

在数据库中更新一下可以看到数据同步更新到数据库中了。

4. 删除接口

删除接口只需要改变路由即可根据id字段进行删除操作,到数据库中去查看,该id字段的行记录已被删除

测试所有的接口都没问题后,我们就可以通过前端去美化增删改查的操作了

四、前端实现

我们把student-admin文件夹拖动在IDEA中打开,该文件夹下有两个文件,分别是back和front。front文件是我们用脚手架创建好的前端文件。

然后在Application.java 启动类中去启动项目。

注!!!如果左上角没有启动按钮,是因为maven项目没有引进来。如下情况

解决:在pom.xml文件中点击鼠标右键,添加为maven项目,然后刷新一下maven,再到启动类去启动就可以启动项目了

1. 安装工具

打开终端,用IDEA里面的终端,然后进入front文件去下载

报警告的提示不必理会,只要没报错就行。

(1) 安装 axios

npm i axios

(2) 安装 bootstrap。

bootstrap官网地址:下载 Bootstrap · Bootstrap v5 中文文档 v5.3 | Bootstrap 中文网

我们选择5.2的版本进行下载

npm install [email protected]

然后在main.js 里面引用

import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'

(3)安装 element-ui 组件

npm i element-ui

也在main.js 中去引用

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI)

2. 编写前端代码

首先我们对前端项目改造一下

1. 删除多余的文件

2. 改造App.vue 文件

这是每个vue文件的模板框架

3. App.vue 中代码

<template>
  <div id="app">
    <div class="col-8 offset-2">
      <table class="table caption-top table-hover ">
        <caption class="text-center">
          <br>
          <h1><b style="color:rgb(0, 191, 255);">学生管理系统</b></h1>
          <br>
          <el-input type="text" placeholder="请输入姓名" class="w-25" v-model="search_name" style="margin-right: 2px;"/>
          <el-button type="success" @click="search">搜索</el-button>
          <el-button type="primary" @click="getStudents">获取学生信息</el-button>
          <el-button type="warning" @click="dialogVisible = true">添加学生</el-button>

          <el-dialog
              title="提示"
              :visible.sync="dialogVisible"
              width="30%"
              :before-close="handleClose">
            <div>添加学生信息</div>
            <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false" type="warning">取 消</el-button>
    <el-button type="primary" @click="addStudent">添 加</el-button>
  </span>
            <span>学号</span><input v-model="newStudent.number" required/><br>
            <span>姓名</span><input v-model="newStudent.name"/><br>
            <span>年龄</span><input v-model.number="newStudent.age"/><br>
            <span>语文</span><input v-model.number="newStudent.chi"/><br>
            <span>数学</span><input v-model.number="newStudent.math"/><br>
            <span>英语</span><input v-model.number="newStudent.eng"/><br>
          </el-dialog>

          <!--登录-->

          <el-button type="primary" @click="dialogVisiblelogin = true" style="margin: 0 6px;">点击登录</el-button>

          <el-dialog
              title="提示"
              :visible.sync="dialogVisiblelogin"
              width="30%"
              :before-close="handleClose">
            <span>用户名</span>
            <input type="text" v-model="user_for_login.username"><br>
            <span>密码</span>
            <input type="password" v-model="user_for_login.password">

            <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisiblelogin = false" type="warning">取 消</el-button>
    <el-button type="primary" @click="login">登 录</el-button>
  </span>
          </el-dialog>

          <!--注册-->

          <el-button type="info" @click="dialogVisibleregister = true">点击注册</el-button>

          <el-dialog
              title="提示"
              :visible.sync="dialogVisibleregister"
              width="30%"
              :before-close="handleClose">
            <span>用户名</span>
            <input type="text" v-model="user_for_register.username"><br>
            <span>密码</span>
            <input type="password" v-model="user_for_register.password"><br>
            <span>确定密码</span>
            <input type="password" v-model="user_for_register.confirmPassword">
            <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisibleregister = false" type="warning">取 消</el-button>
    <el-button type="primary" @click="register">注 册</el-button>
  </span>
          </el-dialog>
        </caption>
        <thead>
        <tr>
          <th scope="col">学号</th>
          <th scope="col">姓名</th>
          <th scope="col">年龄</th>
          <th scope="col">语文</th>
          <th scope="col">数学</th>
          <th scope="col">英语</th>
          <th scope="col">操作</th>

        </tr>
        </thead>
        <tbody>                        <!--tbody中放Studnet 组件的数据      把student的值传递到Student组件中-->
        <Student v-for="stu in students_for_page" :key="stu.id" :student="stu"></Student>
        </tbody>                                     <!--student 是列表 ,stu遍历 students这个列表然后赋值给student的-->
      </table>
      <div class="text-center">
        <el-button-group v-show="is_show_page">
          <el-button type="primary" icon="el-icon-arrow-left" @click="last_page" style="left: -100px;">上一页</el-button>
          <el-button type="primary" @click="next_page" style="left: 100px;">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
        </el-button-group>
      </div>
    </div>
  </div>
</template>

<script>

import axios from 'axios'
import Student from './components/Student'
export default {
  name: 'App',
  components: {
    Student
  },
  data() {
    return {
      is_show_page: false,
      search_name: "",        // 模糊查询的名字
      user_for_login:{
        username: "",
        password: "",
      },
      user_for_register:{
        username: "",
        password: "",
        confirmPassword: "",
      },
      page:1,
      students:[],
      dialogVisible: false,
      dialogVisiblelogin: false,            // 对话框默认关闭
      dialogVisibleregister: false,
      newStudent:{                         // 新增对象
        number:"",
        name:"",
        age:"",
        chi:"",
        math:"",
        eng:"",
      }
    }
  },
  methods:{
    getStudents(){
      if(sessionStorage.getItem("isLogined") == "true") {         // 判断用户是否登录过
        axios({
          url:"http://localhost:9090/students",
          method: 'GET',
        }).then(res=>{
          console.log(res.data);
          this.students = res.data;     // 回调函数,赋值给students列表
        })
      }
      else{
        this.$alert("请先登录")
      }
      this.is_show_page = true
    },
    handleClose(done) {
      this.$confirm('确认关闭?')
          .then(() => {
            done();
          })
          .catch(()=> {});
    },
    addStudent() {
      if(this.newStudent.number != '' &&this.newStudent.age!='' &&this.newStudent.name!=''
          && this.newStudent.chi!='' && this.newStudent.math !=''&& this.newStudent.eng){        // 校验
        axios({
          url: "http://localhost:9090/add",
          method: "POST",
          data:this.newStudent
        }),
            this.$alert("添加成功!");
      }
      else{
        alert("请输入完整信息!");
      }

      this.dialogVisible = false
    },
    next_page() {              // 下一页
      this.page += 1;
    },
    last_page() {
      this.page -= 1;         // 上一页
    },
    login() {
      axios({
        url:"http://localhost:9090/login",
        data:this.user_for_login,
        method: "POST",
      }).then(res =>{
        console.log(res.data);
        if(res.data == "1") {            // 后端返回的数据,用于判断
          sessionStorage.setItem("isLogined","true");
          this.$alert("登录成功!");
        }
        else {
          alert("用户名或密码错误");
        }
      })
      this.dialogVisiblelogin = false
    },
    register() {
      if(this.user_for_register.password == this.user_for_register.confirmPassword ){
        axios({
          url: "http://localhost:9090/register",
          method: "POST",
          data:this.user_for_register
        })
        this.$alert("注册成功!");
      }
      else {
        alert("两次密码不一致!");
      }
      this.dialogVisibleregister = false
    },
    search(){
      axios({
        url: "http://localhost:9090/search",
        method:"POST",
        data: {
          name:this.search_name
        }
      }).then(res => {
        this.students = res.data;
      })
    }
  },
  computed:{                  //  分页
    students_for_page(){
      return this.students.slice(this.page*5 - 5,this.page*5) ;
    }
  }
}
</script>

<style>

</style>

4. Student.vue 中代码

<template>
  <tr>
    <td v-show="!is_edit">{{ student.number }}</td>
    <td v-show="!is_edit">{{ student.name }}</td>
    <td v-show="!is_edit">{{ student.age }}</td>
    <td v-show="!is_edit">{{ student.chi }}</td>
    <td v-show="!is_edit">{{ student.math }}</td>
    <td v-show="!is_edit">{{ student.eng }}</td>
    <td v-show="!is_edit">
      <el-button type="primary" @click="modify">修改</el-button>
    </td>
    <td v-show="!is_edit">
      <el-button type="danger" @click="deleteStudent">删除</el-button>
    </td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model="student.number"/></td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model="student.name"/></td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model.number="student.age"/></td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model.number="student.chi"/></td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model.number="student.math"/></td>
    <td v-show="is_edit"><input class="w-50" type="text" v-model.number="student.eng"/></td>
    <td v-show="is_edit">
      <el-button type="primary" @click="save">保存</el-button>
    </td>
    <td v-show="is_edit">
      <el-button type="danger">删除</el-button>
    </td>
  </tr>
</template>

<script>

import axios from 'axios';

export default {
  props:["student"],             //   接受App组件传来的数据
  data() {
    return {
      is_edit:false
    }
  },
  methods:{
    modify(){
      this.is_edit=true;
    },
    save(){
      axios({
        url:"http://localhost:9090/update",
        method: 'Post',
        data:this.student
      })
      this.is_edit=false;
    },
    deleteStudent() {
      axios({
        url:"http://localhost:9090/delete",
        method: 'Post',
        data:this.student
      }),
          location.reload();    // 重新刷新页面
    }
  }
}
</script>

<style>
</style>

最后 在终端进入 front 文件执行 npm run serve 就可以启动前端项目了

注!!!如果运行前端报了如下错误

再重新执行 npm run serve 启动项目即可

可以直接点击上面第一个链接,也可以赋值到你喜欢的浏览器中去打开

 登录的账号密码在数据库中的user表可看到

至此,整个学生信息管理系统就完成了

总结

         该系统作为一个新手练手的项目是非常合适的,可以在项目中了解前后端分离的具体实现。也可以增强对前端和后端框架的熟悉程度,只有把学到的理论知识应用到实际的开发当中,才会知道学到的这些知识是怎样实现的,具体实现了怎样的功能等。在学习的过程中可以先学基础的知识,然后找个简单的项目来操作,再去学对应的理论知识,这才是一种良好的学习方法(有点啰嗦了.dog.jpg)

直接下载源码的同学可以在 front 文件下的 README.md 文件查看怎么启动项目

源码 : https://pan.baidu.com/s/1flOAVDl0NyHzi9nAS0zutg?pwd=1688 

b站参教视频:【从零开始用Springboot+Mybatis-plus+Vue做一个前后端分离的学生管理系统-哔哩哔哩】 https://b23.tv/Pd0bpfx

最后每篇一唠:

        有些人见面要坐汽车,有些人见面要坐火车,有些人见面要做梦。

标签:axios,Vue,Springboot,前端,接口,源码,user,student,data
From: https://blog.csdn.net/2401_83017604/article/details/141128524

相关文章

  • 汽车、校车管理信息系统-计算机毕设Java|springboot实战项目
    ......
  • 计算机毕业设计django+vue酒店客房管理系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着旅游业的蓬勃发展,酒店行业作为旅游产业链中的关键环节,其管理效率与服务质量直接影响到顾客的满意度与忠诚度。传统的酒店客房管理方式......
  • 【计算机毕设选题推荐】基于SpringBoot的springboot仓库点单小程序
    前言:我是天码编程,从事计算机开发行业数年,专注Java程序设计开发、源码分享、技术指导和毕业设计,欢迎各位前来交流讨论......
  • 【Java毕设项目推荐】基于SpringBoot的springboot二手家电管理平台
    前言:我是天码编程,从事计算机开发行业数年,专注Java程序设计开发、源码分享、技术指导和毕业设计,欢迎各位前来交流讨论......
  • 【Java毕设选题推荐】基于SpringBoot的springbootstone音乐播放器的设计与实现
    前言:我是IT源码社,从事计算机开发行业数年,专注Java领域,专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务......
  • SSM基于vuejs的二手车交易平台ue120 虚拟支付
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:用户,卖家,汽车类型,二手汽车,汽车预订,汽车尾款,汽车信息,汽车评估开题报告内容一、项目背景随着汽车产业的快速发展和互联网技术的普及,二手车市场逐......
  • 第17天 信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等
    时间轴演示案例指纹识别—本地工具—GotoScanPython—开发框架—Django&FlaskPHP—开发框架—ThinkPHP&Laravel&YiiJava—框架组件—FastJson&Shiro&Solr&Spring知识点1.CMS指纹识别—不出网程序识别解决:CMS识别到后前期漏洞利用和代码审计一般PHP开发居多,利用源码......
  • 在Vue3中实现自定义指令
    一、前言我们需要明白为什么需要自定义一个指令,其实就是想更加简洁地重复使用操作DOM的逻辑,这就和组件化和组合式函数差不多。不管是Vue内置的指令还是自定义的指令,都有类似于组件的生命周期,我们可以在不同的生命周期完成不同的逻辑操作,并绑定到组件元素上,这样就产生了自定义指......
  • 第二十四篇- SprintBoot+vue内网穿透
    参考链接:https://blog.csdn.net/qq_45774406/article/details/138768624一、将SpringBoot打包成war1.修改pom.xmlpom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="ht......
  • Vue - toValue
    作用将值、refs或getters规范化为值。这与unref()类似,不同的是此函数也会规范化getter函数。如果参数是一个getter,它将会被调用并且返回它的返回值。简单来说,toValue函数的目的是将传入的值规范化为一个普通的值,不管传入的是普通值、ref对象,还是一个返回值的getter......