2025山东大学软件学院创新项目实训博客(四)

2025山东大学软件学院创新项目实训博客(四)

时间

2025.3.31-2025.4.6

工作内容

本周按照项目计划,继续推进后端开发工作,主要完成教师服务功能实现、用户认证功能的整体实现以及相关接口的完善。同时对上周开发的功能进行测试和优化,确保系统稳定性和安全性。

预计产出:教师服务实现类、教师相关API接口、用户认证完整功能、测试报告

详细内容

教师服务实现

学生列表管理

实现了教师查看和管理自己课程学生的功能:
实现思路
addStudent方法:此方法旨在将学生添加至教师所教授课程的学生列表中。首先严格校验传入的studentIdteacherId,一旦发现为空,立即返回Code.CODE_PARAM_ERROR错误码,并附带 “学生 ID 和教师 ID 不能为空” 的错误提示,以此确保关键数据的完整性。在验证通过后,创建AddStudentBody对象,将studentIdteacherId封装其中,随后调用teacherDao.addStudent方法,将学生与教师的关联关系持久化到数据库。倘若在操作期间遭遇异常,通过log.error记录详细的错误日志,并返回Code.CODE_SERVER_ERROR错误码以及 “添加学生失败” 的提示信息 ,保证问题可追溯。

deleteStudent方法:该方法用于从教师的课程学生列表中移除指定学生。同样先对studentIdteacherId进行非空验证,若不符合要求,返回Code.CODE_PARAM_ERROR错误码及对应提示。验证通过后,直接调用teacherDao.deleteStudent方法执行数据库删除操作,当出现异常时,利用log.error记录 “移除学生失败” 的错误日志,并返回Code.CODE_SERVER_ERROR错误码和相应错误提示,确保数据删除操作的准确性和可查性。

getStudentList方法:该方法用于获取教师的学生列表,其逻辑根据teacherId是否为空分情况处理。当teacherId为空时,先调用userDao.getUserList获取所有用户列表,若获取成功且返回数据有效,对用户列表进行筛选,仅保留类型为学生(UserConstants.TYPE_STUDENT)的用户,重新封装成UserListResponse对象后返回;当teacherId不为空时,通过teacherDao.getStudentList从数据库获取该教师对应的学生列表,将列表中的Student对象转换为User对象,构建新的UserListResponse对象返回。无论哪种情况,若在获取过程中出现异常,均通过log.error记录 “获取学生列表失败” 的日志,并返回Code.CODE_SERVER_ERROR错误码及对应提示。

    @Override
    public Result<Void> addStudent(String studentId, String teacherId) {
        try {
            if (studentId == null || teacherId == null) {
                return Result.fail(Code.CODE_PARAM_ERROR, "学生ID和教师ID不能为空");
            }
            AddStudentBody addStudentBody=new AddStudentBody();
            addStudentBody.setStudentId(studentId);
            addStudentBody.setTeacherId(teacherId);
            return teacherDao.addStudent(addStudentBody);
        } catch (Exception e) {
            log.error("添加学生失败", e);
            return Result.fail(Code.CODE_SERVER_ERROR, "添加学生失败");
        }
    }
    @Override
    public Result<Void> deleteStudent(String studentId, String teacherId) {
        try {
            if (studentId == null || teacherId == null) {
                return Result.fail(Code.CODE_PARAM_ERROR, "学生ID和教师ID不能为空");
            }
            return teacherDao.deleteStudent(studentId,teacherId);
        } catch (Exception e) {
            log.error("移除学生失败", e);
            return Result.fail(Code.CODE_SERVER_ERROR, "移除学生失败");
        }
    }
   @Override
    public Result<UserListResponse> getStudentList(String teacherId) {
        try {
            Result<UserListResponse> result;
            if(teacherId==null){
                result=userDao.getUserList();
                if(result.getCode()==0)
                {
                    //过滤出学生用户
                    UserListResponse   userListResponse= result.getData();
                    if(userListResponse!=null){
                        List<User> filteredUsers = userListResponse.getUserList().stream()
                                .filter(user -> user.getType() == UserConstants.TYPE_STUDENT)
                                .collect(Collectors.toList());
                        UserListResponse filteredUserListResponse = new UserListResponse();
                        filteredUserListResponse.setUserList(filteredUsers);
                        result = Result.success(filteredUserListResponse);
                    }
                }
            }
            else {
            Result<StudentListResponse> studentListResponse = teacherDao.getStudentList(teacherId);
                List<Student> students = studentListResponse.getData().getStudents();
                List<User> uStudents =new ArrayList<>();
                for(Student s : students)
                {
                    User u = new User();
                    u.setAccount(s.getAccount());
                    u.setName(s.getName());
                    u.setType(Integer.valueOf(s.getType()));
                    uStudents.add(u);
                }
                UserListResponse userListResponse = new UserListResponse();
                userListResponse.setUserList(uStudents);
                result = Result.success(userListResponse);
            }
            System.out.println(result);
            if (result.getCode() != Code.CODE_SUCCESS) {
                return Result.fail(result.getCode(), result.getMessage());
            }
            return Result.success(result.getData());
        } catch (Exception e) {
            log.error("获取学生列表失败", e);
            return Result.fail(Code.CODE_SERVER_ERROR, "获取学生列表失败");
        }
    }
