资讯动态

Spring Boot 在线问卷系统源码深度拆解:动态表单与统计聚合实战

发布时间:2026/10/23 3:10:39 来源:尧图企业网站定制
简介这是一套基于Spring Boot的在线问卷调查系统完整源码项目名为questionnaire-master面向具备Java与Spring基础、希望以实战方式掌握Web全栈开发的学习者与开发者。系统覆盖用户登录注册与权限控制、问卷模板创建编辑、问卷发布与社交网络分享、结果统计与图表展示、个人中心等核心模块并涉及Spring Security、Spring Data JPA、Spring MVC、RESTful API设计及MySQL数据库表结构设计等知识点可作为课程设计、毕业设计或技术练手的参考案例。资源包共294个文件以100个java源码为主体辅以26个js、26个html、8个css等前端页面与脚本另有4个sql建表脚本、6个properties配置、dockerfile与yml部署文件及若干图片素材压缩包约37.17MB目录结构清晰便于按模块阅读与二次开发。目前已有269人学习下载适合通过源码理解在线问卷系统从后端接口到前端交互的完整实现流程。1. 从一份问卷系统源码说起为什么 Spring Boot 项目值得反复拆很多做后端的朋友拿到一份「基于 Spring Boot 的在线问卷调查系统源码」时第一反应是打开 IDEA 跑起来看看效果然后就没有然后了。我见过太多人把这类项目当成练手 Demo跑通登录、建个问卷、提交一次答案就丢进硬盘吃灰。但真正有价值的做法是把它当成一个完整的业务系统来拆——问卷系统看起来简单实际上覆盖了权限、动态表单、统计聚合、并发提交这几个后端高频场景麻雀虽小五脏俱全。这份源码适合三类人一是刚学完 Spring Boot 基础、想找一个完整项目练手的开发者二是需要快速搭一套问卷/表单收集工具的后端工程师三是准备面试、想拿一个能讲清楚业务链路的项目当谈资的人。它解决的核心问题是把「创建问卷 → 发布 → 用户填写 → 数据回收 → 统计分析」这条链路用一套可运行的代码落地而不是停留在教程里的增删改查。2. 拆开看架构分层、依赖与动态表单的选型逻辑2.1 先搞清楚项目怎么分层拿到源码第一步不是跑是看目录结构。一个规范的 Spring Boot 问卷系统通常按经典三层走controller接请求、service写业务、mapper或repository碰数据库。但问卷系统有个特殊点——它的「题目」和「选项」是动态的不是固定表结构能解决的所以实体设计上会比普通 CRUD 多一层。我一般会先找这几个关键包# 典型目录结构以 Maven 项目为例 src/main/java/com/example/survey/ ├── controller/ # 接口层问卷的增删改查、提交、统计 ├── service/ # 业务层问卷发布逻辑、答案校验、统计聚合 ├── mapper/ # 持久层MyBatis 或 JPA 接口 ├── entity/ # 实体Survey、Question、Option、Answer、User ├── dto/ # 传输对象提交答案的请求体、统计返回体 └── config/ # 配置拦截器、跨域、MyBatis 配置看目录就能判断技术栈有mapper包基本是 MyBatis有repository包大概率是 JPA。这一步决定了你后面改代码的写法别急着动手。2.2 动态表单的实体设计是核心问卷系统最难的地方不在接口在数据模型。一份问卷有多个题目每个题目有多个选项用户提交的答案要能对应回题目和选项。常见做法是四张核心表表名作用关键字段survey问卷主表id、title、status、create_timequestion题目表id、survey_id、type、content、sortoption选项表id、question_id、content、sortanswer答案表id、survey_id、question_id、option_id、user_id这里有个选型细节question.type字段决定题目是单选、多选还是填空。单选多选走option表关联填空则直接把文本存进answer的扩展字段。我见过有的实现把填空也塞进 option 表结果统计时一团乱这是设计阶段就该避开的坑。2.3 跑起来之前先确认三件事在application.yml里重点看三个配置数据库连接、端口、以及有没有用 Redis 做缓存或 session。问卷系统如果带登录session 存储方式直接影响你能不能多端调试。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/survey?useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver # 如果项目用了 Redis 存 session这里会有 redis 配置 redis: host: localhost port: 6379参数说明serverTimezone必须设否则 MySQL 8 以上版本时间字段会报错useSSLfalse本地调试用生产环境要开。数据库要先手动建好survey库导入源码里的schema.sql或init.sql别指望框架自动建表——大部分这类项目没配ddl-auto。3. 把项目跑起来建库、导数据、启动与接口验证3.1 数据库初始化别偷懒源码包里通常有个sql文件夹里面是建表语句和初始数据。我一般用命令行导入比图形化工具稳# 登录 MySQL 并创建数据库 mysql -u root -p -e CREATE DATABASE survey DEFAULT CHARACTER SET utf8mb4; # 导入建表脚本假设文件在项目根目录的 sql 文件夹 mysql -u root -p survey sql/schema.sql # 导入初始数据如果有 mysql -u root -p survey sql/data.sql逻辑说明utf8mb4是为了支持 emoji问卷里用户填表情很常见用utf8会存不进去。导入顺序不能反先建表再插数据。如果脚本里用了DROP TABLE IF EXISTS重复执行不会报错但会清空数据生产环境慎用。3.2 启动项目与常见启动失败用 Maven 启动# 在项目根目录执行 mvn clean spring-boot:run # 或者打包后运行 mvn clean package -DskipTests java -jar target/survey-system-0.0.1-SNAPSHOT.jar启动失败最常见的原因是端口占用和数据库连不上。端口占用改server.port数据库连不上先看url里的库名和账号密码再看 MySQL 服务有没有起。如果报Table survey.xxx doesnt exist说明建表脚本没导成功回去检查。3.3 用接口验证核心链路项目起来后别急着开浏览器先用 curl 或 Postman 把核心接口过一遍。典型接口有这几个# 1. 创建问卷 curl -X POST http://localhost:8080/api/survey \ -H Content-Type: application/json \ -d {title:测试问卷,questions:[{type:1,content:你常用什么语言?,options:[Java,Python,Go]}]} # 2. 获取问卷详情假设返回的 id 是 1 curl http://localhost:8080/api/survey/1 # 3. 提交答案 curl -X POST http://localhost:8080/api/answer \ -H Content-Type: application/json \ -d {surveyId:1,answers:[{questionId:1,optionId:1}]} # 4. 查看统计 curl http://localhost:8080/api/survey/1/statistics参数说明type:1代表单选optionId对应选项表的主键。提交答案时questionId和optionId必须成对出现缺一个后端校验就会拦。统计接口返回的通常是每个选项的计数如果返回空先确认answer表里有没有数据。提示如果接口返回 401 或 403说明项目配了权限拦截先找登录接口拿 token再在请求头加Authorization。4. 避坑排查这份源码最容易翻车的五个地方4.1 提交答案报「题目不存在」现象调用提交接口时返回题目校验失败但问卷详情里明明有这道题。 原因提交的questionId和问卷实际关联的题目 id 对不上常见于前端传了数组下标而不是数据库主键。 解决先调问卷详情接口把返回的questionId原样传给提交接口别自己拼。4.2 统计结果全是零现象答案表里有数据但统计接口返回的每个选项计数都是 0。 原因统计 SQL 的关联条件写错了常见是answer.option_id和option.id没对上或者survey_id过滤条件漏了。 解决打开 mapper 里对应的统计 SQL先手动在数据库执行一遍确认能查出数再回来看代码。4.3 中文乱码现象问卷标题或选项存进数据库变成问号。 原因数据库字符集不是utf8mb4或者 JDBC url 没加字符集参数。 解决建库时指定utf8mb4url 里加characterEncodingutf8两边都要改。4.4 多选答案只存了最后一个现象用户选了三个选项数据库里只有一条记录。 原因多选提交时前端传了数组后端只取了第一个元素或者循环插入时事务没提交。 解决检查 service 层对多选的处理逻辑确认是遍历插入而不是取[0]并确认方法上有Transactional。4.5 启动报 Redis 连接失败现象项目起不来日志里一堆 Redis 连接异常。 原因源码里配了 Redis 但本地没装或者配置的 host 不对。 解决要么本地起一个 Redis要么把 Redis 相关配置和依赖暂时注释掉先跑通主流程。5. 二次开发技巧把问卷系统改成你自己的工具5.1 加一种新题型评分题原项目只有单选、多选、填空想加个 1-5 分的评分题改动其实很小。核心是在question.type里加一个枚举值比如4代表评分然后在前端渲染和后端校验里各加一个分支。// 在题目类型枚举里加一项 public enum QuestionType { SINGLE(1), MULTI(2), TEXT(3), RATING(4); private final int code; QuestionType(int code) { this.code code; } public int getCode() { return code; } } // service 层校验时放行评分题 if (type QuestionType.RATING.getCode()) { // 评分题答案直接存数值不关联 option 表 answer.setScore(request.getScore()); }逻辑说明评分题不需要option表答案直接存分数。参数上要注意分数范围校验别让用户传个 100 分进来。这个改动涉及实体、service、mapper 三处改完记得同步更新统计逻辑——评分题统计的是平均分不是计数。5.2 用拦截器统一处理问卷状态问卷有草稿、已发布、已关闭三种状态如果每个接口都写一遍状态判断代码会很脏。我一般加一个拦截器在进入 controller 前统一校验。Component public class SurveyStatusInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String uri request.getRequestURI(); // 只拦截提交答案的接口 if (uri.contains(/api/answer)) { Long surveyId Long.parseLong(request.getParameter(surveyId)); Survey survey surveyService.getById(surveyId); if (survey.getStatus() ! 1) { // 1 代表已发布 response.setStatus(403); return false; } } return true; } }参数说明status字段的取值要和数据库里定义的一致别一边用 0/1 一边用字符串。拦截器注册在WebMvcConfig里注意放行登录和问卷详情接口否则用户连问卷都看不到。5.3 验证改动是否生效的笨办法改完代码别只看编译通过我习惯用「三步验证」第一步重启项目看日志有没有报错第二步用 curl 把改动的接口重新打一遍看返回结构对不对第三步直接查数据库确认数据真的落库了。这三步走完基本不会出现「接口通了但数据没存」的玄学问题。从那以后我每次拆这类源码都强制自己先跑通核心链路再动代码改一处验一处绝不一次性改五个文件再启动。希望这份拆解能帮到你拿到源码后少走点弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