1. 项目概述与背景
在线教育平台已经成为现代教育体系中不可或缺的一部分。作为一名长期从事教育信息化开发的工程师,我最近完成了一个基于Java和微信小程序的在线课堂系统开发项目。这个系统采用前后端分离架构,后端使用Spring Boot框架,前端采用微信小程序作为用户界面,实现了课程管理、在线学习、互动交流等核心功能。
为什么选择微信小程序作为前端?在实际开发中我们发现,微信小程序具有以下优势:
- 无需安装,即用即走,用户使用门槛低
- 依托微信生态,用户基数大,传播方便
- 开发成本相对较低,迭代速度快
- 跨平台兼容性好,适配各种移动设备
提示:选择技术栈时,不仅要考虑技术本身的先进性,更要考虑目标用户的使用习惯和实际场景需求。
2. 系统架构设计
2.1 技术选型与考量
后端技术栈:
- 核心框架:Spring Boot 2.5.6(稳定版)
- 数据库:MySQL 8.0(支持JSON数据类型)
- ORM框架:MyBatis-Plus 3.4.3(简化CRUD操作)
- 安全框架:Spring Security(权限控制)
- 缓存:Redis 6.2(提升系统响应速度)
前端技术栈:
- 微信小程序原生开发
- WeUI组件库(保持与微信一致的设计风格)
- ECharts for WeChat(数据可视化)
2.2 数据库设计关键点
数据库设计是系统稳定性的基础,我们特别关注了以下几个关键表的设计:
课程信息表(course_info)
sql复制CREATE TABLE `course_info` (
`id` bigint NOT NULL AUTO_INCREMENT,
`course_name` varchar(100) NOT NULL COMMENT '课程名称',
`category_id` bigint NOT NULL COMMENT '分类ID',
`teacher_id` bigint NOT NULL COMMENT '教师ID',
`price` decimal(10,2) DEFAULT '0.00' COMMENT '课程价格',
`cover_url` varchar(255) DEFAULT NULL COMMENT '封面图URL',
`preview_video` varchar(255) DEFAULT NULL COMMENT '预览视频',
`description` text COMMENT '课程描述',
`status` tinyint DEFAULT '1' COMMENT '状态:0-下架 1-上架',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id`),
KEY `idx_teacher` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
课程视频表(course_video)
sql复制CREATE TABLE `course_video` (
`id` bigint NOT NULL AUTO_INCREMENT,
`course_id` bigint NOT NULL COMMENT '关联课程ID',
`chapter_name` varchar(100) NOT NULL COMMENT '章节名称',
`video_url` varchar(255) NOT NULL COMMENT '视频地址',
`duration` int DEFAULT '0' COMMENT '视频时长(秒)',
`free_flag` tinyint DEFAULT '0' COMMENT '是否免费:0-否 1-是',
`sort_order` int DEFAULT '0' COMMENT '排序权重',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_course` (`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
注意:视频资源建议使用专业云存储服务(如腾讯云点播),不要直接存储在服务器本地,避免服务器带宽和存储压力过大。
3. 核心功能实现
3.1 微信小程序登录流程
微信小程序登录是系统的第一个关键功能点,我们采用了标准的微信登录流程:
- 前端调用wx.login()获取临时code
- 将code发送到后端服务器
- 后端使用code向微信接口服务换取openid和session_key
- 后端生成自定义登录态(token)并返回给小程序
- 小程序存储token用于后续接口鉴权
java复制// 示例代码:微信登录处理
@PostMapping("/wxLogin")
public Result wxLogin(@RequestParam String code) {
// 1. 使用code换取openid
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId
+ "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
String result = HttpUtil.get(url);
JSONObject json = JSON.parseObject(result);
// 2. 处理微信返回结果
if(json.containsKey("errcode")) {
return Result.error(json.getString("errmsg"));
}
String openid = json.getString("openid");
String sessionKey = json.getString("session_key");
// 3. 查询或创建用户
User user = userService.getByOpenid(openid);
if(user == null) {
user = new User();
user.setOpenid(openid);
userService.save(user);
}
// 4. 生成JWT token
String token = JwtUtil.generateToken(user.getId());
return Result.success(token);
}
3.2 课程视频播放实现
视频播放是核心体验功能,我们采用了以下优化方案:
- 视频格式统一转换为H.264编码的MP4格式,确保兼容性
- 实现分段加载(Range请求),支持拖动进度条
- 添加播放记录功能,记录用户学习进度
- 对于付费课程,增加权限验证中间件
java复制// 视频播放权限校验示例
@GetMapping("/video/{videoId}")
public void playVideo(@PathVariable Long videoId, HttpServletRequest request, HttpServletResponse response) {
// 1. 验证用户登录状态
Long userId = JwtUtil.getUserId(request);
if(userId == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return;
}
// 2. 验证课程购买状态
CourseVideo video = videoService.getById(videoId);
if(video == null) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
if(video.getFreeFlag() == 0) {
boolean hasSubscribed = subscribeService.checkSubscribe(userId, video.getCourseId());
if(!hasSubscribed) {
response.setStatus(HttpStatus.FORBIDDEN.value());
return;
}
}
// 3. 获取视频播放地址(这里可以是云存储的临时URL)
String playUrl = videoService.getPlayUrl(videoId);
// 4. 记录播放行为
studyRecordService.recordPlay(userId, videoId);
// 5. 返回播放地址
response.setContentType("application/json");
response.getWriter().write(JSON.toJSONString(Result.success(playUrl)));
}
4. 性能优化与安全实践
4.1 缓存策略设计
为提高系统响应速度,我们设计了多级缓存策略:
- Redis缓存热点数据:课程基本信息、用户基本信息等
- 本地缓存(Caffeine):配置信息、静态数据等
- 数据库查询优化:合理使用索引,避免全表扫描
缓存更新策略采用"先更新数据库,再删除缓存"的方式,确保数据一致性。
4.2 安全防护措施
- 接口防刷:使用Redis实现接口调用频率限制
- XSS防护:对所有用户输入进行过滤和转义
- SQL注入防护:使用预编译语句,禁止拼接SQL
- 敏感数据加密:用户手机号等敏感信息加密存储
- HTTPS传输:所有接口强制使用HTTPS协议
java复制// 接口限流示例
@Aspect
@Component
public class RateLimitAspect {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Around("@annotation(rateLimit)")
public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
String key = "rate_limit:" + getRequest().getRequestURI() + ":" + getUserId();
long count = redisTemplate.opsForValue().increment(key, 1);
if(count == 1) {
redisTemplate.expire(key, rateLimit.time(), rateLimit.timeUnit());
}
if(count > rateLimit.count()) {
throw new BusinessException("操作过于频繁,请稍后再试");
}
return joinPoint.proceed();
}
}
5. 部署与运维实践
5.1 服务器部署方案
我们推荐以下部署架构:
- 前端:微信小程序(托管在微信平台)
- 后端:Spring Boot应用(Docker容器化部署)
- 数据库:MySQL主从架构
- 缓存:Redis集群
- 文件存储:腾讯云COS对象存储
- CDN:腾讯云CDN加速静态资源
5.2 监控与日志
- 应用监控:使用Spring Boot Actuator暴露健康指标
- 日志收集:ELK(Elasticsearch+Logstash+Kibana)栈
- 异常报警:集成Prometheus+Grafana实现监控看板
- 链路追踪:使用SkyWalking进行分布式追踪
提示:生产环境一定要做好日志轮转和归档策略,避免日志文件占用过多磁盘空间。
6. 开发经验与避坑指南
在实际开发过程中,我们积累了一些宝贵经验:
-
微信小程序限制:
- 小程序包大小不能超过2MB(分包后可扩展至8MB)
- 网络请求必须使用HTTPS
- 部分API需要用户授权才能调用
-
视频处理建议:
- 使用FFmpeg进行视频转码和压缩
- 生成多种清晰度的视频源适配不同网络环境
- 添加水印保护版权
-
性能优化技巧:
- 小程序页面使用onPageScroll事件要谨慎,避免频繁触发
- 列表数据实现分页加载,避免一次性加载过多数据
- 使用小程序的自定义组件提高代码复用率
-
测试注意事项:
- 微信开发者工具不能完全模拟真机环境
- 必须测试不同机型的表现差异
- 关注小程序在后台运行时的行为
-
上线前检查清单:
- [ ] 所有接口HTTPS测试
- [ ] 敏感信息加密验证
- [ ] 权限控制测试
- [ ] 压力测试(特别是视频播放接口)
- [ ] 小程序体验评分达到80分以上
这个项目从技术选型到最终上线历时3个月,期间遇到了不少挑战,特别是微信小程序端的兼容性问题和视频播放的流畅度优化。通过这个项目,我们验证了Java+微信小程序技术栈在教育类应用中的可行性,也为后续类似项目积累了宝贵经验。