feat:修改学生相关,完善代码

backend
poppoppuppylove 2 months ago
parent ea43ca93ad
commit ddf078bae5

@ -0,0 +1,146 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>attendance</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>attendance</name>
<description>attendance</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot Starter JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- Spring Boot DevTools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- MyBatis Starter Test -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<!-- Spring Security for password encryption -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT Library -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- BCrypt for password hashing -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release> <!-- 设置 release 参数来简化配置 -->
</configuration>
</plugin>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,33 @@
package com.example.attendance.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 关闭 CSRF 保护(适用于测试,生产环境中请谨慎处理)
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/teacher/register", "/api/teacher/login").permitAll() // 允许注册和登录接口匿名访问
.anyRequest().authenticated() // 其他请求需要认证
)
.formLogin(form -> form.disable()) // 关闭表单登录(如有需要可以调整)
.httpBasic(httpBasic -> httpBasic.disable()); // 关闭基本认证(如有需要可以调整)
return http.build();
}
}

@ -0,0 +1,24 @@
package com.example.attendance.controller;
import com.example.attendance.entity.RollCallResponse;
import com.example.attendance.entity.RollCallSettings;
import com.example.attendance.entity.Student;
import com.example.attendance.service.RollCallService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/rollcall")
public class RollCallController {
private final RollCallService rollCallService;
public RollCallController(RollCallService rollCallService) {
this.rollCallService = rollCallService;
}
@PostMapping("/start")
public RollCallResponse startRollCall(@RequestBody List<Student> students, @RequestBody RollCallSettings settings) {
return rollCallService.startRollCall(students, settings);
}
}