作业管理

实现思路
publishHomework方法:作为作业发布的核心方法,首先对传入的homework对象进行全面检查,重点验证homework对象本身以及其中的courseId是否为空,若存在缺失,即刻返回Code.CODE_INVALID_PARAM错误码和 “作业信息不完整” 的提示。在验证通过后,设置作业状态为 “已发布”(HomeworkStatus.PUBLISHED.getValue()),并记录作业的创建时间为当前时间(new Date()),接着借助homeworkMapper.insert方法将作业信息插入数据库。依据插入操作影响的行数判断结果,若行数大于 0,表明插入成功,通过logger.info记录教师发布作业的日志,并返回包含作业 ID 的成功结果;否则返回Code.CODE_SYSTEM_ERROR错误码和 “发布作业失败” 的提示。

getHomeworkList方法:该方法主要负责根据课程 ID 获取对应的作业列表。首先对传入的courseId进行非空验证,若为空则返回Code.CODE_INVALID_PARAM错误码和 “课程 ID 不能为空” 的提示。验证通过后,调用homeworkMapper.selectByCourseId方法从数据库查询该课程下的所有作业列表,将查询结果封装在Result对象中返回,若查询过程出现异常,同样返回相应的错误提示。

endHomework方法:用于结束指定作业,首先对传入的homeworkId进行非空验证,若为空返回Code.CODE_INVALID_PARAM错误码和 “作业 ID 不能为空” 的提示。验证通过后,使用homeworkMapper.selectById方法根据homeworkId从数据库查询作业信息,若未查询到对应作业,则返回Code.CODE_NOT_FOUND错误码和 “作业不存在” 的提示。若查询到作业,将作业状态设置为 “已结束”(HomeworkStatus.ENDED.getValue()),通过homeworkMapper.updateById方法更新作业状态,根据更新影响的行数判断操作结果,若行数大于 0,记录结束作业的日志并返回成功结果,否则返回Code.CODE_SYSTEM_ERROR错误码和 “结束作业失败” 的提示。
完成了作业的发布、查看和结束等功能:

javaCopy@Override
public Result<?> publishHomework(Homework homework) {
    if (homework == null || homework.getCourseId() == null) {
        return Result.fail(Code.CODE_INVALID_PARAM, "作业信息不完整");
    }
    
    // 设置作业状态为已发布
    homework.setStatus(HomeworkStatus.PUBLISHED.getValue());
    homework.setCreateTime(new Date());
    
    int rows = homeworkMapper.insert(homework);
    if (rows > 0) {
        // 记录日志
        logger.info("教师 {} 发布了作业 {}", homework.getTeacherId(), homework.getHomeworkId());
        return Result.success(homework.getHomeworkId());
    } else {
        return Result.fail(Code.CODE_SYSTEM_ERROR, "发布作业失败");
    }
}

@Override
public Result<List<Homework>> getHomeworkList(Integer courseId) {
    if (courseId == null) {
        return Result.fail(Code.CODE_INVALID_PARAM, "课程ID不能为空");
    }
    
    List<Homework> homeworks = homeworkMapper.selectByCourseId(courseId);
    return Result.success(homeworks);
}

@Override
public Result<?> endHomework(Integer homeworkId) {
    if (homeworkId == null) {
        return Result.fail(Code.CODE_INVALID_PARAM, "作业ID不能为空");
    }
    
    Homework homework = homeworkMapper.selectById(homeworkId);
    if (homework == null) {
        return Result.fail(Code.CODE_NOT_FOUND, "作业不存在");
    }
    
    // 设置作业状态为已结束
    homework.setStatus(HomeworkStatus.ENDED.getValue());
    int rows = homeworkMapper.updateById(homework);
    if (rows > 0) {
        // 记录日志
        logger.info("教师结束了作业 {}", homeworkId);
        return Result.success();
    } else {
        return Result.fail(Code.CODE_SYSTEM_ERROR, "结束作业失败");
    }
}

用户认证功能完善

在上周JWT工具类的基础上,本周完成了完整的用户认证功能:

用户登录功能

实现思路
login接口接收accountpassword两个请求参数,首先利用StringUtils.isEmpty方法对参数进行严格校验,一旦发现账号或密码为空,立即返回Code.CODE_INVALID_PARAM错误码和 “账号或密码不能为空” 的提示。接着通过userService.getUserByAccount方法根据账号查询用户信息,若未查询到对应用户,返回Code.CODE_NOT_FOUND错误码和 “用户不存在” 的提示。在获取到用户信息后,使用passwordEncoder.matches方法对传入的密码和数据库中存储的加密密码进行比对,若密码不匹配,返回Code.CODE_INVALID_PASSWORD错误码和 “密码错误” 的提示。当密码验证通过后,调用jwtUtil.generateToken方法生成 JWT 令牌,将令牌封装在HashMap中,并以Result.success的形式返回给前端,确保用户身份认证和令牌发放的准确性。
实现了管理员和教师两种角色的登录,包括表单验证、状态管理和路由跳转:

javaCopy@PostMapping("/login")
public Result<?> login(@RequestParam String account, @RequestParam String password) {
    // 参数校验
    if (StringUtils.isEmpty(account) || StringUtils.isEmpty(password)) {
        return Result.fail(Code.CODE_INVALID_PARAM, "账号或密码不能为空");
    }
    
    // 查询用户
    User user = userService.getUserByAccount(account);
    if (user == null) {
        return Result.fail(Code.CODE_NOT_FOUND, "用户不存在");
    }
    
    // 验证密码
    if (!passwordEncoder.matches(password, user.getPassword())) {
        return Result.fail(Code.CODE_INVALID_PASSWORD, "密码错误");
    }
    
    // 生成JWT令牌
    String token = jwtUtil.generateToken(user);
    
    // 返回结果
    Map<String, String> data = new HashMap<>();
    data.put("token", token);
    
    return Result.success(data);
}
用户注册功能

实现思路
register方法在用户注册流程中起着关键作用。首先调用userDao.getUser方法,传入空的用户 ID 和待注册的账号,检查该账号是否已被注册,若查询结果中存在对应数据,即表明账号已存在,返回Code.CODE_PARAM_ERROR错误码和 “账号已存在” 的提示。若账号可用,进一步检查用户传入的type字段,若为空则将用户类型设置为默认的学生类型(UserConstants.TYPE_STUDENT)。随后,使用passwordUtil.encode方法对用户密码进行加密处理,最后调用userDao.addUser方法将处理后的用户信息添加到数据库,依据添加操作的结果返回相应的成功或失败信息,保障注册流程的安全性和数据准确性。
完成了用户注册功能,包括表单验证、密码确认和页面跳转:

    @Override
    public Result<Void> register(User user) {
        // 检查账号是否已存在
        Result<User> existingUser = userDao.getUser(null, user.getAccount());
        if (existingUser.getData() != null) {
            return Result.fail(Code.CODE_PARAM_ERROR, "账号已存在");
        }
        
        // 设置用户类型(默认为学生)
        if (user.getType() == null) {
            user.setType(UserConstants.TYPE_STUDENT);
        }
        
        // 加密密码
        user.setPassword(passwordUtil.encode(user.getPassword()));
        
        // 添加用户
        return userDao.addUser(user);
    }
重置密码功能

实现了忘记密码后的重置功能:
实现思路
forgetPassword方法用于处理用户忘记密码后的重置操作。首先通过userDao.getUser方法,传入空的用户 ID 和需要重置密码的账号,获取用户信息,若未查询到对应账号,返回Code.CODE_NOT_FOUND错误码和 “账号不存在” 的提示。在获取到用户信息后,使用passwordUtil.encode方法对新传入的密码进行加密处理,将加密后的密码更新到用户对象中,接着调用userDao.updateUser方法更新数据库中的用户密码信息,根据更新操作的结果返回相应的成功或失败信息,确保密码重置过程的安全可靠。

    @Override
    public Result<Void> forgetPassword(String account, String password) {
        // 获取用户信息
        Result<User> userResult = userDao.getUser(null, account);
        if (userResult.getData() == null) {
            return Result.fail(Code.CODE_NOT_FOUND, "账号不存在");
        }
        
        // 更新密码(加密)
        User user = userResult.getData();
        user.setPassword(passwordUtil.encode(password));
        return userDao.updateUser(user);
    }

后端接口完善

本周根据前端需求,对API接口进行了完善和测试,确保接口的可用性和稳定性。主要修改了以下接口:

  1. 用户登录接口优化:添加了更详细的错误提示和日志记录
  2. 用户信息获取接口增强:支持根据不同条件查询用户信息
  3. 密码重置接口改进:增加了安全验证步骤
  4. 删除用户接口完善:添加了级联删除相关数据的功能
  5. 修改用户接口优化:支持部分字段更新

测试结果

进行了全面的功能测试和边界测试,测试结果如下:

  1. 功能测试通过
    • 管理员登录
    • 教师登录
    • 管理员注册
    • 教师注册
    • 管理员重置密码
    • 教师重置密码
    • 表单验证
    • 错误提示
    • 路由跳转
  2. 边界测试通过
    • 空表单提交
    • 密码不一致
    • 网络错误处理
    • 登录状态保持

本周工作结果

  1. 完成TeacherServiceImpl类实现:实现了教师端主要业务逻辑,包括教师信息管理、学生列表管理、作业管理和题目管理。
  2. 实现用户认证完整功能:完成了用户登录、注册和密码重置功能,提升了系统安全性。
  3. 完善API接口:根据前端需求优化了接口设计,提高了系统的可用性。
  4. 添加代码注释和日志记录:规范了代码风格,便于后续维护。
  5. 完成功能测试:对所有实现的功能进行了测试,确保系统稳定可靠。

总结

本周在后端功能开发上取得了显著进展,完成了教师服务实现类和用户认证功能的开发,为前端提供了完整的API支持。通过统一使用Code类中定义的常量作为错误码,使系统响应更加规范和一致。同时,完善的日志记录和代码注释也提高了代码的可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值