Java Web课程设计实战:JSP+Servlet+MySQL权限系统
2026/9/16 23:28:18 网站建设 项目流程

简介:这是一套面向Java Web初学者与课程设计实践者的个人与家乡展示管理平台完整实现,基于JSP+MySQL技术栈,适用于高校Web开发类课程设计、毕业设计参考及Java全栈入门项目实战。资源包含2000个文件,主体为1621个SVG图标资源(用于前端界面美化)、100个SCSS样式文件(支持主题定制)、82个JS脚本(实现轮播、表单交互与留言功能)、48个JSP页面(覆盖首页、个人简介、技能管理、家乡特色、留言板等核心模块)以及40个Java后端类(含用户、技能、留言等业务逻辑的增删改查实现),压缩包大小47.48MB。目前已有146人学习下载。读者可直接部署运行,获得具备前后端分离雏形、多级下拉分类管理、游客注册留言与管理员后台一体化的可扩展Web应用,同时掌握JSP动态页面开发、MySQL数据库设计、Servlet基础架构及常见前端组件集成方法。

1. 这不是静态简历页,而是一个可部署、可扩展、带完整权限控制的 Java Web 课程设计实战项目

很多同学把“个人与家乡展示平台”当成纯前端页面堆砌——轮播图+几段文字+留言板,用 HTML 写完就交作业。但这个编号为100010279的课程设计项目完全不同:它基于标准 Java Web 技术栈(JSP + Servlet + JDBC),后端用 MySQL 实现完整的 CRUD 事务管理,前端集成 Bootstrap 4 风格的sb-admin-2.css和 Font Awesome 图标体系,支持游客注册、管理员分级操作、留言审核、技能分类下拉联动等真实业务逻辑。它不是演示型 Demo,而是能跑在 Tomcat 9+、兼容 JDK 8/11、具备生产级分层结构(view–controller–model–dao)的可运行系统。适合 Java Web 初学者完成课程设计答辩,也适合作为 JSP 动态页面开发、MySQL 表关系建模、Session 权限控制的实操入口。如果你正卡在“JSP 编译 class 文件保存在哪里”“如何让下拉菜单动态加载技能分类”“MySQL 中更新子查询怎么写才不报错”,这个项目就是你缺的那块拼图。

2. 从环境搭建到目录结构:为什么选 JSP 而非 Spring Boot?Tomcat 如何精准定位编译后的 .class 文件?

2.1 技术选型依据:课程设计场景下的轻量级可控性优先

Java Web 课程设计强调对底层机制的理解,而非快速交付。Spring Boot 虽好,但自动配置掩盖了 Servlet 生命周期、JSP 编译流程、JDBC 连接池初始化等关键知识点。本项目采用原生 JSP + Servlet 模式,所有请求路由、会话管理、数据库交互均由开发者显式控制。例如:用户登录校验不依赖@Secured注解,而是通过HttpSession.getAttribute("user")手动判断;留言提交不走 REST API,而是<form action="LeaveMessageServlet" method="post">直连 Servlet。这种“裸写”方式迫使学生理解web.xml<servlet-mapping>的作用、<jsp:useBean>标签与 JavaBean 的绑定规则、以及request.setCharacterEncoding("UTF-8")必须在getParameter()前调用的底层原因。MySQL 选用 5.7 版本(非 8.0),因其默认认证插件mysql_native_password与 JDBC 8.0 驱动兼容性更稳,避免初学者陷入Public Key Retrieval is not allowed类错误。

提示:不要跳过web.xml配置。本项目中<welcome-file-list>指向index.jsp,而LoginServlet<url-pattern>设为/login,这是 JSP 页面能正确转发到 Servlet 的前提。漏配会导致 404 或表单提交无响应。

2.2 Tomcat 部署路径与 JSP 编译产物定位

项目部署到 Tomcat 后,JSP 文件并非直接执行,而是先被编译为.java源文件,再编译为.class字节码。其路径规律如下(以 Windows + Tomcat 9.0.83 为例):

# JSP 源文件位置(项目内) D:\apache-tomcat-9.0.83\webapps\homeShow\index.jsp # 编译生成的 .java 和 .class 文件位置(Tomcat 工作目录) D:\apache-tomcat-9.0.83\work\Catalina\localhost\homeShow\org\apache\jsp\index_jsp.java D:\apache-tomcat-9.0.83\work\Catalina\localhost\homeShow\org\apache\jsp\index_jsp.class

该路径可通过CATALINA_BASE/work/Catalina/localhost/{context-path}精准定位。若需调试 JSP 编译逻辑(如排查jsp jsonarray import失败),直接打开index_jsp.java查看PageContext初始化、out.write()调用链及异常堆栈。注意:每次修改 JSP 后,Tomcat 默认会重新编译,但若出现中文乱码,需检查web.xml<jsp-config>是否设置了<page-encoding>UTF-8</page-encoding>

