山东大学软件学院2026项目实训个人博客(二)
项目名称:基于AI大模型的智能考研社区
撰写日期:2026年4月18日
本周我主要完成了项目基础环境的进一步搭建和Redis、RabbitMQ配置的完善,优化当前注册功能、登录功能、错题本CRUD功能,并进行Swagger测试。
一、基础环境搭建
从git仓获取我负责的后端分支develop-backend后,我着手进行基础环境的搭建和本地化配置。
(1)Redis配置类
MessageServiceImpl 通过@RequiredArgsConstructor 注入了 RedisTemplate<String, Object>。Spring Boot 虽然引入了 spring-boot-starter-data-redis 依赖,但默认只自动配置了 RedisTemplate<Object, Object>,不会自动配置 RedisTemplate<String, Object>,因此 Spring 无法找到匹配的 Bean。
因此我创建 RedisConfig 配置类定义 RedisTemplate<String, Object> Bean:
// 使用 String 序列化 Key
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// 使用 JSON 序列化 Value
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
(2)RabbitMQ
安装Erlang和rabbitmq。在RabbitMQ Command Prompt (sbin dir)命令行中启动:
rabbitmq-plugins enable rabbitmq_management
登录进入RabbitMQ仪表盘后在,顶部菜单点击 Queues。在列表中找到 chat-queue(或者是报错日志里提到的队列名)。点击该队列进入详情页。向下滚动找到 Purge 按钮。点击 Purge messages 确认清空(Purge),目的是:清除队列中堆积的异常消息、无效消息或消费失败的死信,避免旧消息持续引发程序报错,使队列恢复正常可用状态,保证新消息能够正常生产与消费。

