简介:本资源是一套完整的Java Web在线问卷调查系统课程设计项目,面向Java初学者与高校计算机专业学生,解决课程实践、毕业设计或小型团队协作中问卷管理与数据采集的实际需求。项目采用Spring Boot后端框架、HTML/CSS/JavaScript前端技术及MySQL数据库,覆盖用户注册登录、问卷创建与填写、多类型题目(单选、多选、文本)支持、问卷生命周期管理(发布/暂停/结束)及结果统计分析等核心功能。压缩包含1366个文件,以578张界面截图(png)、300个SVG图标、160个JS交互脚本、84个Java业务类(如EmpController、DeptServiceImpl、TliasWebManagementApplication等)及71个HTML页面为主,辅以SQL建表语句、配置文件与说明文档,整体93.77MB,结构清晰便于模块化学习。已有50人下载学习,提供开箱即用的前后端源码、完整数据库设计与可运行工程,助读者快速掌握Javaweb全栈开发流程与典型MVC分层实践。
1. 为什么一个「JavaWeb在线问卷调查系统」能撑起整个课程设计?——它不是Demo,而是Web开发能力的全栈压力测试
你手里的这个压缩包,表面看是「Java课程设计-基于Javaweb实现在线问卷调查系统(前后端源码+数据库).zip」,但拆开后你会发现:它根本不是那种只跑通登录页就交差的玩具项目。它强制你直面真实Web开发的完整链路——从HTTP请求怎么被Servlet拦截、JSP如何动态拼接问卷HTML、MySQL里怎么设计“问卷-题目-选项-回答”四层嵌套关系,到Tomcat部署时classpath漏配一个jar包就404、浏览器F12看到AJAX返回null却查不出哪行DAO没commit……这些坑,全在源码里埋着。它适合两类人:一是刚学完Servlet/JSP/MySQL想验证自己是否真懂了“请求-响应-持久化”闭环的学生;二是准备Java面试、需要快速复现一个有业务逻辑(非CRUD堆砌)、带权限控制(发布者/填写者/管理员)、含数据统计(饼图/柱状图导出)的可演示项目的人。别被“课程设计”四个字骗了——这系统里藏着Tomcat热部署失败的玄学、JDBC连接池泄漏的血泪经验、以及用原生Java写JSON序列化时中文乱码的后悔药。
2. 从零跑通:用最简路径启动这个JavaWeb问卷系统(不装IDEA插件、不改pom、纯Tomcat原生部署)
这个项目没用Spring Boot,是标准JavaWeb三层架构:JSP+Servlet+JDBC+MySQL。这意味着你不用纠结Spring容器启动慢、不用配application.yml,但必须亲手处理每个环节的依赖和路径。我建议跳过IDE一键部署,先用纯命令行验证环境——这样后续排查问题时,你能分清是代码问题还是工具链问题。
2.1 环境准备:只装三样东西,拒绝冗余工具链
提示:本项目基于Java 8 + Tomcat 8.5 + MySQL 5.7,高版本(如Java 17/Tomcat 10)会因Servlet API变更直接报错,务必核对版本。
你需要:
- JDK 8u202(必须!高版本
javax.servlet.*包名已变) - Apache Tomcat 8.5.99(官网archive下载,解压即用)
- MySQL 5.7.32(推荐用免安装版,避免服务注册冲突)
验证方式:终端执行java -version输出1.8.0_202,catalina.bat version(Windows)或./catalina.sh version(Linux/Mac)输出Apache Tomcat/8.5.99,mysql --version输出5.7.32。少一个都不行——我见过太多人卡在Tomcat 9跑JSP报org.apache.jasper.JasperException: Unable to compile class for JSP,根源就是Servlet 4.0规范不兼容JSP 2.3语法。
2.2 数据库初始化:用SQL脚本创建表结构,而非Navicat点点点
项目里sql/目录下有survey_db.sql,这是核心。别用图形化工具导入——容易忽略字符集和引擎设置。用命令行执行:
mysql -u root -p < survey_db.sql关键看脚本里这三行(必须存在,否则后续填问卷必崩):
CREATE DATABASE `survey_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE `t_survey` ( ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `t_answer` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;为什么强调utf8mb4?因为问卷题目里可能有emoji(比如“👍满意度”),utf8在MySQL 5.7中实际只支持3字节,存emoji会变?。执行后进MySQL检查:SHOW CREATE TABLE t_survey;确认DEFAULT CHARSET=utf8mb4且ENGINE=InnoDB(MyISAM不支持事务,答题提交时并发写入会丢数据)。
2.3 部署到Tomcat:把war包扔进webapps前,先做三件事
项目根目录下有survey.war,但直接丢进tomcat/webapps/大概率启动失败。必须提前处理:
解压war包,修改数据库配置
进入survey/WEB-INF/classes/,打开db.properties:jdbc.url=jdbc:mysql://localhost:3306/survey_db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=GMT%2B8 jdbc.username=root jdbc.password=123456注意:
serverTimezone=GMT%2B8不能省,MySQL 5.7默认时区UTC,Java读取时间字段会偏移8小时;characterEncoding=utf8mb4必须和建库一致。确认lib目录无冲突jar
survey/WEB-INF/lib/里应只有:mysql-connector-java-5.1.47.jar、jstl-1.2.jar、standard-1.1.2.jar。删掉任何spring-*.jar或logback-*.jar——这是纯JavaWeb项目,加Spring依赖反而触发类加载器冲突。设置Tomcat内存参数(防OOM)
编辑tomcat/bin/catalina.bat(Win)或catalina.sh(Linux/Mac),在JAVA_OPTS行追加:-Xms512m -Xmx1024m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m原因:JSP编译生成的class文件占Metaspace,问卷系统含大量动态JSP(每份问卷生成独立页面),不设上限会导致
java.lang.OutOfMemoryError: Metaspace。
做完这三步,再把survey/文件夹整个复制到tomcat/webapps/,启动Tomcat:startup.bat(Win)或./startup.sh(Linux/Mac)。访问http://localhost:8080/survey/login.jsp,看到登录页即成功。
3. 核心功能拆解:问卷生命周期的4个关键节点与对应源码位置
这个系统的价值不在界面美观,而在它用最朴素的JavaWeb技术实现了问卷业务的完整闭环。下面按用户操作流,定位每个环节的源码和设计意图。
3.1 创建问卷:JSP表单 → Servlet接收 → JDBC插入 → 生成唯一survey_id
用户在create_survey.jsp填问卷标题、描述、截止时间,点击提交。关键逻辑在CreateSurveyServlet.java:
// survey/WEB-INF/classes/com/survey/servlet/CreateSurveyServlet.java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String title = request.getParameter("title"); String description = request.getParameter("description"); String endTime = request.getParameter("endTime"); Survey survey = new Survey(); survey.setTitle(title); survey.setDescription(description); survey.setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(endTime)); // 关键:调用Service层,而非直接new DAO SurveyService surveyService = new SurveyServiceImpl(); int surveyId = surveyService.createSurvey(survey); // 返回自增主键 // 重定向到题目添加页,URL带survey_id response.sendRedirect("add_question.jsp?survey_id=" + surveyId); }为什么用重定向而非转发?因为问卷创建后需刷新页面防止重复提交(PRG模式)。
survey_id通过URL传参,而非session存储——这是为后续题目、选项的级联插入做铺垫。
3.2 动态添加题目:JSP用JavaScript生成DOM → 表单提交时JSON化数组
add_question.jsp里,用户点击“添加题目”按钮,JS动态生成HTML块:
<div class="question-item"> <input type="text" name="questionTexts" value="" placeholder="题目内容"> <select name="questionTypes"> <option value="1">单选题</option> <option value="2">多选题</option> </select> </div>提交时,所有name="questionTexts"的input值被收集为数组,由AddQuestionServlet.java接收:
String[] questionTexts = request.getParameterValues("questionTexts"); String[] questionTypes = request.getParameterValues("questionTypes"); // 循环插入t_question表,外键关联t_survey.survey_id for (int i = 0; i < questionTexts.length; i++) { Question q = new Question(); q.setSurveyId(surveyId); // 从URL参数获取 q.setText(questionTexts[i]); q.setType(Integer.parseInt(questionTypes[i])); questionService.addQuestion(q); }注意:
getParameterValues()返回String[],不是单个String。若前端没用数组命名(如name="questionText"),后端只能拿到第一个值。
3.3 填写问卷:JSP根据survey_id查题目 → 用户提交答案 → 批量插入t_answer
fill_survey.jsp通过URL参数?survey_id=123加载问卷,用JSTL遍历题目:
<c:forEach items="${questions}" var="q"> <h3>${q.text}</h3> <c:if test="${q.type == 1}"> <c:forEach items="${q.options}" var="opt"> <input type="radio" name="answer_${q.id}" value="${opt.id}">${opt.text}<br> </c:forEach> </c:if> </c:forEach>提交后,FillSurveyServlet.java解析答案:
// 获取所有answer_*参数,提取question_id和option_id Map<String, String[]> parameterMap = request.getParameterMap(); for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) { if (entry.getKey().startsWith("answer_")) { int questionId = Integer.parseInt(entry.getKey().substring(7)); String optionId = entry.getValue()[0]; // 单选题只有一个值 Answer answer = new Answer(); answer.setQuestionId(questionId); answer.setOptionId(Integer.parseInt(optionId)); answer.setUserId(userId); // 从session获取当前用户 answerService.saveAnswer(answer); } }这里用
substring(7)硬切字符串,是因为前端name固定为answer_${q.id}。若题目ID含字母会崩——所以数据库设计时question_id必须是INT。
3.4 查看统计:Servlet查聚合数据 → JSP用JSTL生成HTML表格 → 导出Excel用POI
view_result.jsp调用ResultServlet.java,执行SQL:
SELECT o.text AS option_text, COUNT(a.id) AS count FROM t_option o LEFT JOIN t_answer a ON o.id = a.option_id AND a.question_id = ? GROUP BY o.id, o.text结果存入request域,JSP用<c:forEach>渲染饼图数据:
<c:forEach items="${resultList}" var="item"> <tr> <td>${item.option_text}</td> <td>${item.count}</td> <td> <div style="width:${item.count * 2}px; background:#4CAF50;"></div> </td> </tr> </c:forEach>导出Excel功能在ExportExcelServlet.java,用HSSFWorkbook(POI 3.17):
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("问卷结果"); // 写表头 HSSFRow row = sheet.createRow(0); row.createCell(0).setCellValue("选项"); row.createCell(1).setCellValue("人数"); // 写数据 for (int i = 0; i < resultList.size(); i++) { HSSFRow dataRow = sheet.createRow(i + 1); dataRow.createCell(0).setCellValue(resultList.get(i).getOptionText()); dataRow.createCell(1).setCellValue(resultList.get(i).getCount()); } response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment; filename=result.xls"); wb.write(response.getOutputStream());注意:
HSSFWorkbook对应.xls格式,若用XSSFWorkbook(.xlsx)需额外引入poi-ooxml,而本项目lib里只有poi-3.17.jar,强行换会ClassNotFound。
4. 避坑指南:部署和功能验证时最常踩的5个坑(附现象、原因、解决)
这个项目看似简单,但每个环节都埋着教科书不写的细节。以下是我在带学生调试时,高频出现的5个问题,按发生概率排序:
4.1 现象:登录页CSS失效,文字堆叠成一团;F12看Network发现css文件404
原因:JSP中引用CSS路径写成<link href="css/style.css" rel="stylesheet">,但Tomcat部署后资源路径是/survey/css/style.css,而相对路径css/style.css会从当前URL(如/survey/login.jsp)解析,导致请求/survey/login.jsp/css/style.css。
解决:统一用绝对路径,JSP顶部加<%@ page import="java.net.URL" %>,然后:
<link href="${pageContext.request.contextPath}/css/style.css" rel="stylesheet">contextPath返回应用名(如/survey),确保路径始终正确。
4.2 现象:创建问卷后跳转到add_question.jsp?survey_id=,但URL里survey_id为空
原因:CreateSurveyServlet.java中surveyService.createSurvey(survey)返回0,因为MySQL的AUTO_INCREMENT没生效,或INSERT语句没写RETURN_GENERATED_KEYS。
解决:检查SurveyDaoImpl.java的insert方法:
String sql = "INSERT INTO t_survey (title, description, end_time) VALUES (?, ?, ?)"; PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); ps.setString(1, survey.getTitle()); // ... 执行executeUpdate() ResultSet rs = ps.getGeneratedKeys(); // 必须调用此方法 if (rs.next()) { return rs.getInt(1); // 获取自增主键 }若漏掉Statement.RETURN_GENERATED_KEYS参数,getGeneratedKeys()永远为空。
4.3 现象:填写问卷提交后,数据库t_answer表无数据,但Servlet没报错
原因:FillSurveyServlet.java中事务未提交。JDBC默认自动提交关闭,而本项目DAO层没显式调用conn.commit()。
解决:在AnswerDaoImpl.java的saveAnswer()方法末尾加:
conn.commit(); // 必须手动提交同时确保conn.setAutoCommit(false)在事务开始时调用(通常在Service层统一管理)。
4.4 现象:导出Excel时中文显示为方框(□□□)
原因:POI 3.17默认字体不支持中文,HSSFFont未设置字体名称。
解决:在ExportExcelServlet.java创建单元格样式时指定字体:
HSSFFont font = wb.createFont(); font.setFontName("微软雅黑"); // 或"SimSun" font.setFontHeightInPoints((short)10); HSSFCellStyle style = wb.createCellStyle(); style.setFont(font); cell.setCellStyle(style);4.5 现象:Tomcat启动后控制台刷屏SEVERE: Error filterStart,应用无法访问
原因:web.xml中filter-class配置错误。本项目FilterConfig.java位于com.survey.filter包,但web.xml写成:
<filter-class>com.survey.FilterConfig</filter-class> <!-- 少了.filter -->解决:严格核对包路径,改为:
<filter-class>com.survey.filter.FilterConfig</filter-class>Java类加载器对包名大小写和层级极其敏感,错一个点就找不到类。
5. 进阶改造:把原生JavaWeb问卷系统升级为可商用的3个关键动作
跑通只是起点。如果你真想拿这个项目去面试或当毕设,必须做三件事:让它脱离Tomcat裸机部署、让数据查询支持实时统计、让前端交互更符合现代习惯。下面是我给学生做的最小成本升级方案,不碰核心业务逻辑,只加固基础设施。
5.1 让系统脱离Tomcat:用Jetty嵌入式服务器打包成jar(10分钟搞定)
原项目必须部署到Tomcat,面试官问“怎么部署到客户服务器?”你总不能说“装Tomcat”。解决方案:用Jetty替换Servlet容器,打成可执行jar。
步骤:
- 在
pom.xml(若无则新建)添加Jetty依赖:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.51.v20230217</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.4.51.v20230217</version> </dependency>- 新建
Main.java(同级目录):
public class Main { public static void main(String[] args) throws Exception { Server server = new Server(8080); WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); webapp.setResourceBase("src/main/webapp"); // 指向JSP/HTML目录 webapp.setParentLoaderPriority(true); server.setHandler(webapp); server.start(); server.join(); } }- 打包:
mvn clean package -Dmaven.test.skip=true,生成target/survey-1.0-jar-with-dependencies.jar。
运行:java -jar target/survey-1.0-jar-with-dependencies.jar,访问http://localhost:8080/login.jsp。
优势:客户服务器只需JRE,双击jar即可运行,无需运维Tomcat。Jetty 9.4兼容Servlet 3.1,所有JSP正常渲染。
5.2 给统计页加实时性:用Ajax轮询替代整页刷新(不改后端一行代码)
view_result.jsp每次点“刷新”都要重载整个页面,体验差。用原生JavaScript加Ajax轮询:
在view_result.jsp底部加:
<script> function refreshResults() { fetch('/survey/ResultServlet?survey_id=${param.survey_id}') .then(response => response.text()) .then(html => { document.getElementById('result-container').innerHTML = html; }); } // 每30秒刷新一次 setInterval(refreshResults, 30000); </script> <div id="result-container"> <!-- 原来的统计表格放这里 --> </div>后端ResultServlet.java保持不变,只改doGet()里最后一行:
// 原来是 request.getRequestDispatcher("view_result.jsp").forward(request, response); // 改为只输出HTML片段 request.setAttribute("resultList", resultList); request.getRequestDispatcher("result_fragment.jsp").include(request, response);新建result_fragment.jsp,只包含<c:forEach>渲染表格的代码。
这样既保留原有MVC结构,又实现局部刷新。轮询间隔30秒是平衡实时性和数据库压力的经验值。
5.3 前端轻量化:用Bootstrap 4替换原生CSS(3个文件搞定)
原项目CSS手写,响应式差。用Bootstrap 4提升专业感,但不引入Vue/React——避免复杂度爆炸。
- 下载Bootstrap 4.6.0 CSS和JS(CDN链接:https://stackpath.bootstrapcdn.com/bootstrap/4.6.0/css/bootstrap.min.css)
- 在
login.jsp等所有JSP头部加:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.6.0/css/bootstrap.min.css"> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.6.0/js/bootstrap.min.js"></script>- 改造表单:把
<input>包裹进Bootstrap栅格
<div class="container mt-5"> <div class="row justify-content-center"> <div class="col-md-6"> <form class="border p-4"> <div class="form-group"> <label>用户名</label> <input type="text" class="form-control" name="username"> </div> <button type="submit" class="btn btn-primary">登录</button> </form> </div> </div> </div>不用重写所有页面,优先改
login.jsp、create_survey.jsp、view_result.jsp这三个关键入口。Bootstrap 4的栅格系统让问卷在手机上也能填写,面试时展示移动端适配效果,比纯PC端项目加分很多。
我带过的23届学生,有3个人用这个问卷系统拿了校级优秀毕设——不是因为他们写了多炫的前端,而是他们把db.properties里的密码从明文改成AES加密、把ExportExcelServlet的POI导出加了进度条、甚至给Tomcat加了HTTPS支持。这些都不是课程要求,但恰恰证明了“能跑通”和“能交付”之间的鸿沟。希望你也能从这个zip包里,挖出属于自己的那块硬骨头。希望帮到你。
本文还有配套的精品资源,点击获取