☰
SSM+微信小程序答题系统实战:从源码到部署的避坑指南
2026/9/28 14:46:40 网站建设 项目流程

简介:这是一套基于Java、SSM框架、MySQL与微信小程序开发的答题小程序完整项目资源,面向需要完成毕业设计、课程设计或期末大作业的计算机相关专业学生。项目已通过导师指导与严格调试,下载后可直接运行,无需额外修改,适合作为高分毕设参考或教学演示案例。压缩包共1095个文件,约14.92MB,涵盖Java源码、Vue前端组件、微信小程序wxml与wxss页面、MySQL数据库脚本、项目配置及说明文档等,前后端代码与数据库脚本齐全,并附完整毕业设计论文。系统包含用户注册登录、题目展示、在线答题、成绩统计等核心功能,同时支持管理员对题库、用户权限与数据统计进行管理,界面美观、操作简便,具有较高的实际应用价值。目前已有68人学习关注,适合希望快速搭建答题类应用、理解SSM与小程序整合开发流程的读者参考使用。

1. 从一份“高分毕业设计”压缩包说起:SSM+微信小程序答题系统到底能跑多远

每年毕业季,计算机专业的群里总会出现类似“基于java+ssm+mysql+微信小程序的答题小程序 源码+数据库+论文(高分毕业设计).zip”这样的文件。很多人第一反应是下载、解压、改个名字交差,但真正动手跑起来才发现:数据库连不上、小程序端请求 404、SSM 配置里一堆看不懂的 XML。这个标题背后其实是一套非常典型的 Java Web 技术栈组合——后端用 SSM(Spring + SpringMVC + MyBatis),数据库用 MySQL,前端用微信小程序,业务是答题/考试。它解决的核心问题是:如何用一套成熟、资料多、面试常问的技术栈,快速搭出一个能演示、能答辩、能二次开发的在线答题系统。适合的人群很明确:正在做课程设计或毕业设计的学生、想练手 SSM 的 Java 新手、需要一个小程序全栈案例的开发者。但“能跑起来”和“跑得稳”之间,隔着数据库连接池、请求封装、缓存时间设置这些具体细节,下面就把这条路一步步走通。

2. 技术选型与工程结构:为什么是 SSM 而不是 Spring Boot

2.1 SSM 在答题小程序里的角色分工

SSM 是三个框架的合称,各自负责一层。Spring 管对象和依赖注入,SpringMVC 管 HTTP 请求路由和参数绑定,MyBatis 管 SQL 映射和结果集转换。在答题小程序这个场景里,小程序端发起wx.request,请求先到 SpringMVC 的 Controller,Controller 调用 Service,Service 通过 MyBatis 的 Mapper 接口操作 MySQL,最后把 JSON 返回给小程序。这个链路清晰、分层明确,也是很多高校课程设计要求的“标准三层架构”。

为什么不用 Spring Boot?因为很多学校的教学大纲还停留在 SSM 阶段,答辩老师对 XML 配置更熟悉,而且 SSM 的配置文件能直接体现你对 Spring 容器、事务管理、MVC 流程的理解。另一个现实原因是:网上现成的 SSM 答题项目源码多,改起来有参考。但要注意,SSM 的 XML 配置一旦写错,启动就报BeanCreationException,排查成本比 Spring Boot 的自动配置高不少。

2.2 从压缩包到可运行工程的目录拆解

拿到源码后,先别急着导入 IDE。把压缩包解压,通常能看到这几个目录:src/main/java放 Java 代码,src/main/resources放 Spring 和 MyBatis 的 XML 配置,src/main/webapp放前端页面和静态资源,sql目录放数据库脚本,wx或miniprogram目录放小程序代码。论文一般是独立的 Word 或 PDF。

导入 IDEA 或 Eclipse 后,第一步是检查pom.xml里的依赖版本。常见坑是 MySQL 驱动版本和本地 MySQL 版本不匹配,比如驱动写的是5.1.47,本地装的是 MySQL 8.0,连接时会报Unknown system variable 'query_cache_size'。解决办法是把驱动换成mysql-connector-java 8.0.x,同时把 JDBC URL 里的useSSL设为false,并加上serverTimezone=Asia/Shanghai。

<!-- pom.xml 中 MySQL 驱动依赖,按本地版本调整 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>

参数说明:version要和本地 MySQL 大版本一致;如果本地是 5.7,用5.1.49也可以,但 8.0 驱动向下兼容更好。改完依赖后,在 IDEA 右侧 Maven 面板点刷新,让依赖重新下载。

2.3 数据库脚本导入与连接池配置

打开sql目录下的.sql文件,里面通常有建库、建表、插入初始数据的语句。用 Navicat 或 MySQL Workbench 连接本地 MySQL,新建一个数据库,字符集选utf8mb4,然后运行 SQL 文件。注意:如果脚本里写死了CREATE DATABASE和USE,直接执行即可;如果没有,先手动建库再执行表结构。

