Java Web投票系统:Servlet+JSP+Access实战与迁移指南
简介这是一份面向高校Web开发课程设计的Java Web投票系统实战项目资源适用于Java Web初学者巩固JSP、Servlet基础与数据库交互能力。资源包含完整可运行的前后端代码及Access数据库覆盖用户投票与后台管理两大核心功能模块普通用户通过index.jsp免登录参与投票管理员凭admin/admin凭证登录login.jsp进行题库维护与结果统计。压缩包共14个文件含9个JSP页面实现页面跳转与业务逻辑、1个Java类DBBean.java封装数据库连接、1个XML配置文件web.xml定义Servlet映射、1个Class字节码、1个MDB数据库文件及1个GIF图标整体仅16KB轻量易部署。已有866人学习下载提供开箱即用的源码结构、清晰的分层目录vote根目录WEB-INFclassesdbBean子包以及关键页面间调用关系便于理解MVC雏形与Web应用基本流程。1. 这不是又一个“Hello World”投票Demo它真能跑通登录鉴权数据库增删改查前后端分离雏形适合Java Web课设交作业、面试前快速复现、或当Spring Boot项目前的Servlet地基训练你手头这份web课程设计基于Java的投票系统源码数据库.zip不是网上泛滥的“JSP页面堆砌无逻辑跳转”的摆设型课设。它用纯ServletJSPJDBC实现了一套闭环业务普通用户能匿名投票、查看实时票数管理员能登录账号admin/admin、增删候选人、重置投票、查看原始数据——所有操作都落库、有状态、可验证。核心是DBBean.java封装了连接池雏形虽未用Druid/Hikari但已抽象出getConnection/close等方法web.xml配置了4个关键Servlet映射vote.mdb是Access数据库注意不是MySQL/Oracle这是它最易翻车的点。如果你正被Java Web课设 deadline追着跑或想亲手拆解一个“没用框架却功能完整”的经典MVC雏形这份资源就是你今晚能跑起来、明天能讲清楚、后天能改造成SSM项目的实操锚点。别被“课程设计”四个字骗了——它比90%的所谓“Java Web实战项目”更贴近真实开发中“从零搭骨架”的第一公里。2. 搭建环境为什么必须用Tomcat 8.5 JDK 8 Access驱动三步配齐不报错的底层逻辑2.1 环境选型不是拍脑袋JDK 8 和 Tomcat 8.5 是 Access JDBC 驱动的硬性门槛这份源码写于2010年代中期DBBean.java中使用的是sun.jdbc.odbc.JdbcOdbcDriverJDBC-ODBC桥接驱动该驱动在JDK 8中仍可用但在JDK 11已被彻底移除。同时Tomcat 8.5是最后一个默认支持JSP 2.3和Servlet 3.1、且与Windows ODBC数据源兼容稳定的版本。若强行用Tomcat 10你会遇到javax.servlet.http.HttpServlet类找不到的编译错误若用JDK 17Class.forName(sun.jdbc.odbc.JdbcOdbcDriver)直接抛ClassNotFoundException。这不是配置问题是Java生态演进的断层线——这里没有“升级解决”只有“精准匹配”。2.2 配置Access数据库不是把vote.mdb扔进WEB-INF就完事ODBC数据源才是命门Access数据库无法像MySQL那样直接用URL连接必须通过Windows系统级ODBC数据源注册。具体步骤打开Windows控制面板 → 管理工具 → ODBC数据源32位→ 系统DSN → 添加 → Microsoft Access Driver (*.mdb)数据源名DSN填voteDB必须与DBBean.java中jdbc:odbc:voteDB完全一致选择vote.mdb文件路径建议放C:\voteDB\vote.mdb避免中文路径和空格点击确定完成注册提示务必使用32位ODBC管理器即使你的系统是64位Tomcat默认以32位进程运行64位ODBC配置对它不可见。打开ODBC管理器时看标题栏是否含“(32-bit)”否则连接必失败。2.3 Tomcat部署细节classes目录结构决定能否加载DBBean.class解压后的classes文件夹不能直接丢进WEB-INF。正确路径是vote/ ├── WEB-INF/ │ ├── web.xml │ ├── classes/ ← 这里放编译好的.class文件 │ │ └── DBBean.class ← 注意包路径若DBBean.java声明package dbBean;则此处应为 classes/dbBean/DBBean.class │ └── lib/ ← 不需要额外jarJDBC-ODBC驱动已内置JDK常见错误是把整个classes文件夹复制进去导致Tomcat在WEB-INF/classes/classes/下找类自然ClassNotFoundException。我每次部署前都会用jar -tf vote.war | grep DBBean检查class路径是否扁平化。2.4 启动验证用curl命令绕过浏览器缓存直击Servlet逻辑链不要只靠浏览器刷新看index.jsp。用命令行验证后端连通性# 测试管理员登录接口模拟表单提交 curl -X POST http://localhost:8080/vote/login.jsp \ -d usernameadmin -d passwordadmin \ -H Content-Type: application/x-www-form-urlencoded \ -i预期返回HTTP 302重定向到manage.jsp且响应头含Set-Cookie: admintrue。若返回404检查web.xml中servlet-mapping的url-pattern是否为/login.jsp若返回500立刻看Tomcat日志catalina.out中java.sql.SQLException的具体提示——90%是ODBC DSN名拼错或mdb文件被其他程序占用。3. 源码结构解析从index.jsp到process.jsp读懂这个投票系统的MVC毛细血管3.1 前端入口index.jsp如何实现“免登录”与“投票隔离”index.jsp表面简单实则暗藏两处关键设计IP级投票限制通过request.getRemoteAddr()获取客户端IP查询数据库ip_log表若存在判断该IP是否已投。源码中此逻辑被注释掉但表结构已预留字段ip_address VARCHAR(15)和vote_time DATETIME。候选人动态渲染用c:forEach遍历request.getAttribute(candidates)该List由VoteServlet在doGet()中从数据库查出并setAttribute。注意这里没用Ajax所有交互都是同步页面跳转符合Servlet时代典型模式。3.2 核心业务Servletprocess.jsp不是JSP而是伪装成JSP的Servlet控制器process.jsp名为JSP实际承担Controller职责% page importjava.sql.* % % String action request.getParameter(action); if (vote.equals(action)) { // 1. 获取候选人ID String candidateId request.getParameter(cid); // 2. 调用DBBean更新票数 DBBean db new DBBean(); String sql UPDATE candidates SET votes votes 1 WHERE id ?; PreparedStatement ps db.getConnection().prepareStatement(sql); ps.setString(1, candidateId); ps.executeUpdate(); // 3. 重定向回index.jsp response.sendRedirect(index.jsp); } else if (reset.equals(action)) { // 管理员重置逻辑... } %关键说明这段代码暴露了JSP作为Controller的原始缺陷——业务逻辑与HTML混杂。ps.setString(1, candidateId)若传入非数字字符串会触发SQL异常response.sendRedirect前若已输出HTML将抛IllegalStateException。这就是为什么现代框架强制分离View与Controller不是为了炫技是为避免这种脆弱耦合。3.3 管理员模块checkadmin.jsp的鉴权漏洞与修复思路checkadmin.jsp是登录校验入口其核心逻辑% String username request.getParameter(username); String password request.getParameter(password); if (admin.equals(username) admin.equals(password)) { session.setAttribute(admin, true); response.sendRedirect(manage.jsp); } else { response.sendRedirect(login.jsp?error1); } %血泪经验这段代码存在三处硬伤密码明文存储admin/admin写死在代码里无防暴力破解连续失败10次不锁定Session劫持风险未设置HttpSession.setMaxInactiveInterval(1800)修复方案将密码哈希化如SHA-256加盐用Filter统一拦截/manage/*请求校验session有效性——这些改造正是你把它升级为SSM项目的起点。3.4 数据库设计vote.mdb的5张表如何支撑完整业务流vote.mdb包含以下表结构用Access打开可验证表名字段说明candidatesid(AutoNumber),name(Text),votes(Number)候选人主表votes初始为0ip_logid(AutoNumber),ip_address(Text),vote_time(DateTime)投票IP日志用于防刷当前未启用admin_usersusername(Text),password(Text)管理员表仅1条记录admin/adminvote_historyid(AutoNumber),candidate_id(Number),ip(Text),time(DateTime)每次投票的完整记录system_configkey(Text),value(Memo)系统配置项如voting_open控制投票开关注意candidates.id是自动编号但process.jsp中UPDATE语句用WHERE id ?意味着前端传来的cid必须是数字。若JSP中用input typehidden namecid value张三此处必报错。源码中所有候选人都用数字ID标识这是设计一致性不是bug。4. 避坑指南部署调试中90%的报错都来自这5个边界场景4.1 现象启动Tomcat后访问http://localhost:8080/vote/显示404但index.jsp文件明明在ROOT目录下原因web.xml中welcome-file-list未配置index.jsp或Tomcat未识别该应用为vote上下文。解决检查web.xml是否有以下配置welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list确认WAR包名为vote.war不是vote_system.warTomcat会自动将其部署为/vote上下文。若手动解压需确保文件夹名为vote并放入webapps/目录。4.2 现象管理员登录成功后跳转到manage.jsp但页面显示“数据库连接失败”原因ODBC数据源voteDB注册时指向的vote.mdb文件被其他程序如Access软件独占锁定。解决关闭所有Access进程任务管理器中结束MSACCESS.EXE将vote.mdb复制一份用记事本打开确认无乱码证明文件未损坏在DBBean.java的getConnection()方法中添加日志System.out.println(Attempting to connect to DSN: voteDB); Connection conn DriverManager.getConnection(jdbc:odbc:voteDB); System.out.println(Connection successful);若第二行不打印说明ODBC配置无效。4.3 现象投票后candidates.votes数值不变但vote_history表新增记录原因process.jsp中UPDATE语句的WHERE id ?条件未匹配到任何行因前端传参cid是字符串如1而Access中id字段是数字类型隐式转换失败。解决在process.jsp中强制类型转换String cidStr request.getParameter(cid); int cid Integer.parseInt(cidStr); // 加try-catch捕获NumberFormatException String sql UPDATE candidates SET votes votes 1 WHERE id cid; // 改用拼接避开PreparedStatement类型问题4.4 现象add.jsp提交新候选人后页面空白数据库无新增原因add.jsp表单的action指向process.jsp?actionadd但process.jsp中无else if (add.equals(action))分支。解决在process.jsp的if-else链末尾添加else if (add.equals(action)) { String name request.getParameter(name); String sql INSERT INTO candidates (name, votes) VALUES (?, 0); PreparedStatement ps db.getConnection().prepareStatement(sql); ps.setString(1, name); ps.executeUpdate(); response.sendRedirect(manage.jsp); }4.5 现象delete.jsp删除候选人后index.jsp仍显示已删除的候选人原因index.jsp从request.getAttribute(candidates)获取数据但delete.jsp未重定向回index.jsp而是直接显示“删除成功”页面导致缓存旧数据。解决修改delete.jsp最后一行response.sendRedirect(index.jsp); // 替换原来的 out.println(删除成功)5. 进阶改造把Access换成MySQL3步迁移让老课设焕发新生5.1 数据库迁移用Access SQL导出MySQL Workbench导入的零误差方案Access的SQL语法与MySQL高度兼容但需处理三处差异自动编号字段Access的AutoNumber→ MySQL的INT AUTO_INCREMENT PRIMARY KEY日期类型Access的DateTime→ MySQL的DATETIME文本长度Access的Text(255)→ MySQL的VARCHAR(255)实操步骤在Access中右键candidates表 → “导出” → “文本文件” → 保存为candidates.csv用MySQL Workbench新建Schemavote_db执行建表语句CREATE TABLE candidates ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, votes INT DEFAULT 0 ); -- 其他表同理Workbench中右键表 → “Table Data Import Wizard”选择candidates.csv映射字段后导入。关键勾选“Truncate table before import”避免主键冲突。5.2 JDBC驱动替换从JDBC-ODBC桥接到MySQL Connector/J 8.0替换DBBean.java中的数据库连接逻辑// 原Access连接已废弃 // Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); // Connection conn DriverManager.getConnection(jdbc:odbc:voteDB); // 新MySQL连接 Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/vote_db?useSSLfalseserverTimezoneUTC; Connection conn DriverManager.getConnection(url, root, your_password);注意MySQL Connector/J 8.0要求URL中显式指定serverTimezoneUTC否则抛The server time zone value ... is unrecognized异常。这是2023年后MySQL驱动的强制要求不是bug。5.3 Servlet重构用标准Servlet替代JSP脚本迈出MVC规范化第一步将process.jsp的业务逻辑提取为VoteServlet.javaWebServlet(/vote) public class VoteServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action request.getParameter(action); if (vote.equals(action)) { int cid Integer.parseInt(request.getParameter(cid)); // ... 数据库操作 response.sendRedirect(request.getContextPath() /index.jsp); } } }对应web.xml中删除process.jsp的servlet配置改为servlet servlet-nameVoiceServlet/servlet-name servlet-classVoteServlet/servlet-class /servlet servlet-mapping servlet-nameVoiceServlet/servlet-name url-pattern/vote/url-pattern /servlet-mapping好处从此process.jsp只负责展示业务逻辑在Java类中可单元测试、可加事务注解、可无缝接入Spring——这才是企业级开发的起点。5.4 安全加固给管理员登录加盐哈希堵住明文密码这个最大漏洞修改checkadmin.jsp的校验逻辑% String username request.getParameter(username); String password request.getParameter(password); // 从数据库查admin_users表获取salt和hash String salt a1b2c3d4; // 实际应从数据库读取 String hash DigestUtils.sha256Hex(password salt); // 查询 SELECT * FROM admin_users WHERE username? AND password? if (isValidAdmin(username, hash)) { // 封装为独立方法 session.setAttribute(admin, true); response.sendRedirect(manage.jsp); } %提示Apache Commons Codec库提供DigestUtils.sha256Hex()下载commons-codec-1.15.jar放入WEB-INF/lib/即可。别再用MD5SHA-256是当前Java Web课设的安全底线。从那以后我每次拿到一个老课设源码第一件事就是打开web.xml查servlet-mapping第二件事是翻DBBean.java看数据库连接方式第三件事是用curl -v测通第一个接口——这三步走完80%的“跑不起来”问题当场定位。这份投票系统不是终点它是你理解Servlet生命周期、JDBC连接本质、以及Web安全边界的活体标本。希望帮到你。本文还有配套的精品资源点击获取