2.3 项目核心目录结构解析(含sb-admin-2.cssfontawesome.css的集成逻辑)

项目采用经典 WebContent 结构,关键目录与用途如下:

目录/文件作用注意事项
WebContent/Web 根目录,包含所有静态资源和 JSP 页面sb-admin-2.min.cssall.min.css必须按顺序引入,否则图标显示异常
WebContent/css/存放sb-admin-2.css,fontawesome.css,all.csssb-admin-2.css依赖 Bootstrap 4,需确保bootstrap.min.css已加载
WebContent/js/包含sb-admin-2.js,jquery.min.js,bootstrap.bundle.min.js轮播图依赖carousel插件,必须在bootstrap.bundle.min.js后加载
WebContent/WEB-INF/web.xmlServlet 配置中枢<filter>定义字符编码过滤器,解决jsp选择文件夹时中文参数乱码
src/com/home/model/JavaBean 类(User.java, Message.java, Skill.java)Skill.javacategory字段对应下拉菜单值,需与数据库skill_category表字段一致
src/com/home/dao/数据访问层(UserDao.java, MessageDao.java)所有 DAO 方法均使用PreparedStatement防 SQL 注入,如INSERT INTO user VALUES (?, ?, ?)
src/com/home/servlet/控制层(LoginServlet.java, LeaveMessageServlet.java)doPost()中调用request.getSession().setAttribute("user", user)实现登录态保持

注意:sb-admin-2.css并非独立框架,而是基于 AdminLTE 的轻量定制版。其导航栏菜单(<ul class="navbar-nav">)通过>-- 用户表(游客可注册,管理员由初始SQL插入) CREATE TABLE `user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) UNIQUE NOT NULL, `password` VARCHAR(100) NOT NULL, -- 存储 BCrypt 加密后字符串 `role` ENUM('admin','visitor') DEFAULT 'visitor', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 留言表(关联用户ID,支持回复) CREATE TABLE `message` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `user_id` INT NOT NULL, `content` TEXT NOT NULL, `reply_to` INT DEFAULT NULL, -- 自关联,指向另一条 message.id `status` ENUM('pending','approved','rejected') DEFAULT 'pending', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE ); -- 技能分类主表(支撑下拉菜单数据源) CREATE TABLE `skill_category` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(30) NOT NULL UNIQUE -- 如:'科研情况'、'开发技能' ); -- 技能详情表(与分类表一对多) CREATE TABLE `skill_detail` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `category_id` INT NOT NULL, `title` VARCHAR(100) NOT NULL, `description` TEXT, FOREIGN KEY (`category_id`) REFERENCES `skill_category`(`id`) ON DELETE CASCADE );

该设计覆盖java面试 er图常见考点:

  • ON DELETE CASCADE体现外键级联删除(删除用户时自动清理其留言);
  • ENUM类型用于角色和状态字段,比TINYINT更语义化,且mysql中更新子查询场景下可避免类型转换错误;
  • reply_to字段实现留言嵌套回复,是mysql存储过程实现复杂业务逻辑的预备结构(如统计某用户所有回复数)。

3. 关键功能实现:下拉菜单动态加载、留言板审核流、家乡特色多维度管理

3.1 技能管理模块:JSP 中<select>如何绑定数据库分类并支持增删改查?

技能管理页(skillManage.jsp)需同时展示分类列表与详情列表,并支持新增分类、新增详情、编辑详情、删除详情。核心逻辑在SkillServlet.java中实现:

// SkillServlet.java - 处理分类列表加载 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<SkillCategory> categories = new SkillCategoryDao().findAll(); request.setAttribute("categories", categories); // 传给 JSP String action = request.getParameter("action"); if ("addDetail".equals(action)) { int categoryId = Integer.parseInt(request.getParameter("categoryId")); request.setAttribute("currentCategory", categoryId); request.getRequestDispatcher("addDetail.jsp").forward(request, response); return; } request.getRequestDispatcher("skillManage.jsp").forward(request, response); }

对应 JSP 中动态生成下拉菜单:

<!-- skillManage.jsp --> <select name="categoryId" class="form-control"> <c:forEach items="${categories}" var="cat"> <option value="${cat.id}">${cat.name}</option> </c:forEach> </select>

逻辑说明:<c:forEach>遍历request.getAttribute("categories"),每个SkillCategory对象的idname分别作为<option>value和显示文本。此处mysql下载官网不相关,但mysql创建索引skill_category(name)字段上已建立唯一索引,防止重复分类名插入。

3.2 留言板功能:游客留言、管理员审核、回复链式存储的完整闭环

留言板涉及三类角色操作,需严格区分权限:

角色可执行操作后端校验点
游客(未登录)查看公开留言、填写新留言session.getAttribute("user") == null时禁用回复按钮
注册用户查看自己留言、回复他人留言(仅限同一页)message.user_id == sessionUser.idmessage.status == 'approved'
管理员审核留言(status更新)、删除恶意留言、回复所有留言user.role.equals("admin")UPDATE message SET status='approved' WHERE id=?

关键 SQL 实现审核:

-- 管理员审核留言(将 pending 改为 approved) UPDATE message SET status='approved', update_time=NOW() WHERE id=? -- 查询待审核留言(mysql面试题高频:WHERE + ORDER BY + LIMIT) SELECT m.id, u.username, m.content, m.create_time FROM message m JOIN user u ON m.user_id = u.id WHERE m.status='pending' ORDER BY m.create_time DESC LIMIT 10;

JSP 中显示回复链:

<!-- messageList.jsp --> <c:forEach items="${messages}" var="msg"> <div class="card mb-3"> <div class="card-header">${msg.username} · ${msg.create_time}</div> <div class="card-body">${msg.content}</div> <c:if test="${not empty msg.replyTo}"> <div class="card-footer bg-light"> <small>回复 <strong>${msg.replyToUsername}</strong>:${msg.replyToContent}</small> </div> </c:if> </div> </c:forEach>

参数说明:msg.replyToUsernamemsg.replyToContent来自MessageDao中的关联查询,SQL 使用LEFT JOIN message r ON m.reply_to = r.id获取回复内容,避免 N+1 查询。

3.3 家乡特色管理:美食/美景/风土人情三维度数据隔离与统一展示

家乡特色数据存于hometown_feature表,通过type字段区分维度:

CREATE TABLE `hometown_feature` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `title` VARCHAR(100) NOT NULL, `content` TEXT NOT NULL, `type` ENUM('food','scenery','custom') NOT NULL, -- 三类严格隔离 `image_path` VARCHAR(200), -- 存储相对路径,如 /images/food/1.jpg `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP );

