【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.repository.ClassRepository;
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";
    }

}

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 java.util.List;


public interface ClassService {
   //获取所有班级数据
    List<Class1> getAllClass();
    
}
package com.example.studentproj.service;

import com.example.studentproj.model.Class1;
import com.example.studentproj.repository.ClassRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClassServiceImpl implements ClassService {

    @Autowired
    private ClassRepository classRepository;

    /**
     * 获取所有班级列表
     *
     * @return 所有班级列表
     */
    @Override
    public List<Class1> getAllClasses() {
        return classRepository.findAll();
    }
}
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应用程序。

猜你喜欢

转载自blog.csdn.net/qq_51294997/article/details/131545399