【JAVA MVC】快速搭建简易学生信息管理系统

场景导入

        在现代Web开发中,选择合适的技术栈对于构建稳健和可扩展的应用程序至关重要。本篇博客将介绍一种非常流行且强大的技术组合,如Spring Boot、JPA、Thymeleaf、MySQL以及额外的Bootstrap库。这个组合不仅能够帮助开发人员高效地构建Web应用程序,还能提供更好的用户体验和简化开发流程,下面来跟着某要求进行开发一个学生信息管理系统,要求如图:

一、技术介绍

1.Spring Boot:

        Spring Boot是一种基于Spring框架的开发工具,它通过提供自动化配置和约定优于配置的原则,简化了Java应用程序的开发过程。Spring Boot能够极大地提高开发效率,同时还提供了丰富的插件和功能,例如内嵌服务器、自动化依赖管理和配置,以及集成了许多常用的开发组件。

2.JPA(Java Persistence API)

        JPA是Java平台上的一种ORM(对象关系映射)规范,它提供了一种将Java对象映射到关系数据库中的方式。与传统的SQL编程相比,使用JPA可以更加方便地操作数据库,提供了对象级别的查询和持久化操作,减少了开发者的数据库访问困扰。

3.Thymeleaf

        Thymeleaf是一种用于构建服务器端Java模板的现代化服务器端Java模板引擎。它允许开发人员将动态数据呈现到HTML页面,并支持强大的表达式语言和模板布局。Thymeleaf的语法简单易用,使得前端开发变得更加容易。

4.MySQL

       MySQL是一个开源的关系型数据库管理系统,被广泛用于Web应用程序开发。它具有卓越的性能、可靠性和可扩展性,提供了丰富的查询语言和存储过程支持。通过与Spring Boot和JPA的结合,我们可以轻松地进行数据库操作,实现数据的持久化和查询。

5.Bootstrap

        Bootstrap是一个流行的前端开发框架,它提供了丰富的CSS和JavaScript组件,可以帮助我们快速搭建现代化的用户界面。通过集成Bootstrap,我们可以对Web应用程序的外观和用户交互进行美化和增强,使得应用在不同设备上的显示效果更加统一和友好。

二、实现过程

1.新建项目

如图,IDEA新建项目时,选择Spring Initializr,选择Maven;

建议JDK 17;添加以下五个依赖

 

2.添加BootStrap样式

样式在官网有很多,可根据实际来修改

3.添加数据库配置

在application.properties文件里面添加本地或远程数据库信息,一遍后续使用

4.框架搭建

 

5.撰写模型属性

        Model层是写我们的业务构成属性的,我们现在写的是学生管理系统,所以在Model层写入学生姓名、性别等属性,并且同步在数据库构建Students学生信息表

6.添加学生信息

        想要添加网页信息到数据库,就需要先在业务接口StudentService写添加方法,然后在StudentServiceLmpl类里面注入JPA接口依赖,随后继承业务接口并实现方法,之后就可在控制层StudentController设置映射,当网址为指定网址时        ,调用添加函数,获取网页传入的数据调用添加方法,将数据储存到数据库,随后跳转回主页面,过程如图所示:

 

 要注意的是,业务层实现类和控制层都要先依赖注入,如图:

7.修改学生信息

        修改功能的实现步骤和添加的类似,不过在控制层要新建映射,通过网页拼接跳转的URL里的id信息来查找学生信息,并在新网页显示信息,用户更改后即跳转到保存函数,如图:

 

 

 

8.删除学生信息

       修改功能的实现步骤和添加的类似,不过在控制层要新建映射,通过网页拼接跳转的URL里的id信息来查找学生信息,并直接删除掉后即跳转到保存函数,如图:

 

9.查找

         查找功能是指定学生名来进行模糊查询,所以我们要现在JPA接口里面建立一个方法,随后在业务层创建并实现该方法,随后步骤和前面的一样了

        这里有个小细节,控制层里面建立映射,获取URL的姓名,并进行查找,所以需要在index.html文件里面设置好跳转链接,如图:

10.分页、排序

        分页和排序是MVC自带的方法,我们只要了解并按语法调用就可以了,先在StudentServiceLmpl类里面注入JPA接口依赖,随后继承业务接口并实现方法,之后就可在控制层StudentController设置映射,当网址为,调用添加函数,获取网页传入的数据调用添加方法,将数据储存到数据库,随后跳转回主页面,过程如图所示:规定每页数据超过五个就进入下一页,设置他的数量是依次递增的,网页设置可以根据不同的需求按照不同的列数进行排序desc:为降序,asc:为升序

11.拓展(数据库一对一)

       为了实现数据库一对一效果,我添加了一个class班级表,里面放班级名称,数据先设置了两个班级和未分配,随后在学生表添加一个外键链接班级表,最后添加class的JPA接口、业务层,即可在控制层获取班级表的所有班级名称,随后将数据传给index主页面,即可添加下拉框来选择班级,并借此来实现查找。并且添加了班级管理页面和增改查等操作,并且当班级名称发生改变时,学生信息的班级名称也发生改变


网页最终呈现的效果 首页

添加学生信息

修改学生信息

查找学生

分页及排序

查看所有班级并按此搜索

班级管理页面

修改班级信息

添加班级信息


三、代码展示

1.模型层(Studnt、Class1)

package com.example.studentproj.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString

/**
 * Class1实体类,对应数据库中的class表
 */
@Entity
@Table(name = "class")
public class Class1 {
    /**
     * 主键ID,自动生成且自增长
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    /**
     * 班级名称
     */
    @Column(name = "classname")
    private String name;
}
package com.example.studentproj.model;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "students")
public class Student {
    /**
     * 学生ID,自动生成且自增长
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    /**
     * 学生姓名
     */
    @Column(name = "name")
    private String name;

    /**
     * 学生性别
     */
    @Column(name = "sex")
    private String sex;

    /**
     * 学生年龄
     */
    @Column(name = "age")
    private int age;

    /**
     * 学籍状态
     */
    @Column(name = "status")
    private String status;

    /**
     * 学生籍贯
     */
    @Column(name = "ticy")
    private String ticy;

    /**
     * 班级名称
     */
    @Column(name = "class_name")
    private String className;

    /**
     * 班级关联
     */
    @ManyToOne
    @JoinColumn(name = "class_id")
    private Class1 class1;
}

2.控制层( StudentController )

package com.example.studentproj.controller;

import com.example.studentproj.model.Class1;
import com.example.studentproj.model.Student;
import com.example.studentproj.service.ClassService;
import com.example.studentproj.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Controller
public class StudentController {

    //依赖注入StudentService接口
    @Autowired
    private StudentService studentService;

    //依赖注入ClassService接口
    @Autowired
    private ClassService classService;

    
    //将获取到的班级名称信息传入model,并且跳转分页函数
    @GetMapping("/")
    public String viewHomePage(Model model) {
        List<Class1> listclass = classService.getAllClass();
        model.addAttribute("listclass",listclass);
        return findPaginated(1, "name", "asc" ,model);
    }


    //跳转添加学生信息网页
    @GetMapping("/showNewStudentForm")
    public String showStudet(Model model){
        Student student = new Student();
        List<Class1> listclass = classService.getAllClass();
        model.addAttribute("listclass",listclass);
        model.addAttribute("student",student);
        return "new_student";
    }

    //跳转保存学生信息网页
    @PostMapping("/saveStudent")
    public String saveStudnt(@ModelAttribute("student") Student student){
        studentService.saveStudent(student);
        return "redirect:/";
    }

    //根据id读取数据库数据,并支持修改
    @GetMapping("/showNewStudentUpdate{id}")
    public String showFormForUpdate(@PathVariable(value = "id") long id,Model model){
        Student student = studentService.getStudentByid(id);
        List<Class1> listclass = classService.getAllClass();
        model.addAttribute("listclass",listclass);
        model.addAttribute("student",student);
        return "update_student";
    }


