简介:基于Java的滑雪场管理系统设计与实现文档是一份面向高校毕业设计、课程设计与Java开发初学者的完整技术资料,围绕滑雪场会员管理、雪具租赁、归还流程、收银统计等核心业务,阐述了基于B/S架构的Web系统从需求分析、系统设计、编码实现到测试维护的全过程,可直接用于理解JSP、MySQL与Tomcat协同开发的企业级项目实现思路。资源包共包含1个docx文档,整体大小约952KB,文档结构清晰,涵盖绪论、需求分析、系统设计、系统实现、系统测试、运行维护与结论七大章节,并附有关键代码示例、数据库设计及目录索引,便于按章节查阅与学习;其中对会员信息管理、雪具租赁管理、收银情况统计等模块的划分和数据库表结构均给出了完整设计。截至当前已有250人学习下载,适合需要完成同类课题设计、参考业务模块划分或快速搭建滑雪场管理系统的读者使用。
1. 滑雪场管理系统:一套 JSP + MySQL 的 B/S 架构源码能解决什么
先说结论:这份基于 Java 的滑雪场管理系统,不是那种空壳演示项目,而是把滑雪场最痛的四件事——会员信息管理、雪具信息管理、租赁归还、收银统计——全部串起来的一套完整 Web 系统。技术栈是典型的课设标配:JSP 做前端页面,Servlet 处理业务逻辑,MySQL 存数据,Tomcat 跑服务,MyEclipse 直接导入就能跑。适合谁?正在做 Java Web 课设、毕业设计,或者想快速拿一套 B/S 结构项目练手的人。它最大的价值不是代码多高级,而是业务闭环完整:从会员办卡、租雪具、归还结算到收银统计,一条链路走通,数据库表结构、页面交互、权限控制全都有现成答案。我拆完这套源码的第一感受是:麻雀虽小,五脏俱全,刚好够你改造成自己想要的形态。
2. 技术选型与架构:为什么 JSP + Servlet 这套老组合还值得拆
2.1 B/S 结构到底怎么理解:浏览器、Tomcat、MySQL 三者怎么协作
这套系统采用的是 B/S(Browser/Server)架构,也就是浏览器/服务器模式。你不需要在客户机上装任何客户端软件,打开浏览器输入 URL,就能访问系统。这和 C/S 架构最大的区别是:业务逻辑全部集中在服务器端,客户端只是一个展示层。
实际运行时的请求链路是这样的:
浏览器发起 HTTP 请求 → Tomcat 接收请求并找到对应的 JSP/Servlet → Servlet 调用 JDBC 连接 MySQL 查询数据 → 把结果封装成 Java 对象 → 转发到 JSP 页面渲染成 HTML → 浏览器展示给用户。
浏览器 → Tomcat(JSP/Servlet)→ JDBC → MySQL提示:JSP 本质上是一个被容器编译成 Servlet 的模板文件。第一次访问时 Tomcat 会把 .jsp 编译成 .java 再编译成 .class,所以第一次访问慢、后续访问快是正常现象。
我在拆这套源码时特意确认了它的分层逻辑,虽然 JSP 里直接写了不少 Java 代码,没有严格的 MVC 分层,但业务模块划分是清晰的。对于课设和毕设来说,这种「轻分层」反而是好事——代码量可控,逻辑一目了然,答辩时你能讲清楚每一行代码的作用。
2.2 Tomcat 和 MySQL 的版本匹配:一个容易被忽略的启动前提
拆这套系统时我注意到一个关键细节:它要求的是 Tomcat 6.0 和 MySQL 5.x 的组合。这个版本匹配不是随便写的,因为 JDBC 驱动、JSP 编译器的兼容性都和版本强相关。
Tomcat 6.0 对应 Servlet 2.5 规范,支持 JSP 2.1。如果你换成 Tomcat 9 或 Tomcat 10,大概率会遇到两个问题:一是 JDBC 驱动类名变更(com.mysql.jdbc.Driver变成com.mysql.cj.jdbc.Driver),二是javax.servlet包名在 Tomcat 10 里变成了jakarta.servlet,源代码直接编译报错。
MySQL 5.x 用的是com.mysql.jdbc.Driver,MySQL 8.x 用的是com.mysql.cj.jdbc.Driver,而且还多了一堆时区参数要配置。这套系统源码里写的是老驱动名,所以最好的方案是老老实实用 MySQL 5.5 或 5.7,别一上来就上 MySQL 8,否则你会被各种连接报错折磨。
2.3 JSP 九大内置对象:这套系统里实际用到了哪几个
JSP 的内置对象是写页面时不用声明就能直接用的对象。这套系统里实际用到的主要是这几个:
| 内置对象 | 类型 | 在滑雪场系统里的用途 |
|---|---|---|
| request | HttpServletRequest | 接收表单提交的会员信息、租赁信息 |
| response | HttpServletResponse | 重定向页面、设置响应编码 |
| session | HttpSession | 保存登录状态、当前管理员信息 |
| out | JspWriter | 向页面输出提示信息、表格数据 |
| application | ServletContext | 记录全局配置信息 |
| pageContext | PageContext | 页面级数据共享 |
// 典型的登录状态校验代码,在系统首页 index.jsp 里很常见 <% Object admin = session.getAttribute("admin"); if (admin == null) { response.sendRedirect("login.jsp"); return; } %>这段代码的逻辑是:每次访问管理页面时先检查 session 里有没有登录标记。如果没有,直接重定向到登录页,防止未授权访问。session.getAttribute("admin")拿到的对象是在登录成功后通过session.setAttribute("admin", adminUser)存进去的。
注意:这套系统是纯 JSP 脚本写法,用
<% %>直接嵌入 Java 代码。如果你打算改成 Servlet + JSP 的标准 MVC,重点就是把这里的业务逻辑抽到 Servlet 里,JSP 只负责渲染。
3. 数据库设计与建表实战:四张核心表和 E-R 模型的落地
3.1 从 E-R 图到物理表:会员、雪具、租赁、管理员的关系梳理
这套系统的数据库设计遵循了标准的 E-R 模型转换流程。我对照源码里的建表语句和论文里的 E-R 图做了核对,一共四张核心表:会员信息表、雪具信息表、租赁信息表、管理员表。
它们之间的关系是典型的「一主多从」:
会员和租赁是一对多,一个会员可以有多次租赁记录;雪具和租赁也是一对多,一件雪具可以被多次租借;租赁表通过会员 ID 和雪具 ID 两个外键把会员和雪具关联起来。这种设计在关系型数据库里是最常规的做法,数据冗余少,查询时通过 JOIN 关联即可。
3.2 四张表的建表 SQL 与关键字段说明
直接看核心建表 SQL,注意字段类型、长度和约束的选择:
-- 会员信息表 CREATE TABLE t_yonghu ( id INT(4) NOT NULL AUTO_INCREMENT COMMENT '编号', yonghuming VARCHAR(50) NOT NULL COMMENT '用户名', mim a VARCHAR(50) NOT NULL COMMENT '密码', xingming VARCHAR(50) DEFAULT NULL COMMENT '姓名', xingbie VARCHAR(10) DEFAULT NULL COMMENT '性别', nianling INT(4) DEFAULT NULL COMMENT '年龄', lianxidianhua VARCHAR(20) DEFAULT NULL COMMENT '联系电话', dianziyouxiang VARCHAR(50) DEFAULT NULL COMMENT '电子邮箱', dizhi VARCHAR(100) DEFAULT NULL COMMENT '地址', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 雪具信息表 CREATE TABLE t_xueju ( id INT(4) NOT NULL AUTO_INCREMENT COMMENT '编号', mingcheng VARCHAR(50) NOT NULL COMMENT '名称', jiage DECIMAL(10,2) DEFAULT NULL COMMENT '价格', beizhu VARCHAR(200) DEFAULT NULL COMMENT '备注', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 租赁信息表 CREATE TABLE t_zulin ( id INT(4) NOT NULL AUTO_INCREMENT COMMENT '编号', huiyuanid INT(4) NOT NULL COMMENT '会员ID', xuejuid INT(4) NOT NULL COMMENT '雪具ID', zulinshijian DATETIME DEFAULT NULL COMMENT '租赁时间', guihuanshijian DATETIME DEFAULT NULL COMMENT '归还时间', shifouguihuan VARCHAR(10) DEFAULT '否' COMMENT '是否归还', zulinfeiyong DECIMAL(10,2) DEFAULT NULL COMMENT '租赁费用', PRIMARY KEY (id), FOREIGN KEY (huiyuanid) REFERENCES t_yonghu(id), FOREIGN KEY (xuejuid) REFERENCES t_xueju(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 管理员表 CREATE TABLE t_guanliyuan ( id INT(4) NOT NULL AUTO_INCREMENT COMMENT '编号', denglueming VARCHAR(50) NOT NULL COMMENT '登录名', mima VARCHAR(50) NOT NULL COMMENT '密码', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;几个关键设计决策:
第一,字符集统一用utf8,不是utf8mb4。这是因为 MySQL 5.x 时代默认字符集就是 utf8,如果你用 MySQL 8 建表,建议直接utf8mb4,不然 emoji 表情存不进去,中文虽然没影响,但从规范角度 utf8mb4 才是正解。
第二,shifouguihuan字段用VARCHAR(10)存「是」或「否」,不是用TINYINT(1)存 0 或 1。从数据库设计规范角度说布尔值应该用数字,但这个系统的查询逻辑是直接字符串等于判断,所以这个设计反而让代码更直观——WHERE shifouguihuan = '否'一眼就能看懂。
第三,租赁费用zulinfeiyong用DECIMAL(10,2),这是钱的标准类型,千万别用FLOAT或DOUBLE,浮点数算钱会有精度丢失的经典问题。
3.3 JDBC 连接原理:驱动加载、连接获取、资源关闭
JDBC 连接这块是这套系统里最容易抄错的地方。源码里用的连接方式是标准的六步:
// 1. 加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2. 定义连接 URL,注意指定字符编码防止乱码 String url = "jdbc:mysql://localhost:3306/huaxue?characterEncoding=utf-8"; // 3. 获取连接 Connection conn = DriverManager.getConnection(url, "root", "123456"); // 4. 创建 Statement 对象 Statement stmt = conn.createStatement(); // 5. 执行 SQL ResultSet rs = stmt.executeQuery("SELECT * FROM t_yonghu"); // 6. 关闭资源 rs.close(); stmt.close(); conn.close();这段代码的逻辑不复杂,但有个细节值得注意:URL 里带了characterEncoding=utf-8,这是处理中文乱码的第一道防线。没有这个参数,JSP 页面往数据库写中文时大概率变成??。
资源关闭顺序必须是先关ResultSet,再关Statement,最后关Connection。很多初学者只关 Connection,跑单个功能没问题,但频繁操作时 Tomcat 的连接池会被耗尽,系统就卡死了。我拆这套源码时发现它没有用连接池,每次请求都新建连接——对课设没问题,但你要往生产环境放,必须换成 C3P0 或 Druid。
注意:这套系统的数据库连接代码是放在 JSP 页面里的,每个页面都重复写了一遍。这不是最佳实践,但确实是很多课设的常态,答辩时你可以提一句「我知道可以抽成 DBUtil 工具类」,算是主动暴露问题再给出解决方案。
4. 核心功能模块实现:登录、会员、租赁、收银统计的关键代码与调用链
4.1 登录模块:session 会话管理和权限校验的实现方式
登录模块是这套系统的门面。它的实现逻辑很清晰:登录表单提交用户名和密码 → JSP 页面接收参数 → 查询 t_guanliyuan 表 → 匹配成功则把管理员信息塞进 session → 跳转到主页面;匹配失败则返回登录页并给出错误提示。
// login.jsp 中登录校验的核心逻辑 String denglueming = request.getParameter("denglueming"); String mima = request.getParameter("mima"); // 拼接 SQL 查询管理员表 String sql = "SELECT * FROM t_guanliyuan WHERE denglueming='" + denglueming + "' AND mima='" + mima + "'"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { // 登录成功,保存登录状态 session.setAttribute("admin", rs.getString("denglueming")); response.sendRedirect("main.jsp"); } else { // 登录失败,返回错误信息 out.print("<script>alert('用户名或密码错误!');history.back();</script>"); }这段代码用的是字符串拼接 SQL 的方式,存在 SQL 注入风险——输入' OR '1'='1就能直接登录。但这确实是老课设的普遍写法。我的建议是:如果你拿这套系统做毕设,至少把登录这块改成PreparedStatement预编译,代码改动不大,但安全性提升了一个档次,答辩时也是加分项。
session.setAttribute("admin", ...)这一步是关键,后续所有页面的权限校验都依赖这个 session 值。response.sendRedirect("main.jsp")是重定向,浏览器地址栏会变成 main.jsp;如果用forward转发,地址栏不变但页面内容变了。从这里能看出这套系统用的是重定向,好处是避免表单重复提交。
4.2 会员管理模块:增删改查的完整页面逻辑与表单参数
会员管理是四大业务模块里最标准的 CRUD。以新增会员为例,流程是:会员添加页面填表单 → 提交到保存页面 → 接收参数 → 插入数据库 → 跳转回列表页。
// 会员添加的处理逻辑 String yonghuming = new String(request.getParameter("yonghuming").getBytes("ISO-8859-1"), "utf-8"); String xingming = new String(request.getParameter("xingming").getBytes("ISO-8859-1"), "utf-8"); String xingbie = new String(request.getParameter("xingbie").getBytes("ISO-8859-1"), "utf-8"); String lianxidianhua = request.getParameter("lianxidianhua"); String sql = "INSERT INTO t_yonghu (yonghuming, xingming, xingbie, lianxidianhua) VALUES ('" + yonghuming + "', '" + xingming + "', '" + xingbie + "', '" + lianxidianhua + "')"; stmt.executeUpdate(sql); response.sendRedirect("huiyuan_list.jsp");注意这里有一个典型的乱码处理手法:new String(request.getParameter("yonghuming").getBytes("ISO-8859-1"), "utf-8")。这是 Tomcat 默认编码导致的问题——Tomcat 6 对 POST 请求默认用 ISO-8859-1 解码,而页面是 UTF-8 编码,所以要先按 ISO-8859-1 取字节再重新编码为 UTF-8。这是老项目里最常见的「中文乱码三件套」之一,后面避坑章节会详细展开。
response.sendRedirect("huiyuan_list.jsp")用了重定向而非转发,因为新增操作后如果直接转发到列表页,用户刷新浏览器时会把表单再提交一次,产生重复数据。重定向跳转后,刷新操作变成 GET 请求,不会再触发 INSERT。
会员删除和修改的逻辑套路相同,核心是拼 SQL:
// 删除会员 String id = request.getParameter("id"); String sql = "DELETE FROM t_yonghu WHERE id=" + id; stmt.executeUpdate(sql); // 修改会员,先查出来回显到表单 String sql = "SELECT * FROM t_yonghu WHERE id=" + id; ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { // 把字段值 set 到表单控件的 value 属性里 } // 提交更新 String sql = "UPDATE t_yonghu SET xingming='" + xingming + "', xingbie='" + xingbie + "' WHERE id=" + id;4.3 租赁与归还:事务处理和状态更新的关键实现
租赁模块是这套系统的业务核心,比单纯的 CRUD 多了一层状态控制。租借雪具时要做三件事:在租赁表插入一条记录、把会员和雪具关联起来、标记雪具为已租出状态。归还时反过来:更新租赁表的归还时间和是否归还字段、释放雪具。
// 租赁登记的核心逻辑 String huiyuanid = request.getParameter("huiyuanid"); String xuejuid = request.getParameter("xuejuid"); String zulinfeiyong = request.getParameter("zulinfeiyong"); // 插入租赁记录,是否归还默认是 '否' String sql = "INSERT INTO t_zulin (huiyuanid, xuejuid, zulinshijian, shifouguihuan, zulinfeiyong) " + "VALUES ('" + huiyuanid + "', '" + xuejuid + "', NOW(), '否', '" + zulinfeiyong + "')"; stmt.executeUpdate(sql);// 归还登记的核心逻辑 String id = request.getParameter("id"); // 租赁记录的ID // 更新租赁表:设置归还时间、标记为已归还 String sql = "UPDATE t_zulin SET guihuanshijian=NOW(), shifouguihuan='是' WHERE id=" + id; stmt.executeUpdate(sql);一个值得注意的细节是NOW()函数的使用。它由 MySQL 服务器生成当前时间,而不是在 Java 代码里用new Date()生成之后传字符串。这样做的好处是时间格式由数据库统一控制,避免 Java 和 MySQL 之间的日期格式转换问题。
但这块有一个隐蔽的问题:租借和归还操作涉及「插入租赁记录」和「标记雪具状态」两步操作,但源码里没有用事务控制。如果插入成功但更新失败,数据就处于不一致状态。这是这套系统的一个缺陷,我建议你在改造时加上事务:
conn.setAutoCommit(false); // 关闭自动提交 try { // 执行多个 SQL 操作 stmt.executeUpdate(sql1); stmt.executeUpdate(sql2); conn.commit(); // 全部成功才提交 } catch (Exception e) { conn.rollback(); // 任何一个失败就回滚 } finally { conn.setAutoCommit(true); }注意:
setAutoCommit(false)之后,所有 SQL 都处于「待提交」状态。只有执行commit()才会真正写入数据库,中途任何异常执行rollback()都能把之前的操作全部撤销。这是保证租赁和归还数据一致性的唯一方案。
4.4 收银统计模块:用 SQL 聚合函数做利润统计
收银统计模块是老板最关心的功能。它的核心是一个按时间段统计租赁收入的总量查询:
// 收银统计的核心逻辑 String sql = "SELECT DATE_FORMAT(zulinshijian, '%Y-%m') AS yuefen, SUM(zulinfeiyong) AS shouru " + "FROM t_zulin WHERE shifouguihuan='是' GROUP BY yuefen ORDER BY yuefen"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { // 输出月份和对应收入到统计表格 out.println("<tr><td>" + rs.getString("yuefen") + "</td>" + "<td>" + rs.getDouble("shouru") + "</td></tr>"); }DATE_FORMAT(zulinshijian, '%Y-%m')把租赁时间格式化成年月,比如2025-06,然后按月份分组求和。这里只统计了shifouguihuan='是'的记录,也就是只有已经归还的租赁才计入收入——这个过滤条件很重要,没归还的雪具意味着还在租赁周期里,费用不应该提前入账。
4.5 修改密码和退出系统:两个小功能里的 session 操作细节
修改密码的逻辑相对简单,先校验旧密码是否正确,再更新为新密码:
// 修改密码 String oldPwd = request.getParameter("oldPwd"); String newPwd = request.getParameter("newPwd"); // 从 session 中获取当前登录管理员 String admin = (String) session.getAttribute("admin"); // 先验证旧密码 String sql = "SELECT * FROM t_guanliyuan WHERE denglueming='" + admin + "' AND mima='" + oldPwd + "'"; ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { // 旧密码正确,更新新密码 String updateSql = "UPDATE t_guanliyuan SET mima='" + newPwd + "' WHERE denglueming='" + admin + "'"; stmt.executeUpdate(updateSql); out.print("<script>alert('密码修改成功!');</script>"); } else { out.print("<script>alert('旧密码错误!');</script>"); }退出系统的实现更简单,核心就两行:
session.invalidate(); // 销毁整个会话 response.sendRedirect("login.jsp"); // 回到登录页session.invalidate()会清空 session 里所有属性,这比逐个removeAttribute更彻底。退出后用户回退浏览器访问之前的页面,session.getAttribute("admin")会返回 null,权限校验不通过,自动弹回登录页。
5. 部署与踩坑:从 MyEclipse 导入到 Tomcat 启动的全过程实录
5.1 环境准备与项目导入:JDK 版本、编码设置、构建路径三个前置条件
我按这套系统的要求,从零开始部署了一遍,记录下整个流程和遇到的坑。如果你是新手,严格按步骤走,半小时内能跑起来。
环境版本我建议这样匹配:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.6 或 1.7 | 太高版本可能不兼容 MyEclipse 6 |
| MyEclipse | 6.0.1 | 源码就是在该版本开发的 |
| Tomcat | 6.0 | 对应 Servlet 2.5 规范 |
| MySQL | 5.5 或 5.7 | 驱动用 com.mysql.jdbc.Driver |
| 浏览器 | Chrome / Edge | 实测 IE 兼容模式会有样式问题 |
导入项目的步骤:
File → Import → General → Existing Projects into Workspace → 选择项目根目录 → 勾选 Copy project into workspace → Finish导入之后,第一件事是检查 JDK 编译版本:右键项目 → Properties → Java Compiler,确认 Compiler compliance level 是 1.6 或 1.7。第二件事是把 MySQL 驱动 jar 包(mysql-connector-java-5.x.jar)拷到 WebRoot/WEB-INF/lib 目录下,或者在 Build Path 里添加外部 Jar。第三件事是修改数据库连接参数,找到源码里的 JDBC 连接代码,把用户名和密码改成你自己的。
5.2 启动 Tomcat 的完整流程与验证方法
在 MyEclipse 里配置 Tomcat:Window → Preferences → MyEclipse → Servers → Tomcat → Tomcat 6.x,设置 Tomcat 安装目录,然后 Apply。
部署项目到 Tomcat:
右键项目 → Run As → MyEclipse Server Application → 选择 Tomcat 6.x → OKTomcat 启动后,观察 Console 窗口的输出日志。看到INFO: Server startup in xxx ms就说明启动成功。然后在浏览器输入:
http://localhost:8080/huaxue/login.jsp注意这里的访问路径是项目名。如果你导入项目后改了名字,访问路径要跟着变。如果你配置了 Tomcat 的虚拟目录或者把项目打成 WAR 包放到 webapps 下,路径规则又不一样。
5.3 常见部署报错的快速定位清单
部署过程中最容易翻车的几个点,我按出现频率排序:
| 现象 | 可能原因 | 快速排查方法 |
|---|---|---|
| Tomcat 启动闪退 | JDK 环境变量没配好 | 命令行执行java -version验证 |
| 数据库连接失败 | 用户名密码不匹配 / MySQL 服务没启动 | 先启动 MySQL,再用命令行测试连接 |
| jdbc 驱动类找不到 | jar 包没放进 lib 目录 | 检查 WEB-INF/lib 下是否有 mysql-connector-java.jar |
| 登录后乱码 | 页面编码和 Tomcat 编码不一致 | 确认页面是 UTF-8,URL 带 characterEncoding=utf-8 |
| 404 错误 | 访问路径不对 / 项目没部署成功 | 在 Console 里看 Tomcat 是否加载了该应用 |
6. 避坑清单:这套滑雪场系统最常踩的六个问题,现象、原因、解决一次说清
6.1 中文乱码三连:页面显示问号、数据库存 ??、查询条件中文失效
现象:JSP 页面插入的中文数据在数据库里变成??;或者数据库里中文是对的,页面上显示乱码。
原因:乱码链条上有三个环节,任何一处编码不一致都会出问题。第一是 JSP 页面本身的pageEncoding和charset没设置成 UTF-8;第二是 Tomcat 接收 POST 请求时默认用 ISO-8859-1 解码;第三是 JDBC 连接 URL 没带characterEncoding=utf-8。
解决:三个环节全部统一。第一,每个 JSP 文件头部加<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>;第二,在接收参数的代码里做编码转换,或者给 Tomcat 配置过滤器统一处理;第三,JDBC URL 里加characterEncoding=utf-8。
我的习惯是直接在项目里加一个 EncodingFilter,在 web.xml 里注册,所有请求统一走 UTF-8 编码。这样既有地方加全局过滤器,也是答辩时的加分点: <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter>6.2 登录永远是「用户名或密码错误」,数据库密码明明是对的
现象:在 MySQL 命令行里查询管理员表,用户名密码都正确,但在登录页面输入同样的值却提示错误。
原因:登录 SQL 拼接时把密码字段类型或者多空格带进去了。比如建表时mima VARCHAR(50),但 INSERT 时没有给密码字段赋值或者赋值了NULL,导致WHERE mima='123456'永远匹配不上。
解决:在 MySQL 里直接查询核对:
SELECT * FROM t_guanliyuan WHERE denglueming='admin' AND mima='123456';如果这条 SQL 能查到记录,说明 SQL 没问题,是页面传参的问题。检查登录页表单的name属性是否和request.getParameter("mima")一致——最常见的情况是表单 name 写错了,导致request.getParameter拿到null,拼接进 SQL 就变成WHERE mima='null'。
6.3 编辑中文信息保存后变成问号,但新增时是正常的
现象:新增会员没问题,编辑修改后再保存,中文全变成了?。
原因:新增和编辑走了不同的页面和参数接收代码。新增页面做了ISO-8859-1到UTF-8的编码转换,但编辑页面直接取参数没转码。
解决:对比两个页面的参数接收代码,把编码转换逻辑统一。更彻底的做法是全局过滤器统一处理,而不是在每个页面单独转码。如果不想改太多代码,就找到编辑保存的 JSP 页面,把每个request.getParameter都用new String(...getBytes("ISO-8859-1"), "utf-8")包一层。
6.4 Tomcat 启动失败:端口被占用导致 Address already in use
现象:启动 Tomcat 后 Console 报Port 8080 required by Tomcat v6.0 Server is already in use。
原因:8080 端口被其他程序占了。最常见的是之前启动过另一个 Tomcat 实例没关干净,或者本地有其他 Web 服务占用 8080。
解决:确认占用进程并结束它。Windows 下用系统资源监视器或任务管理器查看端口占用,找到 PID 后结束进程。不想换端口的话,也可以修改 Tomcat 的server.xml里的端口号为 8081、8082 等,但注意优先级是「先杀占用进程,再改端口」,改端口是最后的选择——因为项目里的跳转地址可能写死了 8080,改了端口还得改代码。
6.5 页面表格显示时间格式带 T,比如 2025-06-01T10:30:00
现象:租赁时间的展示值中间有个T,不符合阅读习惯。
原因:MySQL 5.7 开始,DATETIME类型在某些驱动版本下返回的字符串带T分隔符,这是 ISO 8601 标准的格式。
解决:在 JSP 页面输出时间时做格式化:
// 把 Java 的 Timestamp 转成易读格式 java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String timeStr = sdf.format(rs.getTimestamp("zulinshijian"));或者在 SQL 里直接用DATE_FORMAT(zulinshijian, '%Y-%m-%d %H:%i:%s')格式化,效果一样,代码更少。
6.6 修改密码后重新登录,提示「用户名或密码错误」
现象:密码修改成功,但用新密码登录被拒绝。
原因:密码为纯数字时没问题,但新密码里如果带字母或符号,可能因为编码问题变了。另一个可能是修改密码时表单提交的新密码里含空格,request.getParameter拿到的是带空格的字符串,存进数据库时长尾空格被 MySQL 的VARCHAR保留,查询匹配时又不确定有没有做 TRIM。
解决:在登录校验时对参数做trim()处理,存储前也做一次:
String mima = request.getParameter("mima").trim(); // 入库前也 trim 一次密码是一个容易埋雷的字段,我遇到过一次用户密码末尾有个空格,折腾了半天才发现是表单自动补全带的。从那以后,我接手这类 JSP 系统的第一件事就是把密码字段的取值和入库全都加trim(),顺手把登录 SQL 从字符串拼接改成PreparedStatement预编译参数绑定,既稳住空格问题,也堵住 SQL 注入的洞。希望这篇拆解能让你少走几个弯路,把这套系统跑起来、改明白、讲清楚。
本文还有配套的精品资源,点击获取