ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

【SpringBoot】学生信息录入和查阅的前后端分离的小项目,SpringBoot+React+MySQL,手把手教学

2021-11-19 23:00:44  阅读:218  来源: 互联网

标签:SpringBoot material public React ui Student MySQL import id


 运行效果

 

点击录入,下方的状态会变成数据更新成功。

 

 刷新student_db数据库,发现学生数据被录入数据库并成功获取展示到花名册页面。

 运行演示完,写一下这个小项目的步骤。

新建数据库student_db,在该数据库下新建表stu_tb

CREATE TABLE `stu_tb` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `major` varchar(128) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  `gender` varchar(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

 新建SpringBoot项目

 

 配置项目

打开项目根目录下的pom.xml文件,配置项目基本和其他依赖。

依赖:如果报红需要reimport

<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>


		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</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-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

打开resource目录下的application.properties文件,开始配置数据库信息。

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/student_db?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=你的数据库用户名,默认root
spring.datasource.password=你的数据库密码

开始写后端代码

model

新建一个包,model,在model包下新建一个类Student,

在写好类的私有属性后,快捷键alt+insert自动生成getter 和setter方法,自动生成重写toString方法。加上注解,自动导包。

最后,你的Student.java代码如下:

package com.liulei.stuinfo.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDate;

@Entity
@Table(name = "stu_tb")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Integer id;

    @Column
    private String name;

    @Column
    private String major;

    @Column
    private LocalDate birthday;

    @Column
    private String gender;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", major='" + major + '\'' +
                ", birthday=" + birthday +
                ", gender='" + gender + '\'' +
                '}';
    }

    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;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }

    public LocalDate getBirthday() {
        return birthday;
    }

    public void setBirthday(LocalDate birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

dao

StudentDAO.java

package com.liulei.stuinfo.dao;

import com.liulei.stuinfo.model.Student;

import java.util.List;

public interface StudentDAO {
    List<Student> get();

    Student get(int id);

    void save(Student student);

    void delete(int id);
}

StudentDAOImpl.java

package com.liulei.stuinfo.dao;

import com.liulei.stuinfo.model.Student;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import java.util.List;

@Repository
public class StudentDAOImpl implements StudentDAO{
    @Autowired
    private EntityManager entityManager;

    @Override
    public List<Student> get() {
        Session currSession = entityManager.unwrap(Session.class);
        Query<Student> query = currSession.createQuery("from Student", Student.class);
        List<Student> list = query.getResultList();
        return list;
    }

    @Override
    public Student get(int id) {
        Session currSession = entityManager.unwrap(Session.class);
        Student stu = currSession.get(Student.class, id);
        return stu;
    }

    @Override
    public void save(Student Student) {
        Session currSession = entityManager.unwrap(Session.class);
        currSession.saveOrUpdate(Student);
    }

    @Override
    public void delete(int id) {
        Session currSession = entityManager.unwrap(Session.class);
        Student stu = currSession.get(Student.class, id);
        currSession.delete(stu);
    }
}

service

StudentService.java

package com.liulei.stuinfo.service;

import com.liulei.stuinfo.model.Student;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

public interface StudentService {

    @Transactional
    List<Student> get();

    @Transactional
    Student get(int id);

    @Transactional
    void save(Student student);

    @Transactional
    void delete(int id);
}

StudentServiceImpl.java

package com.liulei.stuinfo.service;

import com.liulei.stuinfo.dao.StudentDAO;
import com.liulei.stuinfo.model.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class StudentServiceImpl implements StudentService{

    @Autowired
    private StudentDAO studentDao;

    @Transactional
    @Override
    public List<Student> get() {
        return studentDao.get();
    }

    @Transactional
    @Override
    public Student get(int id) {
        return studentDao.get(id);
    }

    @Transactional
    @Override
    public void save(Student student) {
        studentDao.save(student);

    }

    @Transactional
    @Override
    public void delete(int id) {
        studentDao.delete(id);

    }
}

controller

StudentController.java
package com.liulei.stuinfo.controller;

import com.liulei.stuinfo.model.Student;
import com.liulei.stuinfo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/student")
    public List<Student> get() {
        return studentService.get();
    }

    @PostMapping("/student")
    public Student save(@RequestBody Student student) {
        studentService.save(student);
        return student;
    }

    @GetMapping("/student/{id}")
    public Student get(@PathVariable int id) {
        return studentService.get(id);
    }

    @DeleteMapping("/student/{id}")
    public String delete(@PathVariable int id) {
        studentService.delete(id);
        return "Student removed with id "+id;

    }

    @PutMapping("/student")
    public Student update(@RequestBody Student student) {
        studentService.save(student);
        return student;
    }
}
StuinfoApplication.java无需修改