    //根据id读取数据库数据,并直接删除掉
    @GetMapping("/deleteStudent{id}")
    public String deleteStudent(@PathVariable(value = "id") long id){
        this.studentService.deleteStudentByid(id);
        return "redirect:/";
    }


    //获取分页数据
    @GetMapping("/page/{pageNo}")
    public String findPaginated(@PathVariable (value = "pageNo") int pageNo,
                                @RequestParam("sortField") String sortField,
                                @RequestParam("sortDir") String sortDir,
                                Model model) {
        //设置每4条数据分一页
        int pageSize = 4;

        Page<Student> page = studentService.findPaginated(pageNo, pageSize, sortField, sortDir);
        List<Student> ListStudent = page.getContent();

        model.addAttribute("currentPage", pageNo);
        model.addAttribute("totalPages", page.getTotalPages());
        model.addAttribute("totalItems", page.getTotalElements());

        model.addAttribute("sortField", sortField);
        model.addAttribute("sortDir", sortDir);
        model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");

        model.addAttribute("listStudent", ListStudent);
        return "index";
    }

    //搜索名字
    @GetMapping("/query{inpname}")
    public String query(@PathVariable(value = "inpname") String inpame,Model model){
        List<Student> listStudent = studentService.findByNameContaining(inpame);
        List<Class1> listclass = classService.getAllClass();
        model.addAttribute("listclass",listclass);
        model.addAttribute("listStudent",listStudent);
        return "index";
    }


    //根据班级名称来查找数据
    @GetMapping("/classname{inpname}")
    public String classname(@PathVariable(value = "inpname") String inpame,Model model){
        List<Student> listStudent = studentService.findByClassName(inpame);
        List<Class1> listclass = classService.getAllClass();
        model.addAttribute("listclass",listclass);
        model.addAttribute("listStudent",listStudent);
        return "index";
    }

    //添加班级映射
    @GetMapping("/addClass")
    public String addClass(Model model) {
        Class1 class1 = new Class1();
        model.addAttribute("class", class1);
        return "add_class";
    }




    //保存班级表
    @PostMapping("/saveClass")
    public String saveClass(@ModelAttribute("class") Class1 class1){
        classService.saveClass(class1);
        return "redirect:classInfo";
    }



    //分页班级表
    @GetMapping("/classInfo")
    public String classInfo(Model model) {
        return findPaginated1(1, "name", "asc" ,model);

    }

    //获取分页数据
    @GetMapping("/page1/{pageNo}")
    public String findPaginated1(@PathVariable (value = "pageNo") int pageNo,
                                 @RequestParam("sortField") String sortField,
                                 @RequestParam("sortDir") String sortDir,
                                 Model model) {
        //设置每4条数据分一页
        int pageSize = 4;

        Page<Class1> page = classService.findPaginated1(pageNo, pageSize, sortField, sortDir);
        List<Class1> listClass = page.getContent();

        model.addAttribute("currentPage1", pageNo);
        model.addAttribute("totalPages1", page.getTotalPages());
        model.addAttribute("totalItems1", page.getTotalElements());

        model.addAttribute("sortField1", sortField);
        model.addAttribute("sortDir1", sortDir);
        model.addAttribute("reverseSortDir1", sortDir.equals("asc") ? "desc" : "asc");

        model.addAttribute("listClass", listClass);
        return "class_info";
    }

    //根据id读取数据库数据,并支持修改
    @GetMapping("/updateClass{id}")
    public String updateClass(@PathVariable(value = "id") long id,Model model){
        Class1 class1 = classService.getClassByid(id);
        model.addAttribute("class1",class1);

        return "update_class";
    }


