目录
1.2. 用户仓库(UserRepository.java)
1.4. 用户控制器(UserController.java)
2.2. 课程仓库(CourseRepository.java)
2.4. 课程控制器(CourseController.java)
2.5. 课程控制器(CourseController.java)
3.2. 支付仓库(PaymentRepository.java)
3.3. 支付服务(PaymentService.java)
3.4. 支付控制器(PaymentController.java)
5. WebSocket配置(WebSocketConfig.java)
6. 页面模板(index.html, login.html, register.html, 等)
6.4. 支付历史页面(payment/history.html)
6.5. 支付结算页面(payment/checkout.html)
家教系统开发概述
这个家教系统的功能主要包括:
用户管理:家长、学生、老师注册、登录、个人资料管理。
课程管理:家教课程发布、查询、预约。
评价系统:学生对老师的评价。
支付系统:通过第三方支付平台实现支付。
消息通知:系统推送消息功能,通知家长、学生、老师课程相关事件。
技术栈
后端:Java(Spring Boot + Spring Data JPA + Spring Security)
前端:Thymeleaf、Bootstrap
数据库:MySQL
支付:模拟支付(后期可以集成如支付宝、微信支付)
消息推送:通过 WebSocket 实现实时消息推送
项目结构
家教系统/
|-- src/
|-- main/
|-- java/
|-- com/
|-- tutoring/
|-- controller/
|-- AuthController.java
|-- CourseController.java
|-- UserController.java
|-- PaymentController.java
|-- entity/
|-- User.java
|-- Course.java
|-- Payment.java
|-- repository/
|-- UserRepository.java
|-- CourseRepository.java
|-- PaymentRepository.java
|-- service/
|-- UserService.java
|-- CourseService.java
|-- PaymentService.java
|-- config/
|-- SecurityConfig.java
|-- WebSocketConfig.java
|-- exception/
|-- CustomException.java
|-- TutoringApplication.java
|-- resources/
|-- templates/
|-- index.html
|-- login.html
|-- register.html
|-- course/list.html
|-- course/create.html
|-- payment/checkout.html
|-- application.properties
1. 完善用户管理模块
1.1. 用户实体类(User.java)
package com.tutoring.entity;
import javax.persistence.*;
import java.util.Set;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String role; // 用户角色,可能是 "STUDENT", "TEACHER", "ADMIN"
@OneToMany(mappedBy = "user")
private Set<Course> courses; // 用户创建的课程
@OneToMany(mappedBy = "student")
private Set<Payment> payments; // 用户的支付记录
// Getter and Setter methods
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public Set<Payment> getPayments() {
return payments;
}
public void setPayments(Set<Payment> payments) {
this.payments = payments;
}
}
1.2. 用户仓库(UserRepository.java)
package com.tutoring.repository;
import com.tutoring.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username); // 通过用户名查找用户
}
1.3. 用户服务(UserService.java)
package com.tutoring.service;
import com.tutoring.entity.User;
import com.tutoring.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 根据用户名查找用户
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
// 注册用户
public User registerUser(User user) {
return userRepository.save(user);
}
// 验证用户登录信息
public boolean validateUser(String username, String password) {
User user = userRepository.findByUsername(username);
return user != null && user.getPassword().equals(password);
}
}
1.4. 用户控制器(UserController.java)
package com.tutoring.controller;
import com.tutoring.entity.User;
import com.tutoring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
// 用户登录页面
@GetMapping("/login")
public String loginPage() {
return "login";
}
// 处理登录请求
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, Model model) {
if (userService.validateUser(username, password)) {
model.addAttribute("username", username);
return "redirect:/home"; // 登录成功后跳转到首页
} else {
model.addAttribute("error", "Invalid username or password");
return "login"; // 登录失败,返回登录页面
}
}
// 用户注册页面
@GetMapping("/register")
public String registerPage() {
return "register";
}
// 处理用户注册
@PostMapping("/register")
public String register(@ModelAttribute User user, Model model) {
user.setRole("STUDENT"); // 默认角色是学生
userService.registerUser(user);
model.addAttribute("message", "Registration successful! Please log in.");
return "login";
}
}
2. 完善课程管理模块
2.1. 课程实体类(Course.java)
package com.tutoring.entity;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
private LocalDateTime startTime;
private LocalDateTime endTime;
@ManyToOne
@JoinColumn(name = "teacher_id")
private User teacher; // 课程的教师
// Getter and Setter methods
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public User getTeacher() {
return teacher;
}
public void setTeacher(User teacher) {
this.teacher = teacher;
}
}
2.2. 课程仓库(CourseRepository.java)
package com.tutoring.repository;
import com.tutoring.entity.Course;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CourseRepository extends JpaRepository<Course, Long> {
List<Course> findByTeacherId(Long teacherId); // 根据教师 ID 查找课程
List<Course> findByTitleContaining(String title); // 根据课程标题查找课程
}
2.3. 课程服务(CourseService.java)
package com.tutoring.service;
import com.tutoring.entity.Course;
import com.tutoring.repository.CourseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CourseService {
@Autowired
private CourseRepository courseRepository;
// 保存课程
public Course saveCourse(Course course) {
return courseRepository.save(course);
}
// 查找所有课程
public List<Course> getAllCourses() {
return courseRepository.findAll();
}
// 根据教师 ID 查找课程
public List<Course> getCoursesByTeacher(Long teacherId) {
return courseRepository.findByTeacherId(teacherId);
}
// 根据课程标题查找课程
public List<Course> searchCourses(String title) {
return courseRepository.findByTitleContaining(title);
}
}
2.4. 课程控制器(CourseController.java)
package com.tutoring.controller;
import com.tutoring.entity.Course;
import com.tutoring.service.CourseService;
import com.tutoring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/course")
public class CourseController {
@Autowired
private CourseService courseService;
@Autowired
private UserService userService;
// 显示所有课程
@GetMapping("/list")
public String listCourses(Model model) {
List<Course> courses = courseService.getAllCourses();
model.addAttribute("courses", courses);
return "course/list";
}
// 创建新课程页面
@GetMapping("/create")
2.5. 课程控制器(CourseController.java)
// 创建新课程页面
@GetMapping("/create")
public String createCoursePage(Model model) {
// 这里可以根据需要将当前用户传递给模板
model.addAttribute("course", new Course());
return "course/create";
}
// 处理创建课程
@PostMapping("/create")
public String createCourse(@ModelAttribute Course course, @RequestParam Long teacherId, Model model) {
// 设置教师为当前登录用户
course.setTeacher(userService.findByUsername("currentLoggedUser")); // 示例: 替换为真实的用户信息
courseService.saveCourse(course);
model.addAttribute("message", "Course created successfully!");
return "redirect:/course/list";
}
// 搜索课程
@PostMapping("/search")
public String searchCourses(@RequestParam String title, Model model) {
List<Course> courses = courseService.searchCourses(title);
model.addAttribute("courses", courses);
return "course/list";
}
// 根据教师ID显示该教师的课程
@GetMapping("/teacher/{teacherId}")
public String coursesByTeacher(@PathVariable Long teacherId, Model model) {
List<Course> courses = courseService.getCoursesByTeacher(teacherId);
model.addAttribute("courses", courses);
return "course/list";
}
}
3. 完善支付模块
3.1. 支付实体类(Payment.java)
package com.tutoring.entity;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Double amount;
private String paymentMethod;
private LocalDateTime paymentDate;
@ManyToOne
@JoinColumn(name = "student_id")
private User student; // 支付的学生
@ManyToOne
@JoinColumn(name = "course_id")
private Course course; // 支付的课程
// Getter and Setter methods
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public String getPaymentMethod() {
return paymentMethod;
}
public void setPaymentMethod(String paymentMethod) {
this.paymentMethod = paymentMethod;
}
public LocalDateTime getPaymentDate() {
return paymentDate;
}
public void setPaymentDate(LocalDateTime paymentDate) {
this.paymentDate = paymentDate;
}
public User getStudent() {
return student;
}
public void setStudent(User student) {
this.student = student;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
}
3.2. 支付仓库(PaymentRepository.java)
package com.tutoring.repository;
import com.tutoring.entity.Payment;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface PaymentRepository extends JpaRepository<Payment, Long> {
List<Payment> findByStudentId(Long studentId); // 根据学生ID查找支付记录
List<Payment> findByCourseId(Long courseId); // 根据课程ID查找支付记录
}
3.3. 支付服务(PaymentService.java)
package com.tutoring.service;
import com.tutoring.entity.Payment;
import com.tutoring.repository.PaymentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PaymentService {
@Autowired
private PaymentRepository paymentRepository;
// 创建支付记录
public Payment createPayment(Payment payment) {
return paymentRepository.save(payment);
}
// 根据学生ID查找支付记录
public List<Payment> getPaymentsByStudent(Long studentId) {
return paymentRepository.findByStudentId(studentId);
}
// 根据课程ID查找支付记录
public List<Payment> getPaymentsByCourse(Long courseId) {
return paymentRepository.findByCourseId(courseId);
}
}
3.4. 支付控制器(PaymentController.java)
package com.tutoring.controller;
import com.tutoring.entity.Payment;
import com.tutoring.entity.User;
import com.tutoring.service.CourseService;
import com.tutoring.service.PaymentService;
import com.tutoring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/payment")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@Autowired
private CourseService courseService;
@Autowired
private UserService userService;
// 支付页面
@GetMapping("/checkout/{courseId}")
public String checkout(@PathVariable Long courseId, Model model) {
model.addAttribute("course", courseService.getAllCourses().get(courseId));
return "payment/checkout";
}
// 处理支付
@PostMapping("/checkout/{courseId}")
public String processPayment(@PathVariable Long courseId, @RequestParam Double amount,
@RequestParam String paymentMethod, Model model) {
User student = userService.findByUsername("currentLoggedUser"); // 示例: 替换为真实用户
Payment payment = new Payment();
payment.setAmount(amount);
payment.setPaymentMethod(paymentMethod);
payment.setPaymentDate(java.time.LocalDateTime.now());
payment.setStudent(student);
payment.setCourse(courseService.getAllCourses().get(courseId));
paymentService.createPayment(payment);
model.addAttribute("message", "Payment successful!");
return "redirect:/payment/history";
}
// 支付历史
@GetMapping("/history")
public String paymentHistory(Model model) {
User currentUser = userService.findByUsername("currentLoggedUser"); // 示例: 替换为真实用户
model.addAttribute("payments", paymentService.getPaymentsByStudent(currentUser.getId()));
return "payment/history";
}
}
4. 配置类(SecurityConfig.java)
为了确保系统的安全性,我们可以使用Spring Security来控制访问权限。
package com.tutoring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/login", "/user/register", "/").permitAll() // 允许所有人访问登录和注册页面
.antMatchers("/course/create", "/course/list").hasRole("TEACHER") // 仅教师可以创建课程
.antMatchers("/payment/**").hasRole("STUDENT") // 仅学生可以进行支付操作
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/user/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
5. WebSocket配置(WebSocketConfig.java)
若您希望加入实时通知或聊天功能,我们可以配置WebSocket。此部分较为简单,您可以根据实际需求进行扩展。
package com.tutoring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
6. 页面模板(index.html, login.html, register.html, 等)
根据Spring Boot的模板引擎(例如Thymeleaf),我们可以设计相应的HTML页面来显示课程列表、支付页面等。
6.1. 课程列表页面(course/list.html)
<!DOCTYPE html>
<html>
<head>
<title>课程列表</title>
</head>
<body>
<h1>课程列表</h1>
<table>
<tr>
<th>课程标题</th>
<th>描述</th>
<th>教师</th>
<th>操作</th>
</tr>
<th:block th:each="course : ${courses}">
<tr>
<td th:text="${course.title}"></td>
<td th:text="${course.description}"></td>
<td th:text="${course.teacher.username}"></td>
<td><a th:href="@{/payment/checkout/{courseId}(courseId=${course.id})}">支付</a></td>
</tr>
</th:block>
</table>
</body>
</html>
6.2. 登录页面(login.html)
<!DOCTYPE html>
<html>
<head>
<title>登录</title>
</head>
<body
<h1>登录</h1>
<form action="/user/login" method="post">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required><br>
<button type="submit">登录</button>
</form>
<a href="/user/register">没有账号?注册</a>
</body>
</html>
6.3. 注册页面(register.html)
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
</head>
<body>
<h1>注册</h1>
<form action="/user/register" method="post">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required><br>
<label for="role">角色:</label>
<select id="role" name="role">
<option value="STUDENT">学生</option>
<option value="TEACHER">教师</option>
</select><br>
<button type="submit">注册</button>
</form>
<a href="/user/login">已有账号?登录</a>
</body>
</html>
6.4. 支付历史页面(payment/history.html)
<!DOCTYPE html>
<html>
<head>
<title>支付历史</title>
</head>
<body>
<h1>支付历史</h1>
<table>
<tr>
<th>课程标题</th>
<th>支付金额</th>
<th>支付方式</th>
<th>支付时间</th>
</tr>
<th:block th:each="payment : ${payments}">
<tr>
<td th:text="${payment.course.title}"></td>
<td th:text="${payment.amount}"></td>
<td th:text="${payment.paymentMethod}"></td>
<td th:text="${payment.paymentDate}"></td>
</tr>
</th:block>
</table>
</body>
</html>
6.5. 支付结算页面(payment/checkout.html)
<!DOCTYPE html>
<html>
<head>
<title>支付结算</title>
</head>
<body>
<h1>支付课程: <span th:text="${course.title}"></span></h1>
<form action="#" method="post">
<label for="amount">支付金额:</label>
<input type="number" id="amount" name="amount" step="0.01" min="0" required><br>
<label for="paymentMethod">支付方式:</label>
<select id="paymentMethod" name="paymentMethod">
<option value="Credit Card">信用卡</option>
<option value="Alipay">支付宝</option>
<option value="WeChat">微信</option>
</select><br>
<button type="submit">提交支付</button>
</form>
</body>
</html>
7. 配置和优化
7.1. 数据库配置
在application.properties中,你可以配置数据库连接信息。以 MySQL 为例:
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/tutoring_system?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
7.2. 日志配置
使用 logback-spring.xml 可以自定义日志输出格式:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
8.总结
本项目实现了一个基本的线上辅导平台,涵盖了从用户管理到课程支付等核心功能,并使用Spring Boot、Thymeleaf和MySQL等技术实现了系统的构建。通过模块化设计和层次化架构,使得系统具备良好的扩展性和可维护性,能够应对日后功能的拓展和优化。
这个平台不仅能为学生提供便捷的学习体验,还能帮助教师有效地管理课程和与学生互动。未来,可以通过持续优化系统性能和增加新功能来提升用户体验,使平台更加完备。