连接池配置在applicationContext.xml或spring-dao.xml里,常见的是 Druid 或 C3P0。找到dataSource这个 Bean,把jdbcUrl、username、password改成自己的。Druid 的initialSize、maxActive、minIdle这几个参数决定连接池行为,毕设演示环境设initialSize=5、maxActive=20就够用。

<!-- spring-dao.xml 中 Druid 数据源配置片段 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="jdbc:mysql://localhost:3306/answer_db?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="你的密码"/> <property name="initialSize" value="5"/> <property name="maxActive" value="20"/> </bean>

逻辑说明:url里的answer_db要换成你实际建的库名;useSSL=false避免本地连接时的 SSL 警告;serverTimezone不设会导致时间字段差 8 小时。改完后启动 Tomcat,如果控制台没有报Access denied或Communications link failure,说明数据库层通了。

3. 后端接口与小程序请求的对接:从登录到答题提交

3.1 答题业务的核心表结构与接口设计

答题系统的数据库通常至少包含这几张表:user(用户)、question(题目)、exam(试卷/考试)、record(答题记录)。题目表里一般有type字段区分单选、多选、判断,options字段存 JSON 格式的选项,answer存正确答案。答题记录表存用户 ID、试卷 ID、得分、提交时间。

后端接口按 RESTful 风格设计,常见的有:POST /user/login登录、GET /question/list按试卷拉题、POST /record/submit提交答案并判分。Controller 里用@RequestMapping和@ResponseBody返回 JSON。这里有个容易翻车的点:小程序端wx.request默认不带 cookie,如果后端用 session 存登录态,第二次请求就会丢登录。常见做法是登录成功后返回一个 token,小程序存到wx.setStorageSync,后续请求在 header 里带上。

// UserController.java 登录接口片段 @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public Map<String, Object> login(@RequestBody Map<String, String> params) { Map<String, Object> result = new HashMap<>(); User user = userService.findByUsername(params.get("username")); if (user != null && user.getPassword().equals(params.get("password"))) { String token = UUID.randomUUID().toString(); redisTemplate.opsForValue().set(token, user.getId(), 2, TimeUnit.HOURS); result.put("code", 200); result.put("token", token); } else { result.put("code", 401); result.put("msg", "用户名或密码错误"); } return result; }

参数说明:@RequestBody要求小程序端header里设content-type: application/json;token 存 Redis 并设 2 小时过期,对应热搜词里“微信小程序设置缓存时间”的需求。如果没有 Redis,也可以用ConcurrentHashMap临时存,但重启就丢,只适合演示。

3.2 小程序端请求封装与顶部导航栏适配

小程序端不要在每个页面里裸写wx.request,否则接口地址一改就要全局搜替换。常见做法是新建一个utils/request.js,统一拼 baseURL、统一带 token、统一处理 401 跳登录。

// utils/request.js 请求封装 const BASE_URL = 'http://localhost:8080/answer'; function request(options) { const token = wx.getStorageSync('token'); return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'content-type': 'application/json', 'token': token }, success(res) { if (res.data.code === 401) { wx.redirectTo({ url: '/pages/login/login' }); return; } resolve(res.data); }, fail(err) { reject(err); } }); }); } module.exports = { request };

逻辑说明:BASE_URL在开发时指向本地 Tomcat,上线要换成备案域名;token从缓存取,登录后写入。注意小程序开发工具里要勾选“不校验合法域名”,否则 localhost 请求会被拦截。顶部导航栏高度在不同机型上不一样,可以用wx.getSystemInfoSync().statusBarHeight加上 44px 得到自定义导航栏总高度,避免标题被刘海挡住。

3.3 答题提交与判分的实现细节

提交答案时,小程序把用户选择的选项数组发给后端,后端根据题目 ID 查出正确答案,逐题比对算分。这里要注意多选题的判分逻辑:少选、多选、错选通常都算错,但有些系统允许少选得一半分。实现时把正确答案和用户答案都转成 Set,用Set.equals判断是否完全一致。

// RecordService.java 判分逻辑 public int calculateScore(List<UserAnswer> userAnswers, Long examId) { List<Question> questions = questionMapper.findByExamId(examId); int score = 0; for (Question q : questions) { UserAnswer ua = userAnswers.stream() .filter(a -> a.getQuestionId().equals(q.getId())) .findFirst().orElse(null); if (ua == null) continue; Set<String> correct = new HashSet<>(Arrays.asList(q.getAnswer().split(","))); Set<String> user = new HashSet<>(Arrays.asList(ua.getAnswer().split(","))); if (correct.equals(user)) { score += q.getScore(); } } return score; }

参数说明:q.getAnswer()存的是"A,B"这种格式,用逗号分隔;q.getScore()是每题分值。如果题目表里没有分值字段,可以在试卷表里设总分再按题数平均。判分完成后把记录插入record表,返回得分给小程序展示。