接着开始写前端代码-React

在工作区目录执行create-react-app stuinfo创建React项目

cd stuinfo进入到项目根目录,

再在components建立AddStudent.js用以录入学生信息的界面,本项目前端样式用的@material-ui,

需要提前添加到依赖中:yarn add 

yarn add @material-ui/core
yarn add @material-ui/icons
import React from "react";
import 'isomorphic-fetch';
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import { Link } from "react-router-dom";
import Grid from "@material-ui/core/Grid";
import GroupIcon from "@material-ui/icons/Group";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";

const useStyles = makeStyles(theme => ({
  paper: {
    marginTop: theme.spacing(7),
    display: "flex",
    flexDirection: "column",
    alignItems: "center"
  },
  avatar: {
    margin: theme.spacing(1),
    backgroundColor: theme.palette.secondary.main
  },
  form: {
    width: "100%",
    marginTop: theme.spacing(3)
  },
  submit: {
    margin: theme.spacing(3, 0, 2)
  },
  textField: {
    marginLeft: theme.spacing(1),
    marginRight: theme.spacing(1),
    width: "100%"
  }
}));

export default function AddStudent() {
  const classes = useStyles();
  const [firstLoad, setLoad] = React.useState(true);

  const [selectedDate, setSelectedDate] = React.useState(
    new Date("1999-12-12T21:11:11")
  );
  const [name, setName] = React.useState("");
  const [major, setMajor] = React.useState("");
  const [gender, setGender] = React.useState("");

  const handleDateChange = date => setSelectedDate(date.target.value);
  const handleNameChange = event => setName(event.target.value);
  const handleMajorChange = event => setMajor(event.target.value);
  const handleGenderChange = event => setGender(event.target.value);

  const [message, setMessage] = React.useState("暂未保存任何内容");

  async function sampleFunc(toInput) {
    const response = await fetch("/api/student", {
      method: "POST", 
      mode: "cors", 
      cache: "no-cache", 
      credentials: "same-origin",
      headers: {
        "Content-Type": "application/json"
       
      },
      redirect: "follow", 
      referrerPolicy: "no-referrer",
      body: JSON.stringify(toInput) header
    });
    let body = await response.json();
    console.log(body.id);
    setMessage(body.id ? "数据更新成功" : "数据更新失败");
  }

  const handleSubmit = variables => {
    const toInput = { name, major, gender, birthday: selectedDate };
    sampleFunc(toInput);
    setName("");
    setMajor("");
    setGender("");
  };

  if (firstLoad) {
    // sampleFunc();
    setLoad(false);
  }

  return (
    <Container component="main" maxWidth="xs">
      <CssBaseline />
      <div className={classes.paper}>
        <Avatar className={classes.avatar}>
          <GroupIcon />
        </Avatar>
        <Typography component="h1" variant="h5">
          学生花名册
        </Typography>
        <form className={classes.form} noValidate>
          <Grid container spacing={2}>
            <Grid item xs={12}>
              <TextField
                variant="outlined"
                required
                fullWidth
                id="name"
                value={name}
                label="姓名"
                name="name"
                autoComplete="name"
                onChange={handleNameChange}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                autoComplete="major"
                name="major"
                variant="outlined"
                required
                fullWidth
                value={major}
                id="major"
                label="专业"
                onChange={handleMajorChange}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <TextField
                variant="outlined"
                required
                fullWidth
                id="gender"
                value={gender}
                label="性别"
                name="gender"
                autoComplete="gender"
                onChange={handleGenderChange}
              />
            </Grid>
            <Grid item xs={12}>
              <TextField
                id="date"
                label="生日"
                type="date"
                defaultValue="1999-12-12"
                className={classes.textField}
                InputLabelProps={{
                  shrink: true
                }}
                onChange={handleDateChange}
              />
            </Grid>
          </Grid>
          <Button
            // type="submit"
            fullWidth
            variant="contained"
            color="primary"
            preventDefault
            className={classes.submit}
            onClick={handleSubmit}
          >
            录入
          </Button>

          <Grid container justify="center">
            <Grid item>
              <Link to="/view">查看学生花名册</Link>
            </Grid>
          </Grid>
        </form>
        <Typography style={{ margin: 7 }} variant="body1">
          状态: {message}
        </Typography>
      </div>
    </Container>
  );
}

