文章目录
2.JPA接口层( ClassRepository、StudentRepository)
2.业务接口层( ClassService、ClassServiceLmpl、StudentService、StudentServiceLmpl)
场景导入
在现代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应用程序。