JSP 展示页(hometown.jsp)按 type 分组渲染:

<!-- 使用 JSTL 标签分组 --> <c:forEach items="${features}" var="f"> <c:choose> <c:when test="${f.type == 'food'}"> <div class="col-md-4 mb-4"> <div class="card h-100"> <img src="${f.imagePath}" class="card-img-top" alt="${f.title}"> <div class="card-body"> <h5 class="card-title">🍜 ${f.title}</h5> <p class="card-text">${f.content}</p> </div> </div> </div> </c:when> <c:when test="${f.type == 'scenery'}"> <!-- 景点卡片,图标换为 🌄 --> </c:when> <c:otherwise> <!-- 风俗卡片,图标换为 🎎 --> </c:otherwise> </c:choose> </c:forEach>

提示:mysql自动备份bat不属于本项目范畴,但hometown_feature表建议每日凌晨用mysqldump备份,命令示例:
mysqldump -u root -p home_db hometown_feature > D:\backup\hometown_%date:~0,4%%date:~5,2%%date:~8,2%.sql

4. 排查高频问题:中文乱码、JSP 页面跳转失败、MySQL 连接拒绝、下拉菜单空白

4.1 中文乱码三重校验清单(覆盖java环境变量配置详细教程未提及的 Web 层细节)

乱码常出现在表单提交、数据库读取、页面显示三个环节,需逐层验证:

环节检查项正确配置
JSP 页面编码<%@ page contentType="text/html;charset=UTF-8" %>必须位于 JSP 文件首行,且charset=UTF-8不可省略
Tomcat 连接器conf/server.xml<Connector port="8080" ... URIEncoding="UTF-8"/>若缺失,jsp选择文件夹上传中文路径会乱码
MySQL 连接 URLJDBC URL 添加?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8mysql安装配置教程常忽略serverTimezone,导致java.sql.SQLException: The server time zone value '...'错误
数据库表字符集CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;utf8mb4支持 emoji,utf8在 MySQL 5.7+ 中仅为utf8mb3别名

验证方法:在LoginServlet中打印request.getParameter("username"),若为????,则问题在 Tomcat 连接器或 JSP 页面编码;若为正常中文但数据库存为??,则问题在 JDBC URL 或表字符集。

4.2 JSP 页面跳转失败:response.sendRedirect()RequestDispatcher.forward()的本质区别

常见错误:用户登录成功后response.sendRedirect("index.jsp")仍停留在登录页。原因在于sendRedirect()是客户端重定向,会丢失request中的属性;而forward()是服务器端转发,保留request属性。本项目中:

  • 登录成功:使用request.getRequestDispatcher("index.jsp").forward(request, response),以便index.jsp能读取request.getAttribute("welcomeMsg")
  • 登录失败:使用response.sendRedirect("login.jsp?error=1"),因需清空request防止敏感信息泄露。