再在components建立Table.js用以输出显示学生花名册

import React from "react";
import 'isomorphic-fetch';
import { makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Avatar from "@material-ui/core/Avatar";
import GroupIcon from "@material-ui/icons/Group";
import { Link } from "react-router-dom";
import Typography from "@material-ui/core/Typography";
import CircularProgress from "@material-ui/core/CircularProgress";

const useStyles = makeStyles(theme => ({
  table: {
    minWidth: 600
  },
  avatar: {
    margin: theme.spacing(1),
    backgroundColor: theme.palette.secondary.main
  },
  paper: {
    display: "flex",
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "center",
    margin: `10px`,
    height: "100%",
    width: "99%",
    marginTop: theme.spacing(7)
  },
  link: {
    color: "rgba(0,0,0,0.65)",
    textDecoration: "none",
    marginLeft: "10%",
    alignSelf: "flex-start",
    "&:hover": {
      color: "rgba(0,0,0,1)"
    }
  }
}));

export default function SimpleTable() {
  const classes = useStyles();

  const [data, upDateData] = React.useState([]);
  const [firstLoad, setLoad] = React.useState(true);
  let isLoading = true;

  async function sampleFunc() {
    let response = await fetch("http://localhost:8081/api/student");
    let body = await response.json();
    upDateData(body);
  }

  if (firstLoad) {
    sampleFunc();
    setLoad(false);
  }

  if (data.length > 0) isLoading = false;

  return ((
    <div className={classes.paper}>
      <Avatar className={classes.avatar}>
        <GroupIcon />
      </Avatar>
      <Typography component="h1" variant="h5">
        学生花名册
      </Typography>

      {isLoading ? (
        <CircularProgress />
      ) : (
        <TableContainer
          style={{ width: "80%", margin: "0 10px" }}
          component={Paper}
        >
          <Table className={classes.table} aria-label="simple table">
            <TableHead>
              <TableRow>
                <TableCell align="center">姓名</TableCell>
                <TableCell align="center">专业</TableCell>
                <TableCell align="center">性别</TableCell>
                <TableCell align="center">生日</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {data?.map(row => (
                <TableRow key={row.name}>
                  <TableCell align="center">{row.name}</TableCell>
                  <TableCell align="center">{row.major}</TableCell>
                  <TableCell align="center">{row.gender}</TableCell>
                  <TableCell align="center">{row.birthday}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      )}
      <Link className={classes.link} to="/">
        {" "}
        <Typography align="left">
          &#x2190; 返回录入界面
        </Typography>{" "}
      </Link>
    </div>
   ) );
}

再在App.js中引入上述组件

import React, { Component } from "react";
import AddStudent from "./components/AddStudent";
import { Route,Routes, BrowserRouter as Router } from "react-router-dom";
import Table from "./components/Table";

class App extends Component {
  render() {
    return (
      <Router>
        <Routes>
        <Route exact path="/" componet=<AddStudent/> />
        <Route exact path="/view" componet=<Table/> />
        </Routes>
      </Router>
    );
  }
}

export default App;

最后在index.js中引入App

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
    <App />,
    document.getElementById('root')
 );

最后在项目根目录执行yarn start就可以启动项目了。在此之前需要先启动springboot的主程序类

StuinfoApplication

标签:SpringBoot,material,public,React,ui,Student,MySQL,import,id
来源: https://blog.csdn.net/lei20172017/article/details/121430452

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有