ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

高校社团管理系统:Java+JSP+Servlet+MySQL实战指南

高校社团管理系统:Java+JSP+Servlet+MySQL实战指南 简介本资源是一套完整的高校社团管理系统毕业设计级项目源码面向计算机专业本科生及Java Web初学者解决校园社团组织管理数字化难题。系统基于JSPServletMySQL三层架构实现涵盖学生、社长、管理员三类角色支持社团创建审批、活动申请、财务管理、新闻发布等核心业务流程界面简洁、功能完备适合作为课程设计、数据库大作业或毕业设计参考。压缩包共981个文件含63个Java业务逻辑类、45个JSP页面、269个JS交互脚本、277个GIF操作演示图、40个CSS样式文件及1个SQL建库脚本另有MP4操作视频与详细说明文档整体大小56.7MB。目前已有2402人学习下载提供从环境搭建、代码结构解析到关键控制器如FrontController、TeamsController、MoneyMangerController调用链路的完整实践路径助力快速掌握Web开发全流程。1. 高校社团管理系统为什么还在用 JavaJSPServletMySQL不是技术落后而是它真能跑通从课设到毕设再到院系试运行的全链路你打开这个.zip包里面没有 Spring Boot 的自动装配、没有 Vue 的响应式绑定、没有 Docker Compose 的一键启停——但你能在 Windows 10 笔记本上装个 JDK 8 Tomcat 9 MySQL 5.715 分钟内把「社团招新报名」「活动审批流」「成员考勤统计」三个核心模块跑起来。这不是怀旧是高校信息化场景的真实约束机房服务器还是 CentOS 6.5 内存 4G教务处老师只认.war包双击部署辅导员用 IE11 审批流程而学生提交的社团 logo 图片尺寸五花八门。这套组合拳的价值不在于多酷炫而在于它把「数据库事务一致性」「HTTP 请求生命周期控制」「JSP 页面动态渲染边界」这些抽象概念钉死在「一个 Servlet 处理报名表单提交 → 校验学号唯一性 → 插入 member 表 关联社团表 记录操作日志」这一条可调试、可断点、可截图交作业的执行路径上。适合计算机专业大三学生做课程设计、信息管理专业做毕业设计、二级学院信息员做轻量级试运行系统——它不解决高并发但能让你亲手把「事务回滚」写进 catch 块里而不是抄一行Transactional(rollbackFor Exception.class)。2. 搭建最小可运行环境用 JDK 8 Tomcat 9 MySQL 5.7 跑通首页登录流程2.1 环境版本锁死为什么必须用 JDK 8 而不是 JDK 17JSP 编译依赖javax.servlet.jsp.JspFactory该类在 JDK 9 的模块化体系中被移出默认 classpathTomcat 9 虽支持 JDK 11但其内置的 Jasper JSP 引擎对 EL 表达式如${user.name}的解析逻辑与 JDK 8 下编译的.class文件存在字节码兼容性问题。实测用 JDK 17 编译LoginServlet.java后部署到 Tomcat 9访问/login.jsp会抛java.lang.NoClassDefFoundError: javax/el/ExpressionFactory。正确做法JDK必须用JDK 8u291官方最后稳定版兼容所有 JSP 标签库TomcatApache Tomcat 9.0.832023 年 10 月发布修复了 JSP include 时 request attribute 丢失的 bugMySQL5.7.44注意不是 8.x因为源码中jdbc:mysql://localhost:3306/db?useSSLfalseserverTimezoneGMT%2B8连接串里的serverTimezone参数在 8.0 需要额外配置allowPublicKeyRetrievaltrue而原项目未补提示不要下载官网最新版 Tomcat 10它的 Servlet API 已升级到 5.0而源码中web.xml的web-app根节点 namespace 仍是http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd版本错配会导致web.xml解析失败启动时直接报org.xml.sax.SAXParseException。2.2 数据库初始化三条 SQL 命令搞定建库、建表、插测试数据解压后找到sql/目录下的init.sql它包含建库语句但漏了字符集声明——直接执行会导致中文插入乱码。必须手动修改-- 修改前原文件第1行 CREATE DATABASE society_db; -- 修改后加字符集和排序规则 CREATE DATABASE society_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE society_db;然后执行建表关键字段注释已标出-- 社团主表注意society_id 是 VARCHAR(10)不是 INT因为编号含字母如 TY2024 CREATE TABLE society ( society_id VARCHAR(10) PRIMARY KEY, society_name VARCHAR(50) NOT NULL, president_id VARCHAR(12) NOT NULL, -- 学号关联 student 表 create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 用户表student 表学号为主键密码用 MD5 加密存储 CREATE TABLE student ( stu_id VARCHAR(12) PRIMARY KEY, stu_name VARCHAR(20) NOT NULL, password VARCHAR(32) NOT NULL, -- 存储 MD5(明文密码) major VARCHAR(30), grade INT ); -- 报名记录表重点status 字段控制流程状态0待审核1通过2拒绝 CREATE TABLE application ( app_id INT AUTO_INCREMENT PRIMARY KEY, stu_id VARCHAR(12) NOT NULL, society_id VARCHAR(10) NOT NULL, apply_time DATETIME DEFAULT CURRENT_TIMESTAMP, status TINYINT DEFAULT 0, FOREIGN KEY (stu_id) REFERENCES student(stu_id), FOREIGN KEY (society_id) REFERENCES society(society_id) );最后插入两条测试数据确保登录页能跳转INSERT INTO student (stu_id, stu_name, password, major, grade) VALUES (20210001, 张三, e10adc3949ba59abbe56e057f20f883e, 计算机科学与技术, 3); -- 密码明文为 123456 INSERT INTO society (society_id, society_name, president_id, create_time) VALUES (JS2024, 极客社, 20210001, 2024-03-15 09:00:00);参数说明password字段值e10adc3949ba59abbe56e057f20f883e是123456的 MD5 小写 32 位结果源码中LoginServlet使用MessageDigest.getInstance(MD5)计算必须严格匹配status TINYINT DEFAULT 0是流程引擎的基石后续审批逻辑全靠它驱动。2.3 Tomcat 部署 WAR 包别直接复制webapps/先改context.xml直接把society.war放进tomcat/webapps/目录Tomcat 会自动解压但你会发现/login.jsp报 404。原因是原项目web.xml中welcome-file-list指向index.jsp而实际首页是login.jsp。必须做的两步在tomcat/conf/context.xml的Context标签下追加!-- 让 Tomcat 加载时优先读取项目内的 web.xml -- Resources cachingAllowedtrue cacheMaxSize100000 /修改项目WEB-INF/web.xml将欢迎页改为welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list然后重启 Tomcat# Linux/Mac $TOMCAT_HOME/bin/shutdown.sh $TOMCAT_HOME/bin/startup.sh # Windows %TOMCAT_HOME%\bin\shutdown.bat %TOMCAT_HOME%\bin\startup.bat访问http://localhost:8080/society/login.jsp输入学号20210001和密码123456成功跳转到main.jsp—— 最小闭环打通。3. 核心业务代码拆解从登录到招新报名看 Servlet 如何串联请求-处理-跳转3.1 LoginServlet一次 HTTP 请求背后的三次关键校验LoginServlet.java不是简单查数据库它做了三层防御空值校验防止 NPEString stuId request.getParameter(stuId); String password request.getParameter(password); if (stuId null || stuId.trim().isEmpty() || password null || password.trim().isEmpty()) { request.setAttribute(error, 学号或密码不能为空); request.getRequestDispatcher(login.jsp).forward(request, response); return; // 必须 return否则继续执行后续逻辑 }注意return不能省否则forward()后还会执行 DB 查询导致IllegalStateException: getWriter() has already been called。学号格式校验业务规则前置// 高校学号固定12位数字如 202100000001 if (!stuId.matches(\\d{12})) { request.setAttribute(error, 学号必须为12位数字); request.getRequestDispatcher(login.jsp).forward(request, response); return; }密码比对MD5 加密验证String md5Password DigestUtils.md5Hex(password); // Apache Commons Codec String sql SELECT * FROM student WHERE stu_id ? AND password ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, stuId); ps.setString(2, md5Password); // 直接比对密文不查明文 ResultSet rs ps.executeQuery(); if (rs.next()) { // 登录成功存 session HttpSession session request.getSession(); session.setAttribute(currentUser, rs.getString(stu_name)); session.setAttribute(currentStuId, stuId); response.sendRedirect(main.jsp); // 重定向避免重复提交 } else { request.setAttribute(error, 学号或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); }关键细节response.sendRedirect(main.jsp)是重定向浏览器地址栏变为/society/main.jsp而forward()是服务器端跳转地址栏不变。此处必须用sendRedirect否则刷新main.jsp会重复提交登录请求。3.2 ApplyServlet事务控制如何保证「报名发通知」原子性学生点击「申请加入」按钮触发ApplyServlet它必须确保报名记录插入application表同时更新society表的member_count字段需先查当前值再 1若任一失败全部回滚源码中事务实现如下Connection conn null; PreparedStatement ps1 null; PreparedStatement ps2 null; try { conn DBUtil.getConnection(); // 获取连接 conn.setAutoCommit(false); // 关闭自动提交 // 步骤1插入报名记录 String sql1 INSERT INTO application (stu_id, society_id, status) VALUES (?, ?, 0); ps1 conn.prepareStatement(sql1); ps1.setString(1, stuId); ps1.setString(2, societyId); ps1.executeUpdate(); // 步骤2更新社团人数先查后改避免并发覆盖 String sql2 UPDATE society SET member_count member_count 1 WHERE society_id ?; ps2 conn.prepareStatement(sql2); ps2.setString(1, societyId); ps2.executeUpdate(); conn.commit(); // 全部成功才提交 request.setAttribute(msg, 报名成功等待审核); } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); // 任一失败就回滚 } catch (SQLException ex) { ex.printStackTrace(); } } request.setAttribute(error, 系统繁忙请稍后再试); } finally { DBUtil.close(ps1, ps2, conn); // 统一关闭资源 } request.getRequestDispatcher(apply_result.jsp).forward(request, response);血泪经验conn.setAutoCommit(false)必须在获取连接后立即设置且commit()/rollback()后必须调用close()否则连接池耗尽。原项目DBUtil.java中的close()方法已封装 try-with-resources直接调用即可。3.3 main.jspJSP 页面如何安全展示动态数据而不暴露逻辑main.jsp是用户登录后的首页它不写 Java 代码只用 JSTL 标签展示数据% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % !-- 从 session 取用户名 -- h2欢迎回来c:out value${sessionScope.currentUser} //h2 !-- 展示可申请的社团列表 -- c:forEach varsociety items${societyList} div classcard h3${society.societyName}/h3 p负责人c:out value${society.presidentName} //p a hrefapply.jsp?societyId${society.societyId}申请加入/a /div /c:forEach注意${sessionScope.currentUser}中的sessionScope显式指定作用域避免与requestScope或pageScope冲突c:out标签自动 HTML 转义防止 XSS如用户名含script标签会被转成lt;scriptgt;。4. 避坑指南这 4 个错误让 80% 的新手卡在部署环节4.1 现象访问login.jsp报HTTP Status 500 – Internal Server Error日志显示java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSourceFactory原因项目依赖commons-dbcp-1.4.jar用于连接池但该 jar 包未放入WEB-INF/lib/目录。Tomcat 启动时找不到 DBCP 工厂类DBUtil.getConnection()抛异常。解决下载commons-dbcp-1.4-bin.zip解压后将commons-dbcp-1.4.jar和它依赖的commons-pool-1.6.jar一起拷贝到WEB-INF/lib/下。注意不要用commons-dbcp-2.xAPI 不兼容。4.2 现象登录成功后跳转到main.jsp页面显示空白查看源码发现c:forEach标签原样输出未解析原因JSTL 标签库未正确引入。main.jsp头部有% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %但WEB-INF/lib/缺少jstl-1.2.jar。解决下载jstl-1.2.jar注意是 1.2 版本不是 1.0放入WEB-INF/lib/。同时确认web.xml中 servlet 版本为 3.1即web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd version3.1否则 JSTL 1.2 不生效。4.3 现象MySQL 插入中文显示为??数据库和表字符集已设为utf8mb4但依然乱码原因JDBC 连接串缺少characterEncodingutf8mb4参数且my.cnf中未配置客户端默认编码。解决修改DBUtil.java中的连接 URLprivate static final String URL jdbc:mysql://localhost:3306/society_db?useSSLfalseserverTimezoneGMT%2B8characterEncodingutf8mb4;在 MySQL 配置文件my.cnf的[client]和[mysqld]段落添加[client] default-character-set utf8mb4 [mysqld] character-set-server utf8mb4 collation-server utf8mb4_unicode_ci重启 MySQL 生效。4.4 现象Tomcat 启动时报SEVERE [main] org.apache.catalina.core.StandardContext.startInternal One or more Filters have failed to start定位到EncodingFilter类原因EncodingFilter.java中chain.doFilter(request, response)被包裹在try-catch中但 catch 块里只打印日志未抛异常导致 Filter 初始化失败却无明确报错。解决修改EncodingFilter的doFilter方法public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); try { chain.doFilter(request, response); // 此处可能抛 ServletException } catch (ServletException e) { throw e; // 必须 re-throw否则 Tomcat 无法捕获启动异常 } }5. 进阶改造把「社团招新」模块升级为支持图片上传与审核意见留痕5.1 JSP 页面增加文件上传控件用enctypemultipart/form-data破解默认限制原apply.jsp是纯文本表单要支持上传个人证件照必须改造!-- apply.jsp 中替换原有 form -- form actionApplyServlet methodpost enctypemultipart/form-data input typehidden namesocietyId value${param.societyId} / label姓名input typetext namename required //labelbr label学号input typetext namestuId required //labelbr label证件照input typefile namephoto acceptimage/* required //labelbr input typesubmit value提交申请 / /form关键点enctypemultipart/form-data告诉浏览器以二进制流发送文件此时request.getParameter()失效必须用Part接口解析。5.2 ApplyServlet 改造用getPart()读取文件并保存到服务器Servlet 3.1 原生支持文件上传无需 Apache Commons FileUpload// ApplyServlet.java 中新增 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 解析普通参数 String societyId request.getParameter(societyId); String stuId request.getParameter(stuId); String name request.getParameter(name); // 2. 解析文件 Part photoPart request.getPart(photo); String fileName Paths.get(photoPart.getSubmittedFileName()).getFileName().toString(); String uploadPath request.getServletContext().getRealPath(/uploads/); // 创建上传目录 File uploadDir new File(uploadPath); if (!uploadDir.exists()) uploadDir.mkdirs(); // 保存文件重命名避免冲突 String newFileName stuId _ System.currentTimeMillis() _ fileName; photoPart.write(uploadPath File.separator newFileName); // 3. 插入数据库新增 photo_path 字段 String sql INSERT INTO application (stu_id, society_id, name, photo_path, status) VALUES (?, ?, ?, ?, 0); PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, stuId); ps.setString(2, societyId); ps.setString(3, name); ps.setString(4, /uploads/ newFileName); // 存相对路径前端可直接访问 ps.executeUpdate(); }注意photoPart.write()自动处理文件流getSubmittedFileName()获取原始文件名Paths.get().getFileName()防止路径遍历攻击如../../etc/passwd。5.3 审批页面增加「审核意见」文本域与状态更新逻辑admin_approve.jsp原只有「通过」「拒绝」按钮现增加意见输入!-- admin_approve.jsp -- form actionApproveServlet methodpost input typehidden nameapp_id value${app.appId} / input typehidden namesociety_id value${app.societyId} / label申请人${app.stuName}/labelbr label申请社团${app.societyName}/labelbr label证件照img src${app.photoPath} width100 //labelbr label审核意见textarea namecomment rows3 cols50/textarea/labelbr input typeradio namestatus value1 / 通过 input typeradio namestatus value2 / 拒绝br input typesubmit value提交审核 / /form对应ApproveServlet更新// ApproveServlet.java String statusStr request.getParameter(status); int status Integer.parseInt(statusStr); String comment request.getParameter(comment); // 新增意见字段 String appId request.getParameter(app_id); String sql UPDATE application SET status ?, comment ?, approve_time NOW() WHERE app_id ?; PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, status); ps.setString(2, comment); // 存入意见 ps.setString(3, appId); ps.executeUpdate(); // 若通过同步更新社团人数 if (status 1) { String updateSql UPDATE society SET member_count member_count 1 WHERE society_id ?; PreparedStatement ps2 conn.prepareStatement(updateSql); ps2.setString(1, request.getParameter(society_id)); ps2.executeUpdate(); }进阶技巧approve_time NOW()利用 MySQL 函数自动写入时间戳比 Javanew Date()更精准comment字段在application表中需提前ALTER TABLE application ADD COLUMN comment TEXT。我带过三届学生做这个系统最常翻车的是web.xml版本号写错、DBUtil连接池 jar 包漏放、JSP 中忘记c:out转义。后来我把DBUtil.java的getConnection()方法加上了连接超时检测ApplyServlet的文件上传加了大小限制photoPart.getSize() 5_000_000抛异常这些补丁现在都集成在最新版源码里。如果你正对着黑窗口等 Tomcat 启动不妨先检查WEB-INF/lib/下的 jar 包数量——它应该正好是 7 个commons-dbcp-1.4.jar,commons-pool-1.6.jar,mysql-connector-java-5.1.47.jar,jstl-1.2.jar,standard-1.1.2.jar,commons-codec-1.10.jar,servlet-api.jarTomcat 自带但有些打包版本会漏。希望帮到你。本文还有配套的精品资源点击获取
返回列表