这个基于Java+SSM+Flask的数学竞赛网站是一个面向数学竞赛培训的综合性在线平台。作为从业十年的全栈开发者,我设计这个系统的初衷是解决传统数学竞赛培训中的三个核心痛点:训练资源分散、学习进度难追踪、师生互动效率低。系统采用混合架构设计,前端使用Vue.js+ElementUI实现响应式布局,后端业务层用Java+SSM处理核心竞赛逻辑,而Python Flask则专门负责数学公式渲染和题目推荐算法。
技术选型心得:选择SSM而非Spring Boot是为了兼容学校已有的Java EE基础设施,而Flask的轻量级特性非常适合快速实现数学特有的算法模块。
系统采用分层架构设计,物理拓扑如下图所示(省略图示说明)。值得特别说明的是我们设计的异步批改系统:
java复制// 伪代码示例:竞赛题目自动批改流程
public class AutoGrader {
@Async
public void gradeSubmission(Submission sub) {
// 1. 基础答案比对
if (exactMatch(sub.answer, stdAnswer)) {
sub.setScore(fullMark);
} else {
// 2. 调用Mathematica引擎进行步骤分解析
stepScore = mathKernel.evaluateSteps(sub.working);
// 3. 人工批改队列处理
if (stepScore < 0.3) {
humanReviewQueue.add(sub);
}
}
}
}
题目管理系统采用JSON Schema定义题目数据结构:
json复制{
"question": {
"stem": "设函数f(x)=...",
"options": ["A. √2", "B. √3"],
"answer_type": "single_choice|multi_choice|open_end",
"difficulty": 3,
"knowledge_points": ["三角函数", "导数应用"],
"solution_steps": [
{"step": "求导过程", "score": 2},
{"step": "极值判定", "score": 3}
]
}
}
开发教训:初期使用富文本编辑器存储题目导致公式渲染不一致,后来改用Markdown+LaTeX混合格式。
Java和Python服务间采用两种通信方式:
Flask服务暴露的关键端点示例:
python复制@app.route('/api/math/render', methods=['POST'])
def render_latex():
data = request.get_json()
# 使用MathJax服务器端渲染
svg = latex2svg(data['latex'])
return jsonify({'svg': svg, 'width': svg.width})
对比测试了三种公式渲染方案:
| 方案 | 渲染速度 | 兼容性 | 部署复杂度 |
|---|---|---|---|
| MathJax客户端渲染 | 慢 | 优 | 简单 |
| MathJax服务器端渲染 | 中 | 优 | 中等 |
| LaTeX转SVG | 快 | 良 | 复杂 |
最终选择方案三,采用Docker部署的LaTeX环境:
dockerfile复制FROM texlive/texlive:latest
RUN apt-get install -y ghostscript
COPY tex2svg /usr/local/bin/
基于Elo评级系统改进的题目推荐算法:
python复制def calculate_elo(user_skill, question_diff, is_correct):
expected = 1 / (1 + 10**((question_diff - user_skill)/400))
k = 32 * (1 - 0.5**user_attempt_count)
new_skill = user_skill + k * (is_correct - expected)
return new_skill
实现的多维度防作弊策略:
压力测试发现的性能瓶颈及解决方案:
| 场景 | 初始QPS | 优化措施 | 优化后QPS |
|---|---|---|---|
| 竞赛提交高峰 | 120 | Redis缓存题目数据 | 850 |
| 自动批改队列堆积 | 200 | 增加Kafka分区数 | 1500 |
| 实时排名更新 | 300 | 改用增量更新策略 | 1200 |
Java和Python服务协同部署的两种模式:
bash复制# 使用supervisor管理进程
[program:flask_math]
command=/opt/math_venv/bin/gunicorn -w 4 app:app
docker-compose复制services:
java-app:
image: openjdk:11
ports: ["8080:8080"]
math-service:
image: python:3.8
command: ["gunicorn", "-b", ":5000", "app:app"]
现象:部分Linux服务器上公式显示为方框
排查:
解决方案:
bash复制# 安装缺失的字体
apt-get install -y fonts-noto-cjk fonts-noto-math
现象:高峰期提交响应时间超过5秒
优化步骤:
最终配置:
properties复制spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.connection-timeout=3000
在实际运营中,我们发现三个值得优化的方向:
移动端体验优化:
智能诊断系统:
python复制def diagnose_errors(answer_pattern):
# 使用预训练的错误模式识别模型
return common_errors[nearest_neighbor(answer_pattern)]
这个项目让我深刻体会到教育类系统的特殊挑战:既要保证技术的严谨性,又要考虑教育的人性化需求。比如在自动批改系统中,我们最终保留了人工复核通道,因为有些解题创意无法用算法完全评估。