    @PostMapping("/updateClasss/{id}")
    public String updateClass1(@PathVariable(value = "id") long id, @RequestParam("className") String className, @RequestParam("oldClassName") String oldClassName){
        // 获取班级实体
        Class1 class1 = classService.getClassByid(id);

        // 更新班级名称
        class1.setName(className);
        classService.saveClass(class1);

        // 同步更新学生表中对应班级的名称
        List<Student> students = studentService.findByClassName(oldClassName);
        for (Student student : students) {
            student.setClassName(className);
            studentService.saveStudent(student);
        }

        return "redirect:/classInfo"; // 重定向到班级列表页面
    }


    //根据id读取数据库数据,并直接删除掉
    @GetMapping("/deleteClass{id}")
    public String deleteClass(@PathVariable(value = "id") long id){
        classService.deleteClassByid(id);
        return "redirect:classInfo";
    }



    }


2.JPA接口层( ClassRepository、StudentRepository)

package com.example.studentproj.repository;


import com.example.studentproj.model.Class1;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ClassRepository extends JpaRepository<Class1, Long> {

    //获取class所有班级名字
    @Query("select c.name from Class1 c ")
    List<Class1> findByClassName();

}
package com.example.studentproj.repository;
import com.example.studentproj.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;


@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

    //通过学生名字来查找学生数据
    @Query("select s from Student s where s.name like %:name%")
    List<Student> findByName(@Param("name") String name);


    //通过班级名字来查找学生数据
    @Query("select s from Student s where s.className = :name")
    List<Student> findByClassName(@Param("name") String name);

}

2.业务接口层( ClassService、ClassServiceLmpl、StudentService、StudentServiceLmpl)

package com.example.studentproj.service;


import com.example.studentproj.model.Class1;
import com.example.studentproj.model.Student;
import org.springframework.data.domain.Page;

import java.util.List;


public interface ClassService {
   //获取所有班级数据
    List<Class1> getAllClass();


    //修改班级名
    Class1 getClassByid(Long id);

    //删除指定班级
    void deleteClassByid(Long id);

    //添加用
    void saveClass(Class1 class1);
    void updateClassName(Long id, String newClassName);

 Page<Class1> findPaginated1(int pageNo, int pageSize, String sortField, String sortDirection);

}
package com.example.studentproj.service;

import com.example.studentproj.model.Class1;
import com.example.studentproj.model.Student;
import com.example.studentproj.repository.ClassRepository;
import com.example.studentproj.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class ClassServiceLmpl implements ClassService{

    //依赖注入jpa接口
    @Autowired
    private ClassRepository classRepository;

    @Autowired
    private StudentRepository studentRepository;


    //获取所有班级名称
    @Override
    public List<Class1> getAllClass() {
        return classRepository.findAll();
    }


    //修改班级名称方法实现
    @Override
    public Class1 getClassByid(Long id) {
        Optional<Class1> optional = classRepository.findById(id);
        Class1 class1 = null;
        if( optional.isPresent()){
            class1 = optional.get();
        }else{
            throw new RuntimeException(" 查无此班,请重输入, id :  "+ id);
        }
        return class1;
    }

    //删除班级名称
    @Override
    public void deleteClassByid(Long id) {
        classRepository.deleteById(id);
    }

    //保存班级名称信息
    @Override
    public void saveClass(Class1 class1) {
        classRepository.save(class1);

    }

    @Override
    public Page<Class1> findPaginated1(int pageNo, int pageSize, String sortField, String sortDirection) {
        //设置排序参数,升序ASC/降序DESC?
        Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
                ? Sort.by(sortField).ascending()
                : Sort.by(sortField).descending();

        //根据页号/每页记录数/排序依据返回某指定页面数据。
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
        return this.classRepository.findAll(pageable);
    }

    @Override
    public void updateClassName(Long id, String newClassName) {
        Optional<Class1> optionalClass = classRepository.findById(id);
        if (optionalClass.isPresent()) {
            Class1 class1 = optionalClass.get();
            class1.setName(newClassName);
            classRepository.save(class1);

            // 同步更新学生信息中的班级名称
            List<Student> students = studentRepository.findByClassName(class1.getName());
            students.forEach(student -> student.setClassName(newClassName));
            studentRepository.saveAll(students);
        } else {
            throw new RuntimeException("查无此班,请重输入, id: " + id);
        }
    }



}
package com.example.studentproj.service;