@ -1,5 +1,6 @@
package com.example.attendance.controller; package com.example.attendance.controller;
import com.example.attendance.entity.PointsRequest;
import com.example.attendance.entity.Student; import com.example.attendance.entity.Student;
import com.example.attendance.service.StudentService; import com.example.attendance.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -16,35 +17,71 @@ public class StudentController {
@Autowired @Autowired
private StudentService studentService; private StudentService studentService;
@GetMapping("/") @GetMapping("/{id}")
public ResponseEntity<Student> getStudentById(@PathVariable Long id) {
Student student = studentService.findById(id);
return ResponseEntity.ok(student);
}
@GetMapping("/studentNumber/{studentNumber}")
public ResponseEntity<Student> getStudentByStudentNumber(@PathVariable String studentNumber) {
Student student = studentService.findByStudentNumber(studentNumber);
return ResponseEntity.ok(student);
}
@GetMapping
public ResponseEntity<List<Student>> getAllStudents() { public ResponseEntity<List<Student>> getAllStudents() {
List<Student> students = studentService.getAllStudents(); List<Student> students = studentService.findAll();
return ResponseEntity.ok(students); return ResponseEntity.ok(students);
} }
@GetMapping("/{id}") @PostMapping
public ResponseEntity<Student> getStudent(@PathVariable Long id) { public ResponseEntity<String> addStudent(@RequestBody Student student) {
Student student = studentService.getStudentById(id); studentService.save(student);
if (student != null) { return ResponseEntity.ok("Student added successfully");
return ResponseEntity.ok(student);
} else {
return ResponseEntity.notFound().build();
}
} }
@PostMapping("/") @PutMapping("/{studentNumber}")
public ResponseEntity<Student> addStudent(@RequestBody Student student) { public ResponseEntity<String> updateStudent(@PathVariable String studentNumber, @RequestBody Student student) {
studentService.addStudent(student); student.setStudentNumber(studentNumber);
return ResponseEntity.ok(student); studentService.update(student);
return ResponseEntity.ok("Student updated successfully");
} }
@PutMapping("/{id}") @DeleteMapping("/{id}")
public ResponseEntity<Student> updateStudentPoints(@PathVariable Long id, @RequestParam int points) { public ResponseEntity<String> deleteStudent(@PathVariable Long id) {
studentService.updateStudentPoints(id, points); studentService.delete(id);
Student updatedStudent = studentService.getStudentById(id); return ResponseEntity.ok("Student deleted successfully");
return ResponseEntity.ok(updatedStudent);
} }
/**
*
* @param page
* @param size
* @return
*/
@GetMapping("/ranking")
public ResponseEntity<List<Student>> getStudentRanking(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
List<Student> ranking = studentService.getStudentRanking(page, size);
return ResponseEntity.ok(ranking);
}
/**
*
* @param studentNumber
* @param pointsRequest
* @return
*/
@PutMapping("/{studentNumber}/adjustPoints")
public ResponseEntity<String> adjustStudentPoints(@PathVariable String studentNumber, @RequestBody PointsRequest pointsRequest) {
try {
studentService.adjustPoints(studentNumber, pointsRequest.getPointsDelta());
return ResponseEntity.ok("积分调整成功");
} catch (Exception e) {
return ResponseEntity.status(500).body("积分调整失败:" + e.getMessage());
}
}
/** /**
* Excel * Excel
* @param file Excel * @param file Excel
@ -55,7 +92,6 @@ public class StudentController {
if (file.isEmpty()) { if (file.isEmpty()) {
return "请上传有效的Excel文件"; return "请上传有效的Excel文件";
} }
try { try {
studentService.importStudents(file); studentService.importStudents(file);
return "学生数据导入成功"; return "学生数据导入成功";

@ -0,0 +1,34 @@
package com.example.attendance.controller;
import com.example.attendance.service.TeacherService;
import com.example.attendance.service.impl.TeacherServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/teacher")
public class TeacherController {
@Autowired
private TeacherService teacherService;
@PostMapping("/register")
public ResponseEntity<String> register(@RequestParam String username, @RequestParam String password) {
try {
teacherService.register(username, password);
return ResponseEntity.ok("注册成功"); // 成功时返回 200 状态和消息
} catch (Exception e) {
return ResponseEntity.badRequest().body("注册失败: " + e.getMessage()); // 失败时返回 400 状态和错误信息
}
}
@PostMapping("/login")
public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) {
try {
String token = teacherService.login(username, password);
return ResponseEntity.ok("登录成功, Token: " + token); // 成功时返回 200 状态和 JWT token
} catch (Exception e) {
return ResponseEntity.badRequest().body("登录失败: " + e.getMessage()); // 失败时返回 400 状态和错误信息
}
}
}

@ -0,0 +1,15 @@
package com.example.attendance.entity;
import java.math.BigDecimal;
public class PointsRequest {
private BigDecimal pointsDelta;
public BigDecimal getPointsDelta() {
return pointsDelta;
}
public void setPointsDelta(BigDecimal pointsDelta) {
this.pointsDelta = pointsDelta;
}
}

@ -1,13 +1,18 @@
package com.example.attendance.dto; package com.example.attendance.entity;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Data import java.math.BigDecimal;
@AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class StudentExcelDTO { @AllArgsConstructor
private String name; @Data
public class RollCallResponse {
private String studentId; private String studentId;
private String name;
private BigDecimal points;
private String message; // 显示结果信息
} }

@ -0,0 +1,15 @@
package com.example.attendance.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class RollCallSettings {
private boolean isRollCall; // 点名(true)或提问(false)
private boolean triggerRandomEvent; // 是否触发随机事件
private boolean wheelOfFortune; // 是否开启命运轮盘
}

@ -1,20 +1,43 @@
package com.example.attendance.entity; package com.example.attendance.entity;
import java.math.BigDecimal;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
// TODO更新数据库表结构
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student { public class Student {
private Long id; private Long id;
private String name; private String studentNumber; // 学号
private int initialPoints = 0; private String name; // 姓名
private int currentPoints = 0; private BigDecimal points; // 积分
private int correctAnswerStreak; // 连续答对次数
private boolean skipNextCall; // 是否跳过下次点名 // getters and setters
private boolean borrowingPoints; // 是否借用积分 public Long getId() {
private boolean increasedCallChance; // 点名概率是否增加 return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStudentNumber() {
return studentNumber;
}
public void setStudentNumber(String studentNumber) {
this.studentNumber = studentNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPoints() {
return points;
}
public void setPoints(BigDecimal points) {
this.points = points;
}
} }

@ -1,14 +1,15 @@
package com.example.attendance.dto; package com.example.attendance.entity;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class StudentDTO { @AllArgsConstructor
@Data
public class Teacher {
private Long id; private Long id;
private String name; private String username;
private int currentPoints; private String password;
} }

@ -1,29 +0,0 @@
package com.example.attendance.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.attendance.dto.StudentExcelDTO;
import com.example.attendance.entity.Student;
import com.example.attendance.mapper.StudentMapper;
public class StudentExcelListener extends AnalysisEventListener<StudentExcelDTO> {
private final StudentMapper studentMapper;
public StudentExcelListener(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
@Override
public void invoke(StudentExcelDTO data, AnalysisContext context) {
Student student = new Student();
student.setName(data.getName());
student.setId(Long.valueOf(data.getStudentId()));
student.setCurrentPoints(0); // 初始积分为0
studentMapper.insertStudent(student);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 处理完成后的操作
}
}

@ -3,20 +3,47 @@ package com.example.attendance.mapper;
import com.example.attendance.entity.Student; import com.example.attendance.entity.Student;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
@Mapper @Mapper
public interface StudentMapper { public interface StudentMapper {
@Select("SELECT * FROM students WHERE id = #{id}") @Select("SELECT * FROM student WHERE id = #{id}")
Student getStudentById(Long id); Student findById(Long id);
@Select("SELECT * FROM students") @Select("SELECT * FROM student WHERE student_number = #{studentNumber}")
List<Student> getAllStudents(); Student findByStudentNumber(String studentNumber);
@Insert("INSERT INTO students(name, initialPoints, currentPoints) VALUES(#{name}, #{initialPoints}, #{currentPoints})") @Select("SELECT * FROM student")
void insertStudent(Student student); List<Student> findAll();
@Update("UPDATE students SET currentPoints = #{currentPoints} WHERE id = #{id}") @Insert("INSERT INTO student (student_number, name, points) VALUES (#{studentNumber}, #{name}, #{points})")
void updateStudentPoints(@Param("id") Long id, @Param("currentPoints") int currentPoints); @Options(useGeneratedKeys = true, keyProperty = "id")
void save(Student student);
@Update("UPDATE student SET name = #{name}, points = #{points} WHERE student_number = #{studentNumber}")
void update(Student student);
@Delete("DELETE FROM student WHERE id = #{id}")
void delete(Long id);
@Insert({
"<script>",
"INSERT INTO student (student_number, name, points) VALUES ",
"<foreach collection='students' item='student' separator=','>",
"(#{student.studentNumber}, #{student.name}, #{student.points})",
"</foreach>",
"</script>"
})
void saveStudents(List<Student> students);
/**
*
* @param offset
* @param size
* @return
*/
@Select("SELECT * FROM student ORDER BY points DESC LIMIT #{size} OFFSET #{offset}")
List<Student> findStudentsByRanking(@Param("offset") int offset, @Param("size") int size);
} }