注意:sendRedirect()的路径是相对于 Web 应用根目录(如/homeShow/index.jsp),而forward()的路径是相对于当前 Servlet 路径(如index.jspWebContent/index.jsp)。混淆会导致404

4.3 MySQL 连接被拒绝:java.sql.SQLException: Access denied for user的五步定位法

UserDao报此错,按顺序排查:

  1. 确认 MySQL 服务运行net start | findstr "MySQL"(Windows)或systemctl status mysql(Linux);
  2. 检查用户名密码:用mysql -u root -p命令行登录,验证账号密码是否正确;
  3. 验证用户权限:执行SELECT User,Host FROM mysql.user;,确认root@localhost存在且 Host 匹配;
  4. 检查 JDBC URL:确保jdbc:mysql://localhost:3306/home_dbhome_db库已存在,且root用户对该库有ALL PRIVILEGES
  5. 防火墙设置:若 MySQL 运行在远程服务器,需开放3306端口,本地测试建议用localhost而非127.0.0.1(部分 MySQL 配置对两者权限不同)。

4.4 下拉菜单为空:<c:forEach>不执行的四个隐藏原因

即使request.setAttribute("categories", list)正确,JSP 中<c:forEach>仍可能不渲染,原因包括:

  • JSTL 标签库未声明:JSP 顶部缺失<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  • JSTL JAR 包缺失WEB-INF/lib/下无jstl-1.2.jarstandard-1.1.2.jar(Tomcat 9+ 推荐用jakarta.servlet.jsp.jstl-apitomcat-jasper-el);
  • List 为 nullSkillCategoryDao.findAll()返回null而非空ArrayList,应改为return Collections.emptyList();
  • EL 表达式被禁用web.xml<jsp-config><el-enabled>true</el-enabled></jsp-config>未开启(Tomcat 9 默认开启,但旧项目可能关闭)。

验证方法:在 JSP 中添加<%= request.getAttribute("categories") != null ? "NOT NULL" : "NULL" %>,确认数据已传入。

5. 进阶技巧:用 MySQL 触发器自动记录操作日志、JSP 页面防重复提交、Tomcat 日志精确定位

5.1 为关键表添加审计日志触发器(替代mysql免安装版教程中的手动日志)

message表添加AFTER INSERT触发器,自动记录留言时间、用户IP(需应用层传入)、操作类型:

DELIMITER $$ CREATE TRIGGER log_message_insert AFTER INSERT ON message FOR EACH ROW BEGIN INSERT INTO operation_log (table_name, operation_type, record_id, operator_ip, create_time) VALUES ('message', 'INSERT', NEW.id, '127.0.0.1', NOW()); END$$ DELIMITER ;

注意:operator_ip实际应由 Java 代码通过request.getRemoteAddr()获取并作为参数传入,此处简化为固定值。真实场景中,可在LeaveMessageServlet中执行INSERT INTO message (...) VALUES (...); INSERT INTO operation_log (...) VALUES (...);事务包裹。

5.2 JSP 页面防重复提交:利用 Session Token 拦截 F5 刷新

leaveMessage.jsp中生成唯一 Token:

<% String token = java.util.UUID.randomUUID().toString(); session.setAttribute("formToken", token); %> <input type="hidden" name="token" value="<%= token %>">

LeaveMessageServlet中校验:

String token = request.getParameter("token"); String sessionToken = (String) request.getSession().getAttribute("formToken"); if (token == null || !token.equals(sessionToken)) { request.setAttribute("error", "请勿重复提交"); request.getRequestDispatcher("leaveMessage.jsp").forward(request, response); return; } request.getSession().removeAttribute("formToken"); // 一次性使用

逻辑说明:每次进入留言页生成新 Token,提交后立即销毁。F5 刷新时sessionToken已不存在,触发拦截。这比屏蔽jsp离开页面提示更可靠,且不干扰用户体验。

5.3 Tomcat 日志精确定位:从catalina.out快速定位 JSP 编译错误

当 JSP 修改后报错,catalina.out中典型错误格式:

org.apache.jasper.JasperException: Unable to compile class for JSP ... Caused by: java.lang.NullPointerException at org.apache.jsp.index_jsp._jspService(index_jsp.java:128)

关键线索是index_jsp.java:128—— 直接打开work/Catalina/localhost/homeShow/org/apache/jsp/index_jsp.java,定位第 128 行,通常为out.write(...)((MyBean) pageContext.getAttribute("bean")).getXXX()调用。若为NullPointerException,说明pageContext.getAttribute("bean")返回 null,需检查jsp:useBean标签是否遗漏scope="request"class路径错误。

提示:web项目配置tomcat后查看jsp编译后的java类是调试必经之路。不要依赖 IDE 的“热部署”,手动查看.java文件才能看清 JSP 被翻译成什么逻辑。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询