一句话定位:一套「Java 后端 + Vue2 管理端/学生端 + 微信原生小程序」的完整考试系统,2019 年开源至今仍在维护,装机量很大、部署确实简单;代价是技术栈停在 Spring Boot 2.1 + Vue2,协议是 AGPL-3.0,数据库脚本还得去官网领。
| 项 | 值 |
|---|---|
| 仓库地址 | https://gitee.com/mindskip/xzs-mysql (PostgreSQL 版:gitee.com/mindskip/uexam) |
| 项目定位 | 前后端分离的在线考试系统,含管理端、学生端 Web 与微信小程序 |
| 官网 / 演示 | https://www.mindskip.net ;学生端演示 :7001,教师端 :7002 |
| 开源协议 | AGPL-3.0(LICENSE、pom.xml、Gitee 项目信息三处一致) |
| 后端技术栈 | Spring Boot 2.1.6.RELEASE / Java 8 / MyBatis 2.1 / Spring Security / Undertow / MySQL 8 |
| 前端技术栈 | Vue 2.7.16 + Element UI 2.15 + vue-cli 4.5 + Vuex 3 + axios;小程序为微信原生 |
| 当前版本 | 3.9.0(pom.xml、两个前端 package.json、release/xzs-3.9.0.jar 一致) |
| 社区热度 | Gitee 19,275 Star / 3,003 Fork / 1,420 Watch(2026-11-10 查询) |
| 维护方 | 武汉思维跳跃科技有限公司(mindskip),仓库创建于 2019-09-07,最近提交 2026-11-10 |
| 部署形态 | 集成部署(前端打进 jar)/ 前后端分离 / docker-compose |
| 文档日期 | 2026-11-10 |
1. 项目是什么
它是「题库 → 试卷 → 考试 → 判分 → 错题本」这一整条链路的开源实现,不是只给你一个答题页面。仓库里装着四份东西:一个 Spring Boot 后端、管理端 Vue、学生端 Vue、微信原生小程序,四者共用同一套接口。
用一句话概括业务模型:
| 概念 | 对应表 | 说明 |
|---|---|---|
| 学科 | t_subject | 年级 + 科目,题目挂在学科下 |
| 题目 | t_question + t_text_content | 题干是富文本 HTML,单独存一张表,支持图片、表格、数学公式 |
| 试卷 | t_exam_paper | paper_type 区分固定试卷、时段试卷、任务试卷 |
| 任务 | t_task_exam | 管理员按年级下发,每个学生只能做一次 |
| 答卷 | t_exam_paper_answer | 一次作答的总分、状态、耗时 |
| 逐题作答 | t_exam_paper_question_customer_answer | 每题对错、得分、你的答案 |
| 消息 | t_message + t_message_user | 管理员群发,按人记录已读 |
需要先想清楚的一点:它提供的是「系统」,不是「题库」。仓库里的 sql/xzs-mysql.sql 只有 13 张表的结构加两条用户记录,没有学科、题目、试卷数据,README 也写明完整脚本要去官网文档站领。clone 下来跑通之后是一个空系统,第一个学科、第一道题都得自己录。
另外两个容易混淆的点:
mindskip/xzs-mysql是 MySQL 版,mindskip/uexam是 PostgreSQL 版,功能同源但仓库分开维护,选型前先确认自己用哪个库。- 官网同时挂着「维多多培训考试系统」「思多多智能考试系统」两个商业产品,它们和这个开源仓库不是同一个东西,功能对比见第 8 节。
2. 核心特性
| 特性 | 说明 | 对使用者的价值 |
|---|---|---|
| 三端一套后端 | 管理端、学生 Web、微信小程序都打同一组 /api/** 接口 | 后端只维护一次,小程序和 Web 的题目、成绩天然一致 |
| 三种试卷形态 | 固定试卷(组好不变)、时段试卷(限时开放)、任务试卷(按年级下发,限做一次) | 覆盖练习、模考、作业三种真实场景,不用二次开发 |
| 五种题型 | 单选、多选、判断、填空、简答;题干富文本支持图片、表格、公式 | 理科公式题、带图题能直接录,不必接外部题库 |
| 答卷完整留痕 | 总分、状态、逐题对错与你的答案全部落库,可回看、可导出 | 学生自助练习闭环完整,老师只需看结果 |
| 错题本 | 答错自动进 question-error 页面,关联题目详情 | 这是很多付费系统才做的功能,开源版直接有 |
| 单 jar 可部署 | 前端产物放进 resources/static,一个 jar 同时供出 /student、/admin | 学校内网一台机器、一条命令就能上线 |
| 无 Redis 依赖 | 登录 token 存 t_user_token 表,不引缓存中间件 | 部署清单最短:只要 JDK 8 + MySQL 8 |
| 微信登录绑定 | 小程序端 wx.login 换 code,后端绑定 openid 并存 token | 学生不用注册,微信一键进考试 |
| 消息中心 | t_message / t_message_user 记录发送与已读 | 通知考试安排不必靠微信群吼 |
| Excel 导入导出 | 管理端带 xlsx、file-saver | 批量导学生名单、导成绩,避免手工点录 |
| 图片上传可托管 | 后端接七牛云 SDK,也支持前端直传鉴权(/api/admin/upload/auth) | 题目图片不占应用服务器磁盘 |
3. 技术架构
整体结构:单体 Spring Boot 应用 + 两个独立 SPA + 一个原生小程序。没有注册中心、没有消息队列、没有 Redis,属于「一台 4C8G 能扛一个学校」的经典单体。
| 层 | 技术 | 说明 |
|---|---|---|
| 后端框架 | Spring Boot 2.1.6.RELEASE | 2019 年的版本,maven.compiler.target 为 1.8 |
| Web 容器 | Undertow | pom 里显式排除了 tomcat;io-threads: 16、worker-threads: 4000 |
| 持久层 | MyBatis 2.1.0 + PageHelper 1.2.12 | 13 个 Mapper XML,放在 resources/mapper/ |
| 安全 | Spring Security | 登录口令用 RSA 公钥加密后传输(system.pwdKey),白名单在 security-ignore-urls 里逐条配置 |
| 会话 | 自签 token + t_user_token 表 | 不依赖 Redis,token 有效期 token-to-live: 12h |
| 数据库 | MySQL 8(驱动 8.0.17) | 连接串带 allowMultiQueries=true,批量 SQL 依赖这个参数 |
| 对象存储 | 七牛云 SDK 7.2.25 | 配置项 system.qn(url / bucket / access-key / secret-key) |
| 管理端 | Vue 2.7.16 + Element UI 2.15 + Vuex 3 + vue-router 3 | vue-cli 4.5,dev 端口 8002,/api 代理到 8000 |
| 学生端 | 同栈 | dev 端口 8001,outputDir 为 student |
| 小程序 | 微信原生(WXML/WXSS)+ iView Weapp | libVersion 2.8.0,接口地址写在 app.js 的 globalData.baseAPI |
| 构建 | Maven(含 mvnw)+ spring-boot-maven-plugin | 前端 vue-cli-service build --mode prod |
后端分层(com.mindskip.xzs):
| 包 | 职责 |
|---|---|
controller/admin、controller/student、controller/wx | 三端接口分开写,权限边界清晰 |
service | 业务逻辑,试卷组卷、判分、任务下发都在这里 |
repository | MyBatis Mapper 接口,SQL 在 resources/mapper/*.xml |
domain | 数据库实体,字段与表一一对应 |
viewmodel | 出入参 DTO/VO,避免实体直接透出 |
configuration | Security、Web、上传等配置 |
context | 当前登录用户上下文(ThreadLocal) |
event / listener | 事件驱动(如答卷提交后触发后续处理) |
utility / exception / base | 加密、响应包装、全局异常 |
几个关键取舍:
- 不引 Redis:省了一个组件,但每次鉴权都要查一次 MySQL。几百人同时在线没问题,千人级并发考试时数据库会先到瓶颈。
- Spring Boot 2.1 + Java 8:好处是能跑在几乎任何老服务器、老宝塔环境上;坏处是这个分支早已结束维护,Spring Security 也是 5.1 语法,想升到 3.x 基本等于重写安全配置。
- Vue 2 + Element UI:2023 年底 Vue 2 已停止维护,Element UI 同样不再迭代,配套的
node-sass6 只能配 Node 14–16。这不是本项目的问题,是这类 2019 年前后项目的通病。 - 小程序用原生而不是 uni-app:包体小、微信能力调用直接;代价是同一套学生端页面写了两遍(Web 一遍、小程序一遍)。
4. 目录结构
| 路径 | 用途 |
|---|---|
source/xzs/ | Maven 后端工程,入口 XzsApplication.java |
source/xzs/src/main/resources/application.yml | 主配置:端口 8000、Security 白名单、RSA 密钥对、微信 appid、七牛密钥、token 有效期 |
source/xzs/src/main/resources/application-{dev,pre,prod,test}.yml | 分环境数据源,只有 datasource 与日志路径 |
source/xzs/src/main/resources/mapper/ | 13 个 MyBatis XML,按表拆分(试卷、题目、用户、消息、日志等) |
source/xzs/src/main/resources/static/{admin,student}/ | 集成部署时放前端产物,/admin、/student 由此供出 |
source/vue/xzs-admin/ | 管理端源码,outputDir: 'admin' |
source/vue/xzs-student/ | 学生端源码,outputDir: 'student' |
source/wx/xzs-student/ | 微信小程序源码(app.js / pages / component / utils / wxs) |
sql/xzs-mysql.sql | 建库 + 13 张表结构 + 2 条用户记录,无题库数据 |
release/java/xzs-3.9.0.jar | 官方编译好的 jar,直接可跑(配置仍是默认的 root/123456) |
release/web/{admin,student}/ | 官方编译好的前端静态文件 |
docker/docker-compose.yml | MySQL 8.0.33 + Java 1.8 两容器,端口 8000 |
docker/install/docker-compose-linux-x86_64 | 仓库里直接塞了一个 docker-compose 二进制(x86_64) |
docs/ | VuePress 文档站的构建产物(HTML),源文档不在仓库里 |
README.md / LICENSE | 功能清单与 AGPL-3.0 全文 |
仓库里有两处不太常见的做法值得注意:release/ 把编译产物直接提交进 Git,好处是「不懂 Maven 也能上线」,坏处是仓库体积和 diff 噪音;source/vue/*/ 下各有一个 node_modules.zip,把依赖打包塞进了源码目录。
5. 快速上手
路线 A:先用官方包跑通(最快)
# 1. 建库并导入结构:脚本自带 CREATE DATABASE,登录 MySQL 后执行
# source /path/to/sql/xzs-mysql.sql
# 2. 启动(数据源务必换掉默认的 root/123456,见 application-prod.yml)
export SPRING_DATASOURCE_USERNAME=你的账号
export SPRING_DATASOURCE_PASSWORD=你的密码
java -Duser.timezone=Asia/Shanghai -jar release/java/xzs-3.9.0.jar --spring.profiles.active=prod启动后访问 http://服务器IP:8000/student 与 /admin。前端产物已经在 jar 的 static/ 里,不需要单独部署 Nginx。
路线 B:docker-compose
# compose 把 ./sql 挂到 MySQL 初始化目录,先把脚本放进去
cp sql/xzs-mysql.sql docker/sql/
cd docker
docker compose up -d注意两点:compose 里 MySQL 的 root 密码写死为 123456,Java 容器用 network_mode: host 加 privileged: true;./log 目录要先建好,否则挂载会失败。
路线 C:前端二次开发
cd source/vue/xzs-admin
npm config set sass_binary_site https://npmmirror.com/mirrors/node-sass
npm install --registry=https://registry.npmmirror.com
npm run serve # 8002,/api 代理到 localhost:8000学生端同样操作,端口 8001。Node 必须是 14 或 16:node-sass@6 在 Node 17+ 上装不上。如果本机只有 Node 18/20,最省事的做法是卸掉 node-sass,改装 sass + sass-loader@10。
路线 D:微信小程序
- 用微信开发者工具导入
source/wx/xzs-student; - 把
project.config.json的appid换成自己的; - 改
app.js里globalData.baseAPI,从http://localhost:8000改成自己的 https 域名; - 在小程序后台配置 request 合法域名,开发阶段可勾「不校验合法域名」。
6. 功能模块清单
学生端(Web 与小程序功能一致)
| 模块 | 说明 |
|---|---|
| 登录 / 注册 | 用户名密码;注册时选年级 |
| 任务中心 | 管理员按年级下发的任务,每人只能做一次 |
| 考试 | 题干支持文本、图片、公式、表格,答题以文本为主 |
| 固定试卷 | 可重复练习、自行批改 |
| 时段试卷 | 在限定时间窗口内可反复练习 |
| 考试记录 | 查看历史答卷与试卷信息 |
| 错题本 | 答错自动入库,可回看题目 |
| 个人信息 / 更新信息 | 资料、头像修改 |
| 个人动态 | 最近行为记录(t_user_event_log) |
| 消息中心 | 接收管理员消息并标记已读 |
管理端
| 模块 | 说明 |
|---|---|
| 仪表盘 | 试卷数、题目数、用户活跃度、月度题量 |
| 学生管理 | 增删改查、禁用、Excel 导入导出 |
| 管理员管理 | 增删改查、禁用 |
| 学科管理 | 按年级建学科、改名、删除 |
| 试卷管理 | 查询、编辑、删除;创建固定/时段/任务试卷 |
| 题目管理 | 五种题型,题干富文本(图片、表格、公式) |
| 任务管理 | 按年级下发,控制完成次数 |
| 消息管理 | 群发消息、查看已读人数 |
| 用户日志 | 全站操作日志 |
| 个人资料 | 姓名、手机号、创建时间线 |
7. 版本与授权
| 项 | 实际情况 |
|---|---|
| 版本号 | 3.9.0,pom.xml、xzs-admin/package.json、xzs-student/package.json、release/java/xzs-3.9.0.jar 四处一致 |
| Git 标签 / Release | 没有。Gitee API 返回的 tags 与 releases 均为空数组,版本只能看 release 目录里的 jar 名和提交记录 |
| 许可证 | AGPL-3.0(LICENSE 全文、pom.xml 的 licenses 节点、Gitee 项目信息一致) |
| 版权方 | 武汉思维跳跃科技有限公司,官网版权标注 2020–2026 |
| 更新节奏 | 近期提交以「教程更新」「组件升级」「bug fix」为主,2026-11 仍在提交 |
AGPL-3.0 这一点值得单独说明,因为它是本次选型里最容易踩的合规坑:
- 你可以免费自用、改造、内部部署;
- 但只要把改造后的系统通过网络提供给外部用户使用(典型的 SaaS 考试平台、对外培训平台),就必须向使用者提供完整源码,包括你的修改;
- 想闭源商用,只有两条路:买官方商业授权,或者自己从零重写。
如果你只是学校/公司内部用,这不影响;如果你打算拿它做对外的付费考试服务,先算清这条。
8. 商业模式说明
开源仓库本身不收钱,也没有「开源版 + 企业版仓库」的分裂。官方把商业化放在官网,用三档产品做区分。以下三档的对照来自官网产品页(2026-11 抓取):
| 维度 | 学之思(开源版) | 维多多(高级版) | 思多多(旗舰版) |
|---|---|---|---|
| 界面设计 | 标准 | 高级 | 高级 |
| 后台技术栈 | Spring Boot / MyBatis / Vue2 / Element UI | 增加 Redis,仍是 Vue2 | Vue3 / Element Plus |
| 小程序端 | 微信原生 | 微信原生 | uni-app(小程序、H5、安卓、iOS) |
| 商业授权 | 无 | 有 | 有 |
| 技术支持 | 无 | 有 | 有 |
| 内网部署 | 无 | 有 | 有 |
也就是说:开源版拿走了「能用」,商业版卖的是「能商用 + 有人管 + 能上多端」。
另外,README 和部署文档里反复出现的「数据库脚本领取地址 https://www.mindskip.net:999」是文档站,教程与视频教程也在那里。仓库里的 SQL 只有表结构,完整数据要按官网指引获取——这一步的授权范围以官方说明为准,别默认「代码 AGPL 就等于所有配套资源随便用」。
作者的变现路径很清晰:商业授权 + 定制开发 + 部署服务,外加两个同源商业产品。这也是这类国产开源项目的标准打法。
9. 生态与周边
| 项目 / 资源 | 作用 | 地址 |
|---|---|---|
mindskip/xzs-mysql | MySQL 版本仓库(本文对象) | gitee.com/mindskip/xzs-mysql |
mindskip/uexam | PostgreSQL 版本,功能同源 | gitee.com/mindskip/uexam |
| GitHub 镜像 | mindskip/xzs-mysql、mindskip/xzs(PG 版) | github.com/mindskip |
| GitCode 镜像 | 同上两套 | gitcode.com/mindskip |
| 官网文档站 | 部署教程、开发文档、数据库脚本指引 | www.mindskip.net:999 |
| 视频教程 | B 站官方账号 | space.bilibili.com/1389892305 |
| 技术交流 | QQ 群 18:700540955 | — |
| 商业产品 | 维多多培训考试系统、思多多智能考试系统 | www.mindskip.net/wdd.html、/sdd.html |
| 容器镜像 | 阿里云 registry.cn-hangzhou.aliyuncs.com/mindskip/{mysql,java} | 仅这两个,非官方 Docker Hub |
生态上有一个空白要提醒:没有 uni-app / 移动 App 版本,也没有官方 Helm、K8s 清单。docker 目录给的是最朴素的 compose,多实例部署、灰度、水平扩容都得自己做。
10. 选型建议
适合你,如果:
- 场景是学校、培训机构、企业内部考核,几百到几千人规模;
- 必须私有化/内网部署,数据不能出机房;
- 团队会 Java、能读 Spring Boot,愿意接一个「结构清楚但版本偏老」的工程;
- 需要一个功能闭环的底座(题库、组卷、考试、错题、消息),在此基础上改业务;
- 想要微信小程序考试,但不想为小程序单独写一套后端。
不适合你,如果:
- 要做对外经营的 SaaS 考试平台且不打算开源改造后的代码(AGPL 卡在这里);
- 对前端技术栈有要求(Vue3 / TypeScript),或需要长期安全维护承诺;
- 预期「万人在线同时开考」——没有 Redis、没有队列,判分与写入全压在 MySQL 上;
- 需要移动 App、需要多租户隔离、需要直播/防作弊等考场管控能力;
- 只想白嫖题库:这套系统的价值在流程,不在内容。
和同类怎么比:市面上的开源考试系统大致分两类——一类像本项目,单体 + 完整业务闭环,装完就能用;另一类偏「考试引擎」或前端模板,需要自己接题库与判分。本项目的优势是部署路径短、功能齐、三端都有,劣势是技术债明显、无版本标签、文档站与代码分离。如果你能接受「2019 年的技术栈」,它是同价位里最省心的选择;如果你要的是能长期演进的地基,建议把它当参考实现而不是最终底座。
11. 风险与坑
- 配置文件里躺着真密钥:
application.yml明文存了 RSA 公私钥对(登录口令加密用)、七牛云的 AccessKey/SecretKey、微信小程序 appid,application-prod.yml里数据库是 root/123456,docker-compose.yml的 MySQL root 密码也是 123456。上线前把这些全部换掉;如果这些是对方真实在用的凭据,建议同步轮换。 - RSA 私钥公开的后果:口令加密的意义在于防明文传输,私钥进了公开仓库,等于这层保护只剩「防君子」。别照抄这段配置。
- SQL 里没有题库:
sql/xzs-mysql.sql只有 13 张表 +student/admin两条用户记录,导入后是一个空系统。README 与部署文档都指向官网文档站领取完整脚本,这一步别跳过,也别指望 demo 数据。 - 默认口令别猜:两个初始用户的密码哈希相同,说明是同一口令;官网演示站给的示例是
student / 123456,但那是对应商业版的演示环境,开源版初始口令以官方文档为准,登不进去就按文档重置。 docker/里塞了二进制:docker/install/docker-compose-linux-x86_64是仓库直接提交的二进制文件;compose 又用了privileged: true+network_mode: host。生产环境建议换成发行版自带的 docker compose 插件,并去掉特权。- 前端目录里有
node_modules.zip:xzs-admin与xzs-student各一份,clone 时间会明显变长,别误当成依赖清单。 - Node 版本陷阱:
node-sass@6+vue-cli@4只认 Node 14–16;Node 18/20 上npm install直接编译失败。要么降 Node,要么换 dart-sass。 - Spring Boot 2.1.6 已 EOL:这个分支 2019 年就停止维护了,Undertow、Jackson 等传递依赖的已知漏洞要自己评估;Spring Security 5.1 的写法与 5.7/6.x 差异很大,升级成本接近重写。
- 集成部署的路径要求死:前端产物必须放到
source/xzs/src/main/resources/static/下的admin、student两个目录,publicPath是'./',放错一层就是白屏。 - 小程序接口地址写死在代码里:
app.js的baseAPI是http://localhost:8000,真机必须改成 https 域名并配好白名单,否则所有请求静默失败。 - 学生端带了别人的统计代码:
source/vue/xzs-student/public/index.html里内嵌了百度统计脚本(站点 IDcd8218cd...),自建站点要删掉,否则访客数据进了别人的统计账号。 - 没有版本标签:想追变更只能翻提交记录,升级时无法用「3.8.0 → 3.9.0 的 changelog」判断影响面。
- 时区:启动参数必须带
-Duser.timezone=Asia/Shanghai,时段试卷的开考与截止时间依赖它;容器默认 UTC 会导致时间窗口错 8 小时。 - 数据库连接串的
allowMultiQueries=true:后端有批量 SQL 依赖这个参数,自建连接池时漏掉会报错。
12. 参考链接
| 名称 | 地址 |
|---|---|
| 代码仓库(Gitee,MySQL 版) | https://gitee.com/mindskip/xzs-mysql |
| 代码仓库(PostgreSQL 版) | https://gitee.com/mindskip/uexam |
| GitHub 镜像 | https://github.com/mindskip/xzs-mysql |
| 官网 | https://www.mindskip.net |
| 学之思产品页 | https://www.mindskip.net/xzs.html |
| 商业授权与购买 | https://www.mindskip.net/buy.html |
| 文档站 | https://www.mindskip.net:999 |
| 学生端在线演示 | https://www.mindskip.net:7001 |
| 教师端在线演示 | https://www.mindskip.net:7002 |
| 视频教程 | https://space.bilibili.com/1389892305 |
| AGPL-3.0 协议全文 | https://www.gnu.org/licenses/agpl-3.0.txt |
本文基于 2026-11-10 的 master 分支源码(pom.xml、application.yml、vue.config.js、package.json、sql 脚本、docker 配置)、Gitee API 数据与官网产品页整理;Star 数、版本号、模块清单均以该日为准,后续迭代请以仓库实际内容为准。*