ARTICLE DETAIL

资讯详情

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

JavaWeb期末作业大学活动管理系统源码运行指南:从数据库到Tomcat部署

JavaWeb期末作业大学活动管理系统源码运行指南:从数据库到Tomcat部署 简介面向JavaWeb课程期末设计这套大学活动管理系统源码提供了完整可运行的MVC分层项目业务围绕大学校园活动的创建、审核、报名、信息维护等常见场景展开。适合正在完成期末大作业的计算机专业学生以及希望借助实例快速熟悉Servlet、JSP、DAO与数据库交互的初学者。压缩包共302个文件约12.52MB主要包含31个Java源文件、19个JSP页面、32个CSS样式、20个JS脚本、29个class文件、11个XML配置另含SQL数据库脚本与项目工程配置前端页面与后端业务代码齐全目录结构清晰可直接导入Eclipse/IDEA等IDE运行调试也便于局部替换后作为自己的期末项目提交。已有2164人学习下载。资源内覆盖UserDao、ActivityDao、ExaminerDao、ConDao等数据访问层以及AddActivityServlet、UpdateUserServlet、UpdateActivityServlet等控制层类可参考其完成登录验证、活动信息发布、审核更新等核心功能JSPServletDAO的分层方式也适合在期末答辩中讲解系统架构与请求处理流程。1. javaweb期末作业大学活动管理系统源码.zip 到底解决什么问题javaweb期末作业大学活动管理系统源码.zip这个包几乎每个高校软件技术专业的期末都会有人拿到手。它对应的系统只做一件事把校园里的活动从发布、审核、报名到最后公示的流程搬到网页上学生能浏览活动并报名辅导员或学生会管理员能创建活动、审批报名、发通知。对期末作业来说它能解决“做了个网页但不知道会不会被打回”的问题只要库表建好、角色分清、几个核心页面能点通老师问到的增删改查和登录权限都能答上。这套源码适合两类人。一类是时间紧、想先跑通再改改界面交作业的学生需要快速把环境和业务对应起来另一类是刚学完 Servlet 和 JSP、想找一份完整案例参考代码风格的新手看看别人怎么分层、怎么处理登录拦截、怎么设计表。不过直接解压不等于能跑。很多同学栽在最后一步不会配 Tomcat不会导 MySQL 驱动或者启动后先报端口占用。既然要把它变成期末能交付的东西就得先从包里的源码结构说起再一步步把运行环境搭起来。2. 拆源码骨架JSPServletDAO 三层结构以及活动管理系统的表怎么设计2.1 为什么期末作业默认采用 JSPServletDAO 三层结构而不是 SSMJavaWeb 课程的验收点通常是 MVC 是否清楚、Servlet 会不会写、JDBC 有没有用明白。SSM 这类框架会把 SqlSession、依赖注入、事务管理都包起来老师问“你的请求路径怎么到方法的”“数据库连接怎么管理的”学生很容易答不上来。所以绝大多数课程设计源码包哪怕是发到网上的版本优先采用 JSP Servlet DAO 三层结构而不是 Spring 全家桶。这种结构的分工非常直观。JSP 负责展示数据Servlet 负责接收请求和跳转页面DAO 负责跟数据库打交道。业务逻辑较少时Servlet 可以直接调 DAO不需要额外一层 Service但更规范的期末项目会加一个 Service 层把“报名前检查活动是否通过审核”“报名成功后已报名人数加一”这类操作收拢起来方便在答辩时讲清楚。从 javaweb 项目完整案例 mysql 这个方向去搜看到的大多数项目都是这个套路。很多源码包里连配套的 sql 脚本都会放好里面预置了管理员账号和几个社团活动。拿到包后第一步不是改代码而是先确认包里的项目结构长什么样。2.2 源码包里的典型包结构从 entity 到 servlet 的调用关系解压源码 zip 后如果是按正常课程设计写的目录结构一般长这样src/main/java cn/xxx/activity entity/ User.java Activity.java Registration.java dao/ UserDao.java ActivityDao.java RegistrationDao.java dao/impl/ UserDaoImpl.java ActivityDaoImpl.java RegistrationDaoImpl.java service/ ActivityService.java web/ LoginServlet.java ActivityServlet.java RegistrationServlet.java filter/ AuthFilter.java EncodingFilter.java util/ DBUtil.java src/main/resources db.properties src/main/webapp WEB-INF/web.xml login.jsp index.jsp admin/ activity_add.jsp activity_audit.jsp student/ activity_list.jsp my_activity.jsp sql/ activity_system.sql这段结构说明了几件事。entity 里就是数据库表的对应对象字段一般和表字段一一对应dao 层通常先写接口再写实现类实现类里全是 JDBC 代码web 包下放 Servletfilter 里放公共拦截逻辑。JSP 尽量放在 webapp 下按角色分子目录管理员和学生看到的页面分开这比所有页面堆在根目录更容易答辩。调用关系是浏览器请求 - Servlet 接收参数并校验 - 调 Service或直接调 DAO- Service 里完成业务规则 - DAO 执行 SQL - 返回结果到 Servlet - Servlet 转发或重定向到 JSP。只要按这个链路去读代码哪怕第一次看这份源码十分钟内就能定位到“报名按钮到底调了哪个类”。2.3 核心表设计活动、用户、报名、分类、通知公告活动管理系统的业务核心是“活动”和“报名”其余表都由这两张表延伸出来。正常课程设计里最少需要五张表用户表、活动表、报名表、活动分类表、通知公告表。如果需要展示评论或点赞再加一张评论表但不加也不影响验收。这五张表各司其职。用户表存学生和管理员用 role 字段区分身份活动表存标题、地点、时间、人数上限和审核状态报名表存“哪个用户报名了哪个活动”分类表只是给活动分个社团、讲座、竞赛等类型减少维护成本通知公告表用于在首页发布系统消息。设计上没有太多玄学关键是字段类型和索引要合理剩下交给代码实现。字段和含义可以这样拆解。活动表比较关键建议按下面这张表的思路来既覆盖功能点又不至于复杂得说不清字段名类型说明activity_idint自增主键titlevarchar(100)活动名称category_idint关联活动分类表locationvarchar(100)活动地点start_timedatetime活动开始时间end_timedatetime活动结束时间max_peopleint报名人数上限0 表示不限enrolled_countint已报名人数statustinyint活动状态0 草稿1 待审核2 已通过3 被驳回create_byint创建人用户 IDcreate_timedatetime创建时间descriptiontext活动详情活动表的 status 字段是整套系统的关键。学生端列表只显示 status2 的活动管理员后台能看到全部状态并执行审核。这里的值约定不是硬性标准但源码包和数据库脚本里一般会保持一致写代码前一定要先看 sql 脚本里的注释别按自己猜的状态值去改页面。2.4 初始化脚本建库建表时要注意的字符集和时间字段这类源码包都会附带一个 sql 初始化脚本路径通常在 sql 或 db 目录下。第一次运行时不要直接在 Navicat 里双击执行整个文件先打开看看建库语句的字符集是不是 utf8mb4。很多旧脚本默认是 utf8插入中文时没问题但遇到表情符号或特殊字符会报错。一个比较规范的初始化脚本建表部分应该长这样CREATE DATABASE IF NOT EXISTS activity_sys DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE activity_sys; CREATE TABLE t_activity ( activity_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 活动ID, title VARCHAR(100) NOT NULL COMMENT 活动名称, category_id INT NOT NULL COMMENT 分类ID, location VARCHAR(100) NOT NULL COMMENT 活动地点, start_time DATETIME NOT NULL COMMENT 开始时间, end_time DATETIME NOT NULL COMMENT 结束时间, max_people INT DEFAULT 0 COMMENT 报名人数上限0不限, enrolled_count INT DEFAULT 0 COMMENT 已报名人数, status TINYINT DEFAULT 0 COMMENT 0草稿 1待审核 2已通过 3被驳回, create_by INT NOT NULL COMMENT 创建人ID, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, description TEXT COMMENT 活动详情, KEY idx_status (status), KEY idx_time (start_time, end_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT活动表;这段 SQL 里有几个点要留意。enrolled_count是一个冗余字段实际上该用报名表统计报名人数但课程设计为了前端展示方便普遍这么写所以后面做报名和取消报名时必须用事务同时更新报名表和这个数字否则就会数据不一致。索引部分给 status 建了普通索引给活动时间建了复合索引这个设计在后文做时间冲突检查时会用到。建表后还要插入默认管理员账号和测试活动脚本里通常用INSERT INTO t_user VALUES (1, admin, 123456, 管理员, admin, ...)这种方式预置密码一般不做加密答辩时老师会问“密码为什么不加密”能答出“课程设计重点在业务生产环境会加盐哈希”就够了。3. 用 IDEA 运行 JavaWeb 项目配置JDK8、Tomcat9、MySQL8 从安装到启动3.1 环境准备JDK8 下载配置、MySQL zip 安装方式先把基础环境定下来。绝大多数课程设计源码还是按 JDK 8 写的哪怕机器上装了新版本也建议单独准备一个 JDK 8。原因很简单老项目没有用到高版本语法但 Tomcat 9 搭配 JDK 8 是最稳的组合不会遇到模块化相关的报错。网上找 jdk8 zip 下载或 exe 安装包都可以zip 版本解压后设置JAVA_HOME指向解压目录再把%JAVA_HOME%\bin加到 Path 环境变量即可。数据库这部分如果你只用可视化工具连接远程库那无所谓但源码要跑在本机就涉及 mysql zip 安装方式。zip 包比 msi 安装包清爽不写注册表、不装服务适合拿来练习。常见做法是解压到C:\mysql在根目录创建 my.ini用命令行初始化# 安装 MySQL zip 包的常用步骤Windows 环境变量 PATH 已加入 mysql bin 目录 mysqld --initialize-insecure # 这条命令生成 data 目录root 账号初始密码为空 mysqld --console # 前台启动方便直接看日志确认 3306 端口起来之后再开新窗口登录 mysql -u root -p # 初始密码为空直接回车登录 ALTER USER rootlocalhost IDENTIFIED BY 123456; FLUSH PRIVILEGES;初始化参数和启动方式是有讲究的。--initialize-insecure会让 root 初始密码为空适合本地学习用一次之后马上改密码生产环境则要用--initialize让它生成随机密码。mysqld --console前台启动适合排查问题看到ready for connections就说明成功这时再按CtrlC停掉改成net start mysql注册成服务常驻。如果本机 3306 端口已经被占用要么在 my.ini 里改port3307要么把旧的 MySQL 服务先停掉。3.2 把源码导入 IDEA 并配置 Tomcatartifact 和 application context拿到解压后的源码先判断它是不是 Maven 项目。看根目录有没有 pom.xml有就用 IDEA 直接File - Open选择该目录等 Maven 自动下载依赖没有就按普通 Web 项目导入依赖全在WEB-INF/lib下。没必要用Import Project的老流程新版 IDEA 直接 Open 反而更不容易出问题。导入后要检查 Project SDK 和语言级别。按CtrlAltShiftS打开项目结构把 Project SDK 选成 1.8Project language level 也选 8。如果代码用到了var或更高版本的语法说明这套源码不是给 JDK8 设计的那就要调整到对应版本。接着配置 Tomcat这是idea运行javaweb项目配置里最常翻车的一步。具体操作是点击工具栏的Edit Configurations点左上角加号选Tomcat Server - Local在 Application server 栏里选择已安装的 Tomcat 9 目录。切到 Deployment 标签页点加号选Artifact一般选xxx:war exploded不要选 war。Application context 设置为/activity_sys这样启动后访问地址才是http://localhost:8080/activity_sys/。如果 Deployment 里没有任何 Artifact说明 IDEA 没把项目识别成 Web 项目需要先在 Project Structure 的 Facets 里加 Web并指定 webapp 目录。这里有个处理细节war exploded是“展开的 war”开发期用它能实现 JSP 和静态资源改完直接刷新浏览器不用重新打包。改为Update resources选项而不是每次Restart Server能节省大量等待时间。Tomcat 版本如果用了 8.5 或 10也要注意Tomcat 10 后的包名变成了jakarta.*老源码里javax.*的 import 全部会编译失败遇到这种情况直接换回 Tomcat 9。3.3 初始化数据库连接db.properties、驱动 jar、JDBC 参数源码里一般会有一个db.properties文件或在DBUtil类里硬编码连接参数。课程设计的正确姿势是用配置文件避免每次改数据库密码都重新编译。文件内容通常长这样jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/activity_sys?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456逐个说下这几个参数。useUnicodetruecharacterEncodingutf8解决中文写入乱码useSSLfalse是为了避免本地连接时 SSL 握手警告serverTimezoneAsia/Shanghai是 MySQL 8 必须加的否则日期类型会报时区错误allowPublicKeyRetrievaltrue在 MySQL 8 的 caching_sha2_password 认证下很关键不加可能报Public Key Retrieval is not allowed。驱动类com.mysql.cj.jdbc.Driver是 8.x 版本的写法如果源码是按 5.x 写的这行会变成com.mysql.jdbc.Driver两个类名不一样千万不要混。驱动 jar 的加载有两种情况。Maven 项目在 pom.xml 里加依赖但要注意scope不能写成provided否则 Tomcat 运行时找不到驱动dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency非 Maven 项目需要把mysql-connector-java的 jar 文件放到WEB-INF/lib目录下。如果源码包里没有这个目录但代码引用驱动时不报错那多半是用了 Maven 依赖。启动后一旦报ClassNotFoundException: com.mysql.cj.jdbc.Driver先看这个 jar 在不在运行时的 artifact 里再看是不是放到了错误的目录。Tomcat 不会自动扫描项目外的 lib 目录。3.4 两种启动方式IDEA 配置 Tomcat 与 Maven Tomcat 插件在 IDEA 里配置好 Tomcat 后点绿色运行按钮即可。这是最接近老师验收环境的方式因为能看到 Tomcat 的控制台日志也能在 Deployment 里改 context path。如果你的 IDEA 一直报No artifacts marked多半是没在 Project Structure 里把 webapp 目录标成 Web 资源根而不是 Tomcat 本身的问题。还有一个轻量备选方案用 Maven 的 tomcat 插件启动适合不带 IDEA、想快速演示的时候。pom.xml 里加一段插件配置plugin groupIdorg.apache.tomcat.maven/groupId artifactIdtomcat7-maven-plugin/artifactId version2.2/version configuration port8080/port path/activity_sys/path uriEncodingUTF-8/uriEncoding /configuration /plugin然后在终端执行mvn clean package -DskipTests mvn tomcat7:run这个插件的内部 Tomcat 是 7.x对老课程设计项目完全够用。它有两个好处不依赖本地安装的 Tomcat换电脑也能跑mvn 命令把编译、部署、启动全部包了适合答辩前临时演示。但要注意插件一旦用了javax.*命名空间Tomcat 10 的本地环境就不适配而插件自带 7.x 反而兼容旧代码。缺点是有些新版 JDK 在 Tomcat 7 上跑旧代码会报反射权限错误所以最稳妥的还是回到 3.2 节的方式老老实实用本地 Tomcat 9。4. 核心业务逻辑实操登录拦截、活动状态切换与报名时间冲突判断4.1 LoginServlet 与 AuthFilterSession 里存用户角色决定去向登录逻辑是整个系统第一个必考考点。大多数源码包的实现方式是登录页提交到 LoginServletServlet 查数据库比对用户名密码后把用户对象放进 Session然后根据角色跳转到不同首页。管理员和普通学生看到的菜单不同靠的就是这一跳。代码风格大致是WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); User user userDao.findByUsernameAndPassword(username, password); if (user null) { request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); return; } HttpSession session request.getSession(); session.setAttribute(loginUser, user); String target admin.equals(user.getRole()) ? /admin/index.jsp : /student/activity_list.jsp; response.sendRedirect(request.getContextPath() target); } }这里有两个容易被问到的点。第一request.getSession()会新建 Session如果用户输错密码没必要新建更规范的做法是先request.getSession(false)判断有没有旧的。第二response.sendRedirect(request.getContextPath() target)必须带getContextPath()不然部署在/activity_sys路径下时重定向会丢掉这个前缀直接跳回根路径导致 404。光在登录时判断角色不够用户可以直接在浏览器输入/admin/index.jsp绕过登录页所以源码里一定还有一个过滤器。AuthFilter 的典型写法是拦截所有请求放行登录页、静态资源其他请求统一检查 SessionWebFilter(/*) public class AuthFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); if (uri.endsWith(.css) || uri.endsWith(.js) || uri.endsWith(.jpg) || uri.contains(login) || uri.endsWith(/)) { chain.doFilter(req, resp); return; } HttpSession session request.getSession(false); if (session null || session.getAttribute(loginUser) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, resp); } }过滤器这段是答辩时最值得讲的素材。它既证明了你会用 Filter 做统一权限控制又埋了一个边界话题静态资源如果不放行CSS 和图片全会被拦截页面样式全崩。很多翻车现场就是刚加完过滤器、页面变成纯文字所以放行规则要写在登录判断之前。4.2 活动状态字段驱动页面草稿、待审核、通过、驳回活动管理系统的核心场景是“发布活动”和“审核活动”而 status 字段决定了每一步页面怎么表现。管理员创建活动时源码里通常会有一个默认值设定如果学校规定活动必须审核后展示入口处默认就是待审核如果不需要审核则直接置为已通过。这个逻辑要看得仔细否则会出现辛苦添加的活动前台看不到的情况。ActivityServlet 中新增活动的处理大致是String action request.getParameter(action); if (add.equals(action)) { Activity activity new Activity(); activity.setTitle(request.getParameter(title)); activity.setLocation(request.getParameter(location)); SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm); activity.setStartTime(sdf.parse(request.getParameter(start_time))); activity.setEndTime(sdf.parse(request.getParameter(end_time))); // 时间校验开始时间必须早于结束时间且不能是过去时间 if (!activity.getStartTime().before(activity.getEndTime())) { request.setAttribute(error, 开始时间必须早于结束时间); request.getRequestDispatcher(/admin/activity_add.jsp).forward(request, response); return; } activity.setStatus(2); // 0草稿1待审核2已通过3被驳回 activity.setEnrolledCount(0); activityService.add(activity); response.sendRedirect(request.getContextPath() /admin/activity_list.jsp); }status2就是一个约定值。如果这套源码走审核流程这里应该设为1管理员在后台审核列表里看到后点“通过”再把状态改成2。学生端查询活动的 SQL 里必然有一个过滤条件WHERE status 2。所以当你发现新手艺新添加的活动后台能看到、前台看不到时九成原因是状态值没对上要么默认值写错要么学生端 SQL 里条件写死。审核本身就是一个简单的 update 操作。ActivityDaoImpl 里对应的是String sql UPDATE t_activity SET status ? WHERE activity_id ?;参数分别是审核后的状态和活动 ID。这段虽然简单但源码里通常会把它包一层判断只有处于待审核状态的活动才能被审核避免已驳回的又被捞起来重复操作。这是老师喜欢追问的“状态机”思路哪怕只是几行 if 判断也能答得很漂亮。4.3 重复报名校验代码查一次数据库唯一键兜底报名接口是活动系统里最容易出 bug 的地方。最朴素的实现是用户点“报名”前端发请求到 RegistrationServletServlet 直接INSERT INTO t_registration不做任何校验。结果就是同一个学生能报名十次人数统计完全混乱。稍微靠谱的源码包会在插入前查一次“这个用户是否已经报过名”查一次“活动人数是否满了”再决定是否继续。代码层面RegistrationService 里这段逻辑是重头戏public int signUp(int activityId, int userId) { // 已经报名过返回 0 由前端提示 if (registrationDao.exists(activityId, userId)) { return 0; } Activity activity activityDao.findById(activityId); if (activity.getStatus() ! 2) { return -1; // 活动未发布不能报名 } if (activity.getMaxPeople() ! 0 activity.getEnrolledCount() activity.getMaxPeople()) { return -2; // 报名人数已满 } // 核心报名表插入 活动表报名人数 1在同一事务里完成 return registrationService.signUpInTransaction(activityId, userId); }注意最后一步必须放在事务里。常见做法是关闭连接自动提交执行注册插入和 update 更新然后统一 commit任何一个失败就 rollback。如果源码里这两步是分开的连接执行人数统计就一定会不一致。但这还不够。哪怕代码里已经做了 exists 判断高并发下还是可能两条请求同时通过检查、同时插入重复记录。数据库层要兜底报名表需要加联合唯一键ALTER TABLE t_registration ADD UNIQUE KEY uk_activity_user (activity_id, user_id);唯一键的存在意味着即使代码漏了幂等判断第二次插入也会抛DuplicateKeyException。源码中如果捕获了这个异常并返回“报名成功”反而掩盖了问题正确的做法是统一当作“已报名”提醒。这个兜底设计是可以写进答辩文档的亮点也解释了为什么不能只依赖应用层判断。4.4 活动时间冲突检查用两条边界条件做区间重叠判断真正让活动管理系统区别于普通增删改查的往往是冲突检测。校园里常见的场景学生想同时报名两个在同一时段举办的讲座系统应该提醒“这个时间和已报名的活动冲突”。实现思路上不是遍历用户所有活动再去比较而是直接写一条关联查询让数据库帮我们判断。核心 SQL 是基于活动时间的区间重叠条件SELECT COUNT(*) FROM t_registration r INNER JOIN t_activity a ON r.activity_id a.activity_id WHERE r.user_id ? AND r.status 0 AND a.status 2 AND a.start_time ? AND a.end_time ?这段 SQL 里两个问号其实是“目标活动的结束时间”和“开始时间”。重叠判断的标准公式是两个区间是否相交已有活动开始时间早于目标活动结束时间同时已有活动结束时间晚于目标活动开始时间。边界情况要留意如果某活动 10:00 结束另一活动 10:00 开始严格和会让它们不算冲突如果校规认为连场也算冲突就把比较符改成和。状态过滤也很关键。查询条件里的r.status 0排除了已取消的报名记录a.status 2排除了未通过审核的活动避免用草稿数据做判断。这段 DAO 层代码写在 ActivityDaoImpl 里时会以 PreparedStatement 方式传参源码里常见的翻车点是忘了带这两个状态条件导致已取消的报名也参与冲突计算学生被挡住无法报新活动。这个功能不是所有课程设计都有但一旦有它是整个系统里最难答清楚的功能点。可以把上面的 SQL 打印出来在 NAVICAT 里手动替换问号验证一下答辩时直接说“我用这段 SQL 完成了基于数据库的区间重叠判断”比空谈业务逻辑要高出不少。5. 避坑手记运行 JavaWeb 活动管理系统源码常见的 5 个问题排查5.1 Tomcat 端口被占用启动报 Address already in use现象是点运行按钮后控制台出现BindException: Address already in use: JVM_Bind日志卡在初始化协议处理器阶段Tomcat 起不来。根本原因是 8080 网络端口或 8005 关闭端口被其他进程占用。很多人只改 8080改完再启动又报 8005因为 Tomcat 有多个端口Jetty、其他开发工具、甚至另一个 IDEA 里的旧 Tomcat 实例都可能占住。解决的方法是找到占用进程并结束它。Windows 下命令很直接netstat -ano | findstr 8080 taskkill /F /PID 12345第一行列出所有占用 8080 的进程和 PID第二行把对应的进程强制结束。需要注意的是这个 PID 可能是 IDEA 的启动进程也可能是占用端口的后台程序强杀前看一眼进程名。如果不想杀进程也可以改 Tomcat 的conf/server.xml把Connector port8080改成其他端口同时把后面的 shutdown 端口也改掉。但改了端口后浏览器访问地址要跟着变成http://localhost:8081/activity_sys如果是在校验收老师习惯用默认端口杀进程更省事。5.2 连接 MySQL 报错驱动类找不到、Public Key Retrieval、Unknown database现象是页面出现 500 错误控制台堆栈里出现ClassNotFoundException、SQLNonTransientConnectionException或Unknown database中的一种。这三个报错指向完全不同的原因不能混在一起猜。排查先看是哪一行。ClassNotFoundException: com.mysql.cj.jdbc.Driver表示 jar 没有进入运行时的 Web 应用里Maven 项目检查 pom.xml 依赖非 Maven 项目检查WEB-INF/lib目录。Public Key Retrieval is not allowed是 MySQL 8 的认证插件问题按 3.3 节在 url 参数里加allowPublicKeyRetrievaltrue即可。如果报Unknown database activity_sys多半是没执行初始化脚本或者数据库名不一致打开db.properties对比一下 name 就叫什么。还有个隐藏坑Access denied for user rootlocalhost。原因可能是密码写错也可能是 MySQL 8 只开了 caching_sha2_password 认证老驱动连不上。解决办法是把 root 用户的认证方式改成 mysql_native_password。这个和源码没关系但课程设计常遇到命令行执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456;改完之后重启 MySQL 服务连接就正常了。顺序上建议先测数据库连接再启动 Tomcat别让两个问题叠在一起。5.3 中文乱码JSP 页面、请求参数、数据库三个层面都要查现象很统一页面上中文变成问号明明 JSP 源文件里写的是“活动管理”浏览器里却显示乱码或者数据库里的标题变成???。这种坑分三种情况必须一层层排除不能只改一个地方。JSP 页面响应乱码原因是页面没有声明编码。源码里每个 JSP 顶部的pageEncodingUTF-8要检查同时 meta 标签里也要有charsetUTF-8。这两个不一致时以容器使用 response 的编码为准所以更可靠的是在请求进入后统一设置。常见做法是加一个编码过滤器WebFilter(/*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); chain.doFilter(request, response); } }数据库写入乱码是因为建库字符集不是 utf8mb4或者数据库连接 url 少了characterEncodingutf8。注意request.setCharacterEncoding只对 POST 请求体有效GET 请求的参数编码由 Tomcat 决定这时需要修改server.xml的 Connector 加URIEncodingUTF-8。最后提醒一个由 IDEA 引起的问题源码 zip 解压后文件可能是 GBK 编码IDEA 里打开乱码。这时别急着改代码打开右下角文件编码切换GBK和UTF-8重载找到不乱码的那个再存为项目编码。5.4 404、405、500浏览器状态码帮你缩小问题范围现象是访问页面得到一个纯文字错误页数字不同含义完全不同。404 是请求的路径不存在405 是请求方法不被 Servlet 支持500 是服务器内部代码异常。很多新手一看到 404 就认为是代码写错实际多半是部署路径问题。404 排查顺序先看地址栏有没有项目上下文。比如配置好 application context 是/activity_sys但浏览器访问http://localhost:8080/activity_sys/admin/index.jsp时少了 contextPath那必然 404。所以 JSP 里的所有表单和链接都要用request.getContextPath()拼前缀form action%request.getContextPath()%/activity?actionsignUp methodpost这是最容易遗漏的地方也是 404 的头号原因。405 是你用 GET 请求访问只实现了 doPost 的 Servlet或反过来。源码里如果WebServlet只写了 doGet表单却用 post 提交地址没问题也会 405。500 则要去看 IDEA 的 Console 标签异常堆栈里第一行是Caused by的位置跟着那个文件和行号去查而不是盯着页面上的红色报错不知所措。5.5 zip 解压后缺文件不是所有“源码包”都能直接用现象是解压后找不到src目录只有几个 JSP或者 Maven 刷新时一直报错代码大面积标红。出现这种情况先别急着怀疑源码有问题多半是压缩包本身被重复嵌套或者下载过程中文件受损。Windows 资源管理器解压时如果提示“无法完成操作”先用软件自带的“测试压缩包”功能检查完整性。有一点要专门提醒网上流传的那些所谓 zip 密码移除工具对课程设计源码包来说基本是坑反而容易把文件弄坏。正常交的期末作业源码包不会加密如果你下载的包真的带密码先找来源不要试图破解。判断项目是否能用最直接的办法是看有没有这两个标志pom.xml或WEB-INF/web.xml。有任意一个项目结构就是完整的框架。如果都没有说明这个 zip 可能只是部分文件不值得在上面浪费时间应该回头找原始资源或重建。6. 答辩前“查漏补缺”从演示脚本到源码重新打包6.1 强制刷新后的演示流程管理员与学生两个视角过一遍提交源码前一定要在自己机器上完整跑一遍演示流程按管理员和学生两种身份分别操作。开两个浏览器窗口一个用 admin 登录一个用普通学生登录对照检查管理员发布一个新活动设置好时间、地点、人数学生端刷新列表能看到这个活动点击报名成功管理员后台能看到新报名记录并修改状态学生端已报名列表出现这条记录。这四步走通系统核心功能就算稳了。如果页面没变不要只是刷新浏览器。JSP 修改后有时被缓存按CtrlF5强制刷新或直接在地址栏重新输入地址。经历过多次现场演示的人都会告诉你答辩只剩两分钟时页面还是旧内容问题八成出在浏览器缓存而不是代码。6.2 一个低成本加分点把冲突检测结果展示成活动名称列表如果基础流程都能答上来又想跟别人拉开差距建议改一处小功能在报名冲突时不只提示“时间冲突”而是直接把冲突的活动列表返回给页面。实现方式只需改 4.4 节的查询语句把COUNT(*)换成SELECT a.title然后通过 request 传给 JSP 展示。SELECT a2.title FROM t_registration r INNER JOIN t_activity a2 ON r.activity_id a2.activity_id WHERE r.user_id ? AND r.status 0 AND a2.status 2 AND a2.start_time ? AND a2.end_time ?这段是原查询的“读版本”比直接输出提示更直观答辩时能自然引出“我用的是区间重叠判断”这句话属于投入很小、回报很高的改造。改完之后记得重新跑一次报名流程确认冲突提示里的文字确实打印出的是活动名而不是一串 ID。6.3 重新归档的习惯把 SQL、README 和源码整理成能交付的 zip最后提交的压缩包不要直接用下载的原名。按课程要求的命名规则重命名比如姓名-学号-大学活动管理系统源码.zip。包内结构保持清晰src放项目源码sql放初始化脚本README.txt写运行说明。README 里至少写明 JDK8、Tomcat9、MySQL8 的版本要求数据库名和默认管理员账号以及 SQL 脚本的执行顺序。这些信息不写的话老师换一台电脑没法跑通再完整的源码也会被打折扣。打包确认之后我会习惯性地把压缩包再解压一遍按 README 重新建库、重新启动像第一次拿到它那样走一遍登录流程没问题才算完成。每次期末项目都这么做能避免很多现场翻车的尴尬。希望这些经验能帮到你祝答辩顺利。本文还有配套的精品资源点击获取
返回列表