@ -0,0 +1,15 @@
package com.example.attendance.mapper;
import com.example.attendance.entity.Teacher;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface TeacherMapper {
@Insert("INSERT INTO teacher (username, password) VALUES (#{username}, #{password})")
void save(Teacher teacher);
@Select("SELECT * FROM teacher WHERE username = #{username}")
Teacher findByUsername(String username);
}

@ -0,0 +1,10 @@
package com.example.attendance.service;
import com.example.attendance.entity.RollCallResponse;
import com.example.attendance.entity.RollCallSettings;
import com.example.attendance.entity.Student;
import java.util.List;
public interface RollCallService {
RollCallResponse startRollCall(List<Student> students, RollCallSettings settings); // 处理点名逻辑
}

@ -1,15 +1,20 @@
package com.example.attendance.service; package com.example.attendance.service;
import com.example.attendance.dto.StudentExcelDTO;
import com.example.attendance.entity.Student; import com.example.attendance.entity.Student;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
public interface StudentService { public interface StudentService {
void importStudents(MultipartFile file); void importStudents(MultipartFile file) throws Exception ;
List<Student> getAllStudents(); void adjustPoints(String studentNumber, BigDecimal pointsDelta);
Student getStudentById(Long id); List<Student> getStudentRanking(int page, int size);
void addStudent(Student student); Student findById(Long id);
void updateStudentPoints(Long id, int points); Student findByStudentNumber(String studentNumber);
List<Student> findAll();
void save(Student student);
void update(Student student);
void delete(Long id);
} }

@ -0,0 +1,23 @@
package com.example.attendance.service;
public interface TeacherService {
/**
*
*
* @param username
* @param password
* @throws Exception
*/
void register(String username, String password) throws Exception;
/**
*
*
* @param username
* @param password
* @return JWT token
* @throws Exception
*/
String login(String username, String password) throws Exception;
}

