1. 项目概述与背景
书画艺术作为中华传统文化的重要组成部分,其传承与普及在数字化时代面临新的机遇与挑战。传统书画学习通常受限于时间、空间和师资条件,而在线学习平台能够有效解决这些痛点。本项目基于SpringBoot框架开发的书画在线学习网站,旨在构建一个集课程学习、资源分享、互动交流于一体的综合性平台。
从技术选型角度看,SpringBoot的自动配置特性和起步依赖机制大幅简化了项目搭建过程。我在实际开发中发现,其内嵌Tomcat服务器使得部署变得异常简单,只需打包成JAR即可运行,这比传统War包部署方式节省了至少40%的运维成本。同时,SpringBoot与MyBatis的天然整合,使得数据库操作既保持了灵活性又兼顾了开发效率。
2. 系统架构设计
2.1 技术栈选型
核心框架采用SpringBoot 2.7.x版本,这个选择基于以下考量:
- 自动配置减少了XML配置工作量
- 内置健康检查端点便于监控
- 与Spring生态无缝集成
数据库选用MySQL 8.0,主要考虑因素包括:
- 事务支持完善,ACID特性有保障
- 对JSON数据类型的良好支持
- 社区活跃,问题解决方案丰富
前端技术栈:
- Thymeleaf模板引擎(后台管理)
- Vue.js 3.x(用户前端)
- Element Plus组件库
2.2 系统分层架构
采用经典的三层架构设计:
└── 表现层:Controller + 视图模板 └── 业务层:Service + 业务逻辑 └── 持久层:Mapper + 实体模型特别在权限控制方面,实现了基于注解的细粒度控制:
@PreAuthorize("hasRole('LECTURER')") @PostMapping("/courses") public Result addCourse(@Valid @RequestBody CourseDTO dto) { // 课程添加逻辑 }3. 核心功能实现
3.1 课程管理模块
3.1.1 课程发布流程
讲师用户发布课程时,系统会执行以下关键操作:
- 文件上传处理(视频、教材PDF等)
- 生成课程缩略图
- 写入课程基础信息
- 建立课程-讲师关联
文件上传采用分块上传策略,核心代码如下:
@PostMapping("/upload") public Result chunkUpload(@RequestParam MultipartFile file, @RequestParam String chunkId) { String tempDir = System.getProperty("java.io.tmpdir"); Path chunkPath = Paths.get(tempDir, chunkId); Files.write(chunkPath, file.getBytes()); return Result.success(); }3.1.2 课程检索优化
为提高课程查询效率,设计了复合索引:
ALTER TABLE course_information ADD INDEX idx_search (course_name, course_classification, course_prices);同时采用Elasticsearch实现全文检索,关键配置:
spring: elasticsearch: uris: http://localhost:9200 connection-timeout: 1s3.2 支付与退款模块
3.2.1 支付流程设计
支付状态机设计:
[未支付] → [支付中] → [已支付] ↓ [支付失败]采用策略模式实现多支付渠道:
public interface PaymentStrategy { PaymentResult pay(PaymentRequest request); } @Service @RequiredArgsConstructor public class PaymentService { private final Map<String, PaymentStrategy> strategies; public PaymentResult pay(String channel, PaymentRequest request) { return strategies.get(channel).pay(request); } }3.2.2 退款事务处理
退款操作需要保证数据一致性:
@Transactional public void processRefund(RefundRequest request) { // 1. 更新订单状态 orderRepository.updateStatus(request.getOrderId(), REFUNDING); // 2. 记录退款申请 refundRepository.save(buildRefundRecord(request)); // 3. 调用支付平台API paymentClient.refund(request); }4. 数据库设计实践
4.1 核心表关系
主要实体关系图:
用户 ──┬── 学员 ├── 讲师 └── 管理员 课程 ←── 课程分类 课程 ←── 课程评分 课程 ←── 购买记录4.2 索引优化方案
针对高频查询场景设计的索引:
- 用户登录查询:
user(username) - 课程搜索:
course_information(course_name) - 购买记录:
course_purchase(student_users, pay_state)
4.3 分表策略
对于可能产生海量数据的表(如用户点击记录),采用按月分表策略:
public class HitsTableRouter implements TableShardingAlgorithm { @Override public String doSharding(String logicTable, Map<String, Object> params) { LocalDate date = (LocalDate) params.get("createTime"); return logicTable + "_" + date.getYear() + date.getMonthValue(); } }5. 系统安全设计
5.1 认证与授权
采用JWT + Spring Security实现安全控制:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/admin/**").hasRole("ADMIN") .antMatchers("/api/lecturer/**").hasAnyRole("LECTURER", "ADMIN") .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())); } }5.2 敏感数据保护
密码存储采用BCrypt加密:
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder { private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @Override public String encode(CharSequence rawPassword) { return encoder.encode(rawPassword); } }支付信息加密存储:
@Convert(converter = CryptoConverter.class) private String cardNumber;6. 性能优化实践
6.1 缓存策略
采用多级缓存架构:
- 本地Caffeine缓存(高频访问数据)
- Redis集群(分布式缓存)
- MySQL查询缓存
缓存注解示例:
@Cacheable(value = "courses", key = "#id") public Course getCourseById(Long id) { return courseRepository.findById(id).orElseThrow(); }6.2 异步处理
使用Spring Event实现异步事件:
@EventListener @Async public void handleCoursePurchaseEvent(CoursePurchaseEvent event) { // 发送通知、更新统计数据等非核心操作 }6.3 数据库连接优化
HikariCP配置示例:
spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 6000007. 测试与部署
7.1 测试策略
采用分层测试方案:
- 单元测试(JUnit 5):覆盖率 >80%
- 集成测试(TestContainers)
- API测试(Postman + Newman)
- 压力测试(JMeter)
7.2 持续集成
GitLab CI配置示例:
stages: - test - build - deploy unit-test: stage: test script: - mvn test package: stage: build script: - mvn package -DskipTests7.3 部署方案
采用Docker Compose编排:
version: '3' services: app: image: openjdk:11-jre command: java -jar /app.jar ports: - "8080:8080" volumes: - ./target/app.jar:/app.jar mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root8. 典型问题解决方案
8.1 并发支付问题
使用乐观锁解决超卖:
@Transactional public PaymentResult processPayment(Long orderId) { Order order = orderRepository.findByIdWithLock(orderId); if (order.getStatus() != INIT) { throw new BusinessException("订单状态异常"); } // 处理支付逻辑 }8.2 大文件上传优化
前端分块上传+后端合并:
// 前端实现 const chunkSize = 5 * 1024 * 1024; // 5MB const chunks = Math.ceil(file.size / chunkSize); for (let i = 0; i < chunks; i++) { const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize); uploadChunk(chunk, i); }8.3 搜索性能优化
Elasticsearch索引设计:
{ "mappings": { "properties": { "courseName": {"type": "text", "analyzer": "ik_max_word"}, "lecturerName": {"type": "keyword"}, "price": {"type": "double"} } } }9. 项目演进方向
- 移动端适配:开发React Native应用
- 智能推荐:基于用户行为的协同过滤算法
- 直播教学:集成WebRTC技术
- 证书体系:区块链存证技术
在实际开发过程中,我发现SpringBoot的Actuator端点对于监控系统健康状态非常有用,但需要特别注意安全配置,建议:
management: endpoints: web: exposure: include: health,info endpoint: health: show-details: when_authorized对于数据库连接池配置,经过压测发现连接数并非越大越好,建议根据实际QPS调整:
最大连接数 = (核心数 * 2) + 有效磁盘数