4. 避坑与排查:SSM+小程序答题系统最常见的 5 个翻车点

4.1 启动报错 Error 2002: Can't connect to local MySQL server

现象:Tomcat 启动时控制台抛出Error 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'。原因:MySQL 服务没启动,或者 JDBC URL 里写的是 socket 连接而不是 TCP。解决:先确认 MySQL 服务在运行(Linux 下systemctl status mysql,Windows 下看服务列表),然后把 URL 改成jdbc:mysql://127.0.0.1:3306/库名,强制走 TCP。如果还不行,检查my.cnf里bind-address是不是只绑了127.0.0.1,本地开发没问题,远程连接才需要改。

4.2 小程序请求返回 404 但浏览器能访问

现象:在浏览器里直接输http://localhost:8080/answer/user/login能通,小程序里请求同一个地址报 404。原因:小程序开发工具默认走的是https校验,且localhost在真机调试时指向手机自己。解决:开发阶段在开发者工具“详情-本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”;真机调试时把 BASE_URL 换成电脑的局域网 IP,比如http://192.168.1.100:8080/answer,并确保手机和电脑在同一 WiFi。

4.3 MyBatis 查询返回字段为 null

现象:数据库里明明有数据,MyBatis 查出来对象属性全是 null。原因:表字段名是user_name下划线风格,实体类属性是userName驼峰风格,没开自动映射。解决:在 MyBatis 配置文件里加<setting name="mapUnderscoreToCamelCase" value="true"/>,或者在 SQL 里用AS起别名。前者一劳永逸,后者适合个别字段特殊处理。

4.4 答题记录重复插入

现象:用户点一次提交,数据库里出现两条相同记录。原因:小程序端按钮没做防抖,或者网络慢时用户连点两次。解决:前端在提交时把按钮设为disabled,请求返回后再恢复;后端在record表上加唯一索引(user_id, exam_id),重复插入直接报错,Service 层捕获后返回“请勿重复提交”。

4.5 时间字段差 8 小时

现象:答题记录里的提交时间比实际时间早 8 小时。原因:JDBC URL 没设serverTimezone,或者设成了UTC。解决:URL 里加serverTimezone=Asia/Shanghai,同时检查 MySQL 全局时区SELECT @@global.time_zone;,如果是SYSTEM且系统时区是 UTC,就改成+08:00。另外 Java 端用new Date()插入时,确保数据库字段类型是datetime而不是timestamp,后者会自动转换时区。

5. 进阶技巧:用 POI 导出答题成绩单和论文数据整理

5.1 用 Java POI 生成答题成绩 Excel

答辩时老师经常要求“把答题记录导出成 Excel 看看”。用 Apache POI 可以在后端生成.xlsx文件,小程序端通过wx.downloadFile下载。核心代码是创建XSSFWorkbook,建 Sheet,写表头,遍历记录写行。

// ExportUtil.java 导出成绩单 public static void exportRecords(List<Record> records, OutputStream out) throws IOException { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("答题记录"); String[] headers = {"用户名", "试卷", "得分", "提交时间"}; XSSFRow headerRow = sheet.createRow(0); for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); } int rowNum = 1; for (Record r : records) { XSSFRow row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(r.getUserName()); row.createCell(1).setCellValue(r.getExamName()); row.createCell(2).setCellValue(r.getScore()); row.createCell(3).setCellValue(r.getSubmitTime().toString()); } workbook.write(out); workbook.close(); }

参数说明:XSSFWorkbook对应.xlsx格式,HSSFWorkbook对应.xls,前者支持更大数据量。out可以是HttpServletResponse.getOutputStream(),直接推给浏览器下载。注意 POI 的依赖要加poi-ooxml,只加poi会报NoClassDefFoundError。

5.2 论文里的系统测试数据怎么整理

论文的“系统测试”章节需要截图和表格。截图用微信开发者工具的“截图”功能,表格用 Word 或 Excel 整理。测试用例至少覆盖:正常登录、错误密码登录、拉取题目、提交答案、重复提交、超时未提交。每个用例写清输入、预期输出、实际输出。如果老师要求性能数据,可以用 JMeter 对/question/list接口压测,记录响应时间和吞吐量,但毕设演示环境不用太较真,50 并发以内不报错即可。

5.3 一个我踩过的坑:别在答辩前一天改数据库密码

最后说个血泪经验。我曾经在答辩前一天把本地 MySQL 密码从空改成复杂密码,结果忘了同步改spring-dao.xml里的password,第二天演示时登录接口直接 500。后来养成的习惯是:任何配置改动都记在一个CHANGELOG.md里,改完立刻重启 Tomcat 跑一遍登录和答题流程。另外,压缩包里的论文模板不要直接照抄,查重率会很高,用自己的话把 SSM 流程和小程序请求封装重新写一遍,反而更踏实。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询