@ -0,0 +1,110 @@
package com.example.attendance.service.impl;
import com.example.attendance.entity.RollCallResponse;
import com.example.attendance.entity.RollCallSettings;
import com.example.attendance.entity.Student;
import com.example.attendance.service.RollCallService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
@Service
public class RollCallServiceImpl implements RollCallService {
@Override
public RollCallResponse startRollCall(List<Student> students, RollCallSettings settings) {
// 1. 根据设定选择点名或提问模式
String mode = settings.isRollCall() ? "点名" : "提问";
System.out.println("当前模式:" + mode);
// 2. 处理命运轮盘 (所有人概率相等)
if (settings.isWheelOfFortune()) {
return handleWheelOfFortune(students);
}
// 3. 正常点名逻辑,使用权重随机选择学生
Student selectedStudent = selectWeightedRandomStudent(students);
RollCallResponse response = new RollCallResponse();
response.setStudentId(selectedStudent.getStudentNumber());
response.setName(selectedStudent.getName());
response.setPoints(selectedStudent.getPoints());
// 4. 判断是否触发随机事件
if (settings.isTriggerRandomEvent()) {
response.setMessage("触发了随机事件: " + triggerRandomEvent());
} else {
response.setMessage("没有触发随机事件," + selectedStudent.getName() + " 被点了!");
}
return response;
}
// 权重随机选择学生,积分越高概率越低
private Student selectWeightedRandomStudent(List<Student> students) {
Random random = new Random();
int totalWeight = 0;
// 计算所有学生的总权重,假设权重为 100 - currentPoints
for (Student student : students) {
int weight = 100 - student.getPoints().intValue();
if (weight < 1) {
weight = 1; // 确保权重最低为1
}
totalWeight += weight; // 累计总权重
}
// 如果 totalWeight 为 0 或负数,则无法进行随机选择
if (totalWeight <= 0) {
throw new IllegalArgumentException("总权重必须为正数");
}
// 随机生成一个 0 到 totalWeight 之间的随机数
int randomIndex = random.nextInt(totalWeight);
int currentWeightSum = 0;
// 遍历学生列表,根据累计权重确定选中的学生
for (Student student : students) {
int weight = 100 - student.getPoints().intValue();
if (weight < 1) {
weight = 1;
}
currentWeightSum += weight;
// 当累计权重超过随机数时,选择当前学生
if (currentWeightSum > randomIndex) {
return student;
}
}
// 如果没有选中任何学生,兜底返回第一个学生(理论上不会发生)
return students.get(0);
}
// 命运轮盘处理(所有学生概率相等)
private RollCallResponse handleWheelOfFortune(List<Student> students) {
Random random = new Random();
Student selectedStudent = students.get(random.nextInt(students.size()));
RollCallResponse response = new RollCallResponse();
response.setStudentId(selectedStudent.getStudentNumber());
response.setName(selectedStudent.getName());
response.setPoints(selectedStudent.getPoints());
response.setMessage("命运轮盘: " + selectedStudent.getName() + " 被选中了!");
return response;
}
// 触发随机事件:赌徒事件或倒霉事件
private String triggerRandomEvent() {
Random random = new Random();
int eventType = random.nextInt(2); // 0表示赌徒事件1表示倒霉事件
if (eventType == 0) {
return "赌徒事件"; // 触发赌徒事件
} else {
return "倒霉事件"; // 触发倒霉事件
}
}
}

