1. 项目概述
这个基于SpringBoot和协同过滤算法的线上安全教育平台,是我最近完成的一个Java毕业设计项目。作为一个有10年开发经验的程序员,我想分享一下这个项目的完整实现过程和技术细节,希望能给正在做毕设的同学一些参考。
这个平台主要解决了传统安全教育形式单一、内容缺乏个性化的问题。通过协同过滤推荐算法,系统能够根据用户的学习行为和偏好,智能推荐最适合的安全教育课程。整个项目采用SpringBoot+Vue的前后端分离架构,数据库使用MySQL,实现了从用户管理、课程推荐到学习记录跟踪的完整功能闭环。
2. 技术架构设计
2.1 整体架构
系统采用典型的三层架构设计:
- 表现层:Vue.js构建的前端界面
- 业务逻辑层:SpringBoot实现的后端服务
- 数据访问层:MyBatis Plus + MySQL
这种分层设计使得系统各模块职责明确,耦合度低,便于后期维护和扩展。我在项目中特别注重接口的规范化设计,前后端通过RESTful API进行数据交互,接口文档使用Swagger自动生成。
2.2 技术选型考量
选择SpringBoot作为后端框架主要基于以下考虑:
- 快速启动:内嵌Tomcat,无需额外配置
- 约定优于配置:减少XML配置
- 丰富的Starter:轻松集成各种组件
- 微服务友好:便于后期扩展
前端选择Vue.js是因为:
- 渐进式框架,学习曲线平缓
- 组件化开发,代码复用率高
- 响应式数据绑定,开发效率高
- 丰富的生态系统(Vuex、Vue Router等)
数据库选用MySQL 8.0,主要看中其:
- 成熟稳定,社区支持好
- JSON数据类型支持,便于存储推荐算法中间结果
- 良好的性能表现
- 完善的ACID特性
3. 核心功能实现
3.1 协同过滤推荐算法
这是本项目的核心创新点。我实现了基于用户的协同过滤算法,主要步骤如下:
- 数据准备阶段:
java复制// 用户-课程评分矩阵
Map<Integer, Map<Integer, Double>> userCourseMatrix = new HashMap<>();
// 从数据库加载用户行为数据
List<UserBehavior> behaviors = behaviorMapper.selectList(null);
for(UserBehavior behavior : behaviors) {
if(!userCourseMatrix.containsKey(behavior.getUserId())) {
userCourseMatrix.put(behavior.getUserId(), new HashMap<>());
}
userCourseMatrix.get(behavior.getUserId())
.put(behavior.getCourseId(), behavior.getScore());
}
- 相似度计算(使用皮尔逊相关系数):
java复制public double calculateSimilarity(Map<Integer, Double> user1,
Map<Integer, Double> user2) {
// 找出共同评价的课程
Set<Integer> commonCourses = new HashSet<>(user1.keySet());
commonCourses.retainAll(user2.keySet());
if(commonCourses.size() == 0) return 0;
// 计算相关系数
double sum1 = 0, sum2 = 0;
double sum1Sq = 0, sum2Sq = 0;
double pSum = 0;
for(int courseId : commonCourses) {
double score1 = user1.get(courseId);
double score2 = user2.get(courseId);
sum1 += score1;
sum2 += score2;
sum1Sq += Math.pow(score1, 2);
sum2Sq += Math.pow(score2, 2);
pSum += score1 * score2;
}
int n = commonCourses.size();
double num = pSum - (sum1 * sum2 / n);
double den = Math.sqrt((sum1Sq - Math.pow(sum1, 2)/n) *
(sum2Sq - Math.pow(sum2, 2)/n));
return den == 0 ? 0 : num / den;
}
- 生成推荐结果:
java复制public List<Recommendation> generateRecommendations(int userId,
int topN) {
// 1. 找到最相似的K个用户
List<SimilarUser> similarUsers = findSimilarUsers(userId, 10);
// 2. 计算推荐分数
Map<Integer, Double> recommendationScores = new HashMap<>();
Map<Integer, Integer> freq = new HashMap<>();
for(SimilarUser simUser : similarUsers) {
double similarity = simUser.getSimilarity();
for(Map.Entry<Integer, Double> entry :
userCourseMatrix.get(simUser.getUserId()).entrySet()) {
int courseId = entry.getKey();
double rating = entry.getValue();
// 跳过用户已经评价过的课程
if(userCourseMatrix.get(userId).containsKey(courseId)) {
continue;
}
// 加权评分
recommendationScores.merge(courseId,
similarity * rating,
Double::sum);
freq.merge(courseId, 1, Integer::sum);
}
}
// 3. 归一化并排序
List<Recommendation> recommendations = new ArrayList<>();
for(Map.Entry<Integer, Double> entry : recommendationScores.entrySet()) {
int courseId = entry.getKey();
double score = entry.getValue() / freq.get(courseId);
recommendations.add(new Recommendation(courseId, score));
}
return recommendations.stream()
.sorted(Comparator.comparing(Recommendation::getScore).reversed())
.limit(topN)
.collect(Collectors.toList());
}
3.2 用户行为采集
为了提升推荐准确度,系统设计了多维度的用户行为采集:
- 显式反馈:
- 课程评分(1-5星)
- 收藏/取消收藏
- 评论内容情感分析
- 隐式反馈:
- 观看时长
- 暂停/回放行为
- 测试完成情况
- 页面停留时间
这些数据通过前端埋点和后端日志两种方式采集,存储在MySQL的user_behavior表中。
3.3 性能优化
推荐算法计算量较大,我做了以下优化:
- 离线计算+实时更新结合:
- 每天凌晨计算全量用户相似度矩阵
- 用户行为触发时,只更新受影响的部分数据
- 缓存策略:
java复制@Cacheable(value = "recommendations", key = "#userId")
public List<Course> getRecommendations(int userId) {
// 生成推荐结果的业务逻辑
}
- 数据库优化:
- 为行为表添加复合索引(user_id, course_id)
- 大表使用分区表
- 热点数据使用Redis缓存
4. 系统关键模块实现
4.1 安全认证模块
采用Spring Security + JWT实现安全的认证授权:
- 登录流程:
java复制@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {
// 1. 验证用户名密码
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginDTO.getUsername(),
loginDTO.getPassword()
)
);
// 2. 生成JWT
SecurityUser user = (SecurityUser) authentication.getPrincipal();
String token = JwtUtil.generateToken(user);
// 3. 返回结果
return Result.success(new LoginVO(token, user.getUsername()));
}
- 安全配置:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
}
4.2 课程管理模块
采用富文本编辑器实现课程内容编辑,支持多种媒体类型:
- 课程实体设计:
java复制@Data
@TableName("course")
public class Course {
@TableId(type = IdType.AUTO)
private Integer id;
private String title;
private String coverImage;
private Integer categoryId;
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> tags;
private String description;
@TableField(typeHandler = JacksonTypeHandler.class)
private CourseContent content; // 包含视频、文档、测试等
private Integer creatorId;
private Date createTime;
private Date updateTime;
private Integer status; // 0-草稿 1-已发布 2-已下架
}
- 内容存储优化:
- 大文本内容使用MySQL的LONGTEXT类型
- 视频文件使用OSS存储,数据库中只保存URL
- 使用Redis缓存热门课程信息
4.3 学习进度跟踪
实时记录用户学习行为,生成学习报告:
- 进度记录设计:
java复制@Data
@TableName("learning_progress")
public class LearningProgress {
@TableId(type = IdType.AUTO)
private Long id;
private Integer userId;
private Integer courseId;
private Integer chapterId;
private Integer status; // 0-未开始 1-进行中 2-已完成
private Integer duration; // 学习时长(秒)
private Integer score; // 测试得分
private Date startTime;
private Date updateTime;
}
- 进度计算逻辑:
java复制public void updateProgress(ProgressUpdateDTO dto) {
// 1. 获取或创建进度记录
LearningProgress progress = progressMapper.selectOne(
new QueryWrapper<LearningProgress>()
.eq("user_id", dto.getUserId())
.eq("course_id", dto.getCourseId())
.eq("chapter_id", dto.getChapterId())
);
if(progress == null) {
progress = new LearningProgress();
progress.setUserId(dto.getUserId());
progress.setCourseId(dto.getCourseId());
progress.setChapterId(dto.getChapterId());
progress.setStatus(1);
progress.setStartTime(new Date());
progressMapper.insert(progress);
}
// 2. 更新学习时长
progress.setDuration(progress.getDuration() + dto.getDuration());
// 3. 更新测试成绩
if(dto.getScore() != null) {
progress.setScore(dto.getScore());
if(dto.getScore() >= PASS_SCORE) {
progress.setStatus(2); // 标记为已完成
}
}
progress.setUpdateTime(new Date());
progressMapper.updateById(progress);
// 4. 更新课程整体进度
updateCourseProgress(dto.getUserId(), dto.getCourseId());
}
5. 系统部署与测试
5.1 部署方案
项目采用Docker容器化部署,主要包含以下服务:
- Web服务:SpringBoot应用
- 数据库:MySQL 8.0
- 缓存:Redis
- 文件存储:MinIO(兼容S3协议)
- 前端:Nginx静态服务
使用docker-compose编排:
yaml复制version: '3.8'
services:
web:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
environment:
- SPRING_PROFILES_ACTIVE=prod
- DATABASE_URL=jdbc:mysql://mysql:3306/safety_edu
- REDIS_HOST=redis
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=safety_edu
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.2
ports:
- "6379:6379"
minio:
image: minio/minio
ports:
- "9000:9000"
volumes:
- minio_data:/data
command: server /data
nginx:
build: ./frontend
ports:
- "80:80"
depends_on:
- web
volumes:
mysql_data:
minio_data:
5.2 性能测试
使用JMeter进行压力测试,主要测试场景:
- 用户登录:100并发,平均响应时间<500ms
- 课程推荐:50并发,平均响应时间<800ms
- 视频播放:30并发,带宽占用<50Mbps
测试结果:
- 推荐算法在100万用户数据量下,离线计算时间约15分钟
- 系统支持500并发用户正常使用
- API平均响应时间<300ms
5.3 安全测试
- 渗透测试:
- SQL注入:使用MyBatis预编译语句防御
- XSS攻击:前端使用vue-sanitize过滤,后端校验
- CSRF:Spring Security默认防护
- 数据安全:
- 敏感信息加密存储(如密码使用BCrypt)
- 通信全程HTTPS
- 定期备份机制
6. 项目总结与改进方向
这个项目从技术选型到最终部署历时3个月,期间遇到了不少挑战,也积累了很多宝贵的经验。以下是几个关键收获:
-
算法优化:最初的全量计算推荐结果性能很差,后来改为增量计算+缓存后性能提升10倍
-
用户体验:通过A/B测试发现,带缩略图的推荐列表点击率比纯文字高35%
-
异常处理:完善了日志监控系统,能够快速定位线上问题
未来改进方向:
- 引入更多推荐算法(如基于内容的推荐)进行混合推荐
- 增加实时推荐能力,利用Kafka处理用户实时行为
- 开发移动端APP,提升学习便捷性
- 引入知识图谱,构建更完善的安全教育体系
对于正在做毕设的同学,我的建议是:
- 尽早确定技术栈,避免后期大改
- 重视文档编写,特别是数据库设计文档
- 模块化开发,方便调试和测试
- 多和导师沟通,及时调整方向
这个项目的完整源码和文档我已经整理好,包含详细的开发文档、数据库设计、API文档等。有需要的同学可以通过文末方式联系我获取,我也会提供一对一的技术指导,帮助大家顺利完成自己的毕业设计。