import com.example.studentproj.model.Student;
import org.springframework.data.domain.Page;

import java.util.List;

public interface StudentService {

    /**
     * 获取所有学生列表
     *
     * @return 所有学生列表
     */
    List<Student> getAllStudents();

    /**
     * 存储学生信息
     *
     * @param student 学生对象
     */
    void saveStudent(Student student);

    /**
     * 通过姓名查询学生列表
     *
     * @param name 姓名
     * @return 符合条件的学生列表
     */
    List<Student> findByNameContaining(String name);

    /**
     * 通过班级查询学生列表
     *
     * @param name 班级名称
     * @return 符合条件的学生列表
     */
    List<Student> findByClassName(String name);

    /**
     * 根据学生ID获取学生信息
     *
     * @param id 学生ID
     * @return 学生对象
     */
    Student getStudentById(Long id);

    /**
     * 根据学生ID删除学生信息
     *
     * @param id 学生ID
     */
    void deleteStudentById(Long id);

    /**
     * 分页查询学生列表
     *
     * @param pageNo         当前页码
     * @param pageSize       每页记录数
     * @param sortField      排序字段
     * @param sortDirection  排序方向
     * @return 分页结果
     */
    Page<Student> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
}
package com.example.studentproj.service;

import com.example.studentproj.model.Student;
import com.example.studentproj.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentRepository studentRepository;

    /**
     * 获取所有学生列表
     *
     * @return 所有学生列表
     */
    @Override
    public List<Student> getAllStudents() {
        return studentRepository.findAll();
    }

    /**
     * 存储学生信息
     *
     * @param student 学生对象
     */
    @Override
    public void saveStudent(Student student) {
        studentRepository.save(student);
    }

    /**
     * 通过姓名查询学生列表
     *
     * @param name 姓名
     * @return 符合条件的学生列表
     */
    @Override
    public List<Student> findByNameContaining(String name) {
        return studentRepository.findByNameContaining(name);
    }

    /**
     * 通过班级查询学生列表
     *
     * @param name 班级名称
     * @return 符合条件的学生列表
     */
    @Override
    public List<Student> findByClassName(String name) {
        return studentRepository.findByClassName(name);
    }

    /**
     * 根据学生ID获取学生信息
     *
     * @param id 学生ID
     * @return 学生对象
     */
    @Override
    public Student getStudentById(Long id) {
        Optional<Student> optional = studentRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        } else {
            throw new RuntimeException("查无此人,请重新输入,id: " + id);
        }
    }

    /**
     * 根据学生ID删除学生信息
     *
     * @param id 学生ID
     */
    @Override
    public void deleteStudentById(Long id) {
        studentRepository.deleteById(id);
    }

    /**
     * 分页查询学生列表
     * @param pageNo       当前页码
     * @param pageSize     每页记录数
     * @param sortField    排序字段
     * @param sortDirection  排序方向(ASC或DESC)
     * @return 分页结果
     */
    @Override
    public Page<Student> findPaginated(int pageNo, int pageSize, String sortField, String         sortDirection) {
    Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
            ? Sort.by(sortField).ascending()
            : Sort.by(sortField).descending();

    Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
    return studentRepository.findAll(pageable);
}    

        整体结构代码已经全部放在这里了,html 的源码和class的拓展代码这里就不往上放了,大家感兴趣可自行摸索或私信我。


总结

        跟着 白导 学编程,通过结合Spring Boot、JPA、Thymeleaf、MySQL和Bootstrap,我们可以构建强大、高效和易于维护的Web应用程序。Spring Boot提供了开发的基础框架,JPA简化了数据库操作,Thymeleaf以及Bootstrap提供了更好的用户体验和界面设计。相信通过学习这些技术栈,大家都能够快速上手开发出出色的Web应用程序。

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡丘. 钦爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值