@ -1,16 +1,19 @@
package com.example.attendance.service.impl; package com.example.attendance.service.impl;
import com.alibaba.excel.EasyExcel;
import com.example.attendance.dto.StudentExcelDTO;
import com.example.attendance.entity.Student; import com.example.attendance.entity.Student;
import com.example.attendance.listener.StudentExcelListener;
import com.example.attendance.mapper.StudentMapper; import com.example.attendance.mapper.StudentMapper;
import com.example.attendance.service.StudentService; import com.example.attendance.service.StudentService;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service
@ -20,33 +23,92 @@ public class StudentServiceImpl implements StudentService {
private StudentMapper studentMapper; private StudentMapper studentMapper;
@Override @Override
public void importStudents(MultipartFile file) { public void importStudents(MultipartFile file) throws Exception {
try (InputStream inputStream = file.getInputStream()) { List<Student> students = new ArrayList<>();
EasyExcel.read(inputStream, StudentExcelDTO.class, new StudentExcelListener(studentMapper))
.sheet() // 获取上传的 Excel 文件流
.doRead(); try (InputStream inputStream = file.getInputStream();
} catch (Exception e) { Workbook workbook = new XSSFWorkbook(inputStream)) {
throw new RuntimeException("从Excel导入学生数据失败", e);
// 读取第一个工作表
Sheet sheet = workbook.getSheetAt(0);
// 遍历每一行,从第二行开始(假设第一行是标题)
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
// 读取学生数据
String studentNumber = row.getCell(0).getStringCellValue();
String name = row.getCell(1).getStringCellValue();
BigDecimal points = new BigDecimal(row.getCell(2).getNumericCellValue());
Student student = new Student();
student.setStudentNumber(studentNumber);
student.setName(name);
student.setPoints(points);
students.add(student);
}
}
// 将学生列表保存到数据库
studentMapper.saveStudents(students);
}
/**
*
* @param studentNumber
* @param pointsDelta
*/
public void adjustPoints(String studentNumber, BigDecimal pointsDelta) {
Student student = studentMapper.findByStudentNumber(studentNumber);
if (student == null) {
throw new RuntimeException("未找到该学生");
} }
BigDecimal updatedPoints = student.getPoints().add(pointsDelta);
student.setPoints(updatedPoints);
studentMapper.update(student);
}
/**
*
* @param page
* @param size
* @return
*/
public List<Student> getStudentRanking(int page, int size) {
int offset = page * size;
return studentMapper.findStudentsByRanking(offset, size);
}
@Override
public Student findById(Long id) {
return studentMapper.findById(id);
}
@Override
public Student findByStudentNumber(String studentNumber) {
return studentMapper.findByStudentNumber(studentNumber);
} }
@Override @Override
public List<Student> getAllStudents() { public List<Student> findAll() {
return studentMapper.getAllStudents(); return studentMapper.findAll();
} }
@Override @Override
public Student getStudentById(Long id) { public void save(Student student) {
return studentMapper.getStudentById(id); studentMapper.save(student);
} }
@Override @Override
public void addStudent(Student student) { public void update(Student student) {
studentMapper.insertStudent(student); studentMapper.update(student);
} }
@Override @Override
public void updateStudentPoints(Long id, int points) { public void delete(Long id) {
studentMapper.updateStudentPoints(id, points); studentMapper.delete(id);
} }
} }

@ -0,0 +1,37 @@
package com.example.attendance.service.impl;
import com.example.attendance.mapper.TeacherMapper;
import com.example.attendance.entity.Teacher;
import com.example.attendance.service.TeacherService;
import com.example.attendance.util.JWTUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class TeacherServiceImpl implements TeacherService {
@Autowired
private TeacherMapper teacherMapper;
@Autowired
private PasswordEncoder passwordEncoder; // 使用 PasswordEncoder 接口
@Override
public void register(String username, String password) {
Teacher teacher = new Teacher();
teacher.setUsername(username);
teacher.setPassword(passwordEncoder.encode(password)); // 密码加密
teacherMapper.save(teacher);
}
@Override
public String login(String username, String password) {
Teacher teacher = teacherMapper.findByUsername(username);
if (teacher == null || !passwordEncoder.matches(password, teacher.getPassword())) {
throw new RuntimeException("用户名或密码不正确");
}
// 返回 JWT token
return JWTUtil.generateToken(teacher);
}
}

@ -0,0 +1,43 @@
package com.example.attendance.util;
import com.example.attendance.entity.Teacher;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
public class JWTUtil {
private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
public static String generateToken(Teacher teacher) {
return Jwts.builder()
.setSubject(teacher.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000)) // Token 有效期 1 小时
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static Claims extractClaims(String token) {
try {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
throw new RuntimeException("Invalid JWT token", e); // 捕获并抛出异常
}
}
public static String getUsernameFromToken(String token) {
return extractClaims(token).getSubject();
}
public static boolean isTokenExpired(String token) {
return extractClaims(token).getExpiration().before(new Date());
}
}

@ -4,4 +4,4 @@ spring.datasource.username=root
spring.datasource.password=123456789jk spring.datasource.password=123456789jk
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:mappers/*.xml

@ -0,0 +1,24 @@
package com.example.attendance;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class PasswordEncryptor {
public static void main(String[] args) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
// 这里使用你希望的明文密码
String rawPassword1 = "123456";
String rawPassword2 = "654321";
String rawPassword3 = "admin123";
// 加密密码
String encodedPassword1 = passwordEncoder.encode(rawPassword1);
String encodedPassword2 = passwordEncoder.encode(rawPassword2);
String encodedPassword3 = passwordEncoder.encode(rawPassword3);
// 打印加密后的密码
System.out.println("teacher1 密码: " + encodedPassword1);
System.out.println("teacher2 密码: " + encodedPassword2);
System.out.println("teacher3 密码: " + encodedPassword3);
}
}
Loading…
Cancel
Save