进一步完善RabbitMQConsumerService.java:
增加 Channel 和 deliveryTag 参数:防止无法手动确认消息,导致脏消息一直重试,可以调用 basicAck /basicNack 控制消息确认;
增加 startsWith ("{") 校验:防止Fastjson 收到 "error" 等文本直接崩溃,提前拦截非 JSON 消息,避免解析异常;
增加 basicNack (deliveryTag, false, false):防止错误消息无限重试,刷屏报错,拒绝消息且不再入队(false, false),彻底丢弃。
(3)创建本地MySQL数据库并修改配置文件
在 Sprint 1 初期进行环境联调时,发现本地开发机无法稳定连接远程云服务器(IP: 47.104.236.72)的 MySQL 服务。因此,将开发阶段的数据源切换至本地。在开发机部署 MySQL 8.0 服务,并通过 Navicat/DBeaver 等可视化工具进行数据库管理。
编写完整的 DDL 脚本,在本地创建 studynote_localdev 数据库,并初始化 user(用户表)、notebook(错题本表)等 6 张核心业务表。
利用 Spring Boot 的 Profile 机制,在 application-dev.yml 中独立配置本地数据源(jdbc:mysql://localhost:3306/studynote_localdev),避免污染远程测试数据;
解决 JDBC 驱动字符集兼容性问题,配置 characterEncoding=UTF-8 。
二、完善现有功能
当前一部分实体类、数据库层、DTO/VO类、Impl 核心逻辑和Controller暴露接口存在缺少注解、代码不简洁、安全性不高等问题,需要进一步完善。
(1)完善User实体类和UserMapper(数据访问层)
给User实体类的添加 Swagger 注解 (@Schema),使代码更易读,指向更明确。同时,删除了原来的 IdType.AUTO,改为 IdType.ASSIGN_ID,使之与配置文件保持一致。
同样,给UserMapper.java(数据访问层)添加注释,说明各个接口用途。
(2)完善登录功能
在初始的登录功能中,后端的LoginVO和UserController会将password明文返回给前端,这在功能上是没必要的,反而会影响安全性。


登录流程分为两个阶段:
阶段 1:验证身份(后端内部完成)
首先用户输入用户名+密码,后端查询数据库找到该用户后,对比密码是否正确,如果正确则验证通过 。这个阶段是在后端内部完成的,前端只需要发送用户名和密码,不需要接收密码回来。
阶段 2:返回登录结果(给前端)
后端验证通过后生成JWT Token(包含 userId),用于后续请求的身份凭证,并将用户 ID、用户名、头像、Token返回给前端。前端保存 Token,跳转到首页。
可以发现,在登录全流程中,后端不需要把密码返回给前端。并且这种行为存在很大的安全隐患。因此,要移除 LoginVO 中的 password 字段,同时修改 UserController,不再返回 password。
此外我发现,UserController的登录缺少验证:没有检查用户名是否为空、没有检查密码是否为空、没有检查用户名长度限制、没有检查密码强度。这会导致当用户提交空的用户名或密码,会引起不必要的数据库查询;可能被恶意利用进行 SQL 注入攻击(虽然 MyBatis-Plus 有防护,但最好还是验证)
因此,在 LoginDTO 中添加验证注解;同时在 UserController 中添加 @Valid 注解启用验证。
@Data
@Schema(description = "用户登录信息")
public class LoginDTO {
@NotBlank(message = "用户名不能为空")
@Size(min = 1, max = 20, message = "用户名长度必须在1-20个字符之间")
@Schema(description = "用户名")
private String name;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")
@Schema(description = "密码")
private String password;
}
(3)修改JwtUtil中Secret key直接在文件里的硬编码
在当前版本,JwtUtil中的Secret key是直接在文件里硬编码的,这导致代码安全性差 (代码提交到 Git 后,所有人都能看到 Secret Key);不灵活(如果想修改过期时间,需要重新编译代码);以及开发、测试、生产环境无法区分。
public static String signKey = "Journey";
public static Long expire = 432000000L;
public static String signName = "Authorization";
因此,将 JWT 配置移到 application-dev.yml,而JwtUtil需要从配置中获取相关内容。
private static String signKey;
@Value("${jwt.sign-key}")
public void setSignKey(String key) {
signKey = key;
}
//expire和signName同理
在application-dev.yml添加配置:
jwt:
sign-key: Journey
expire: 432000000
sign-name: Authorization
这样做的好处是:配置统一管理在 yml 文件中;不同环境可以使用不同的配置(dev/test/prod;)修改配置不需要重新编译;代码符合 Spring Boot 的最佳实践。
三、注册登录功能和错题本CRUD功能的Swagger测试
运行StudynoteApplication,控制台输出:

项目后端启动成功,可以进行Swagger测试。
(1)注册和登录功能测试
在Swagger测试页面里,找到用户管理栏目的user/register和user/login测试块,点击"Try it out",输入测试数据,点击Execute:
{
"name": "test041801",
"password": "123456"
}

HTTP状态码为200,返回值均正常,注册和登录功能测试成功。
(2)错题本CRUD功能测试
a.添加错题本——/notebook/add
测试数据:
{
"id": 0,
"name": "错题本test_0418_1",
"brief": "这是一个错题本添加测试_0418_1"
}

b.获取错题本列表——/notebook/list

c.获取错题本详情——/notebook/detail

d.更新错题本基本信息——/notebook/update
测试数据:
{
"id": 1,
"name": "错题本test0418_1_已更改",
"brief": "这是一个错题本更新测试_0418_1"
}


e.删除错题本——/notebook/delete
测试数据:
{
"id": "1"
}

错题本CRUD功能Swagger测试全部圆满完成。
本周感悟
在本次后端开发的第一阶段,我最大的收获是增强了排查和调试错误、优化代码和功能、进行代码测试的能力。
项目初期,我没有设置好远程数据库配置,不过最终通过在本地搭建 MySQL 并配合可视化工具完成建表解决了问题。随着用户登录与错题本核心功能的跑通,我开始重新检查代码的质量与安全性。我意识到后端接口不能仅仅满足“功能可用”,更要考虑数据边界与隐私保护。因此,我主动移除了登录响应中的密码字段,并将 JWT 密钥从代码中剥离至配置文件。这些改动加深了我对防御性编程、后端安全性的理解,也学会了如何通过配置外置来兼顾系统的安全性与灵活性。
在团队协作中,我对 Git 分支管理与提交规范有了更直观的认识。清晰的版本记录不仅是工作量的证明,更是多人并行开发时保持代码秩序的重要保障。
回顾这一阶段的开发,从环境搭建到Swagger测试成功,每一行代码的落地都让我对后端架构有了更立体的认知。后端开发不仅仅是实现业务逻辑,更是构建稳定、安全、易维护的服务体系。接下来的开发中,我将带着这份学习的热情和开发的严谨,继续推进本次创新项目实践的后续功能开发,努力为整个平台打下坚实的后端基础。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)