新闻详情

新闻详情

首页 / 资讯中心 / 详情

JavaWeb留言板实战:Servlet+JSP+MySQL+Tomcat四层联动

发布时间:2026/9/28 1:46:05来源:尧图网络
JavaWeb留言板实战:Servlet+JSP+MySQL+Tomcat四层联动
简介这是一份面向高校计算机类专业学生如计科、人工智能、通信工程等的JavaWeb课程设计实战资源聚焦留言板系统开发适用于期末大作业、课程设计、毕设初期演示或小白进阶学习。项目基于JavaEE技术栈使用Eclipse IDE开发完整实现用户注册登录、留言发布与管理、评论增删、后台管理等核心功能代码经实机测试全部运行成功答辩平均分达96分具备良好可读性与可扩展性。压缩包共236个文件含35个Java源码、19个JSP页面、26个JS脚本、21个CSS样式及40张PNG界面截图等涵盖前后端逻辑、UI展示与部署说明整体大小15.73MB。已有495人下载学习配套提供详细文档说明与README指引支持在理解基础上二次开发适合作为教学参考、作业提交范本或自主学习的结构化入门项目。1. 这不是“写个JSP页面交差”的作业一个能跑通、能调试、能讲清HTTP生命周期的JavaWeb留言板才是期末大作业的及格线你手里的Eclipse刚装好Tomcat配到一半弹出“找不到或无法加载主类 org.apache.catalina.startup.Bootstrap”JSP里写了个%request.getParameter(msg)%却总显示null数据库连上了但插入数据后查不到——这不是玄学是JavaWeb初学者在真实开发链路上必然撞上的第一堵墙。这个标题里的“留言板”本质是一个最小可行的ServletJSPMySQLTomcat四层联动闭环系统它不追求炫酷UI但必须清晰暴露HTTP请求如何从浏览器发起、经Tomcat解析、由Servlet处理、用JDBC存取、再通过JSP渲染返回它不堆砌SpringBoot自动装配但要求你能手动配置web.xml、理解url-pattern匹配逻辑、亲手写doPost()里request.setCharacterEncoding(UTF-8)这行救命代码。适合计算机专业大二大三学生——你不需要会写框架但必须亲手把HttpServletRequest对象从头到尾拆开看过文档说明不是应付老师而是你未来排查ClassNotFoundException时唯一能翻的救命纸。别被“源代码文档”误导真正值钱的是每行代码背后对应的容器行为、编码陷阱和调试路径。2. 从零搭起可运行环境Eclipse Tomcat MySQL 的三件套校准2.1 Eclipse不是IDEA必须用“Eclipse IDE for Enterprise Java and Web Developers”很多同学用错版本——下载了“Eclipse IDE for Java Developers”纯Java版结果新建Dynamic Web Project时根本找不到Servlet模板。正确做法是访问 https://www.eclipse.org/downloads/找到Eclipse IDE for Enterprise Java and Web Developers注意后缀不是“Java Developers”下载最新稳定版如2023-09解压即用无需安装提示不要用Eclipse Marketplace里搜“Tomcat”插件来配服务器——那是给老版本留的兼容方案。新版本直接用内置Server视图管理更稳。2.2 Tomcat 9.x 是当前JavaWeb教学的黄金搭档为什么不用Tomcat 10因为Servlet规范从4.0升到5.0javax.servlet.*包名全改成jakarta.servlet.*而绝大多数教材、实验手册、甚至老师给的参考代码仍基于javax。强行用Tomcat 10会导致编译报错The import javax.servlet cannot be resolved。下载地址https://tomcat.apache.org/download.cgi → Binary Distributions → Core →apache-tomcat-9.0.xx.zip解压后在Eclipse中Window → Preferences → Server → Runtime Environments → Add → Apache → Tomcat v9.0 → Next → Browse选解压目录 → Finish2.3 MySQL 5.7/8.0 驱动必须手动丢进WEB-INF/lib别信Eclipse自动生成的“Add Library”——它只会把驱动加到Build Path但Tomcat运行时根本看不到。真实路径是YourProject/WebContent/WEB-INF/lib/mysql-connector-java-5.1.47.jar # 或 MySQL 8.0 对应的 mysql-connector-java-8.0.28.jar下载jar包https://dev.mysql.com/downloads/connector/j/ → 选择Platform Independent → ZIP Archive解压后找到.jar文件直接复制粘贴进项目目录不是通过Eclipse界面导入注意MySQL 8.0默认开启caching_sha2_password认证而老驱动不支持。若连接失败进MySQL命令行执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY your_password;再刷新权限FLUSH PRIVILEGES;3. 留言板核心逻辑落地Servlet处理流程与JSP渲染边界3.1 三层结构必须物理隔离src放JavaWebContent放JSPWEB-INF放配置这是新手最容易糊弄的地方——把所有.java文件拖进WebContent/WEB-INF/classes结果Tomcat启动时报Class not found。正确结构如下MyMessageBoard/ ├── src/ # Java源码Servlet、DAO、Bean │ ├── servlet/MessageServlet.java │ ├── dao/MessageDAO.java │ └── bean/Message.java ├── WebContent/ # 静态资源和JSP │ ├── index.jsp # 入口页表单提交到MessageServlet │ ├── list.jsp # 显示留言列表 │ └── WEB-INF/ │ ├── web.xml # 核心配置Servlet映射、编码过滤器 │ └── lib/ # mysql-connector-java.jar在此 └── build/ # Eclipse自动生成勿手动改3.2 web.xml里这三件事缺一不可Servlet声明、URL映射、字符编码过滤器?xml version1.0 encodingUTF-8? web-app xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlnshttp://xmlns.jcp.org/xml/ns/javaee xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 !-- 1. 声明Servlet -- servlet servlet-nameMessageServlet/servlet-name servlet-classservlet.MessageServlet/servlet-class /servlet !-- 2. URL映射关键/msg对应index.jsp里的action/msg-- servlet-mapping servlet-nameMessageServlet/servlet-name url-pattern/msg/url-pattern /servlet-mapping !-- 3. 全局编码过滤器解决中文乱码的后悔药 -- filter filter-nameCharacterEncodingFilter/filter-name filter-classfilter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameCharacterEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping /web-app逻辑说明url-pattern/msg/url-pattern必须和JSP中form action/msg完全一致少个斜杠就404过滤器url-pattern/*/url-pattern表示拦截所有请求确保request.getParameter()拿到的是UTF-8解码后的中文version4.0对应Servlet 4.0规范与Tomcat 9.x严格匹配写成3.1会丢失部分特性。3.3 MessageServlet.javaHTTP方法分发与业务逻辑分离package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import bean.Message; import dao.MessageDAO; public class MessageServlet extends HttpServlet { private static final long serialVersionUID 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // GET请求跳转到list.jsp显示所有留言 MessageDAO dao new MessageDAO(); request.setAttribute(messageList, dao.getAllMessages()); request.getRequestDispatcher(/list.jsp).forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // POST请求处理表单提交 request.setCharacterEncoding(UTF-8); // 双保险过滤器已设此处再确认 String content request.getParameter(content); String author request.getParameter(author); if (content null || content.trim().isEmpty()) { request.setAttribute(error, 留言内容不能为空); request.getRequestDispatcher(/index.jsp).forward(request, response); return; } Message msg new Message(); msg.setContent(content); msg.setAuthor(author ! null ? author.trim() : 匿名用户); msg.setCreateTime(new java.util.Date()); MessageDAO dao new MessageDAO(); boolean success dao.saveMessage(msg); if (success) { response.sendRedirect(request.getContextPath() /msg); // 重定向避免重复提交 } else { request.setAttribute(error, 保存失败请重试); request.getRequestDispatcher(/index.jsp).forward(request, response); } } }参数说明request.setCharacterEncoding(UTF-8)虽有过滤器但此处显式设置是血泪经验——某些Tomcat版本对POST参数编码不敏感response.sendRedirect(...)用重定向而非forward防止用户刷新页面时重复提交表单request.getContextPath()动态获取项目上下文路径如/MyMessageBoard避免硬编码导致部署失败。4. 数据库操作与JSP渲染DAO模式与EL表达式避坑指南4.1 MessageDAO.javaJDBC连接池不是必须但Connection必须手动关闭package dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import bean.Message; public class MessageDAO { private static final String URL jdbc:mysql://localhost:3306/message_db?useSSLfalseserverTimezoneGMT%2B8; private static final String USER root; private static final String PASSWORD 123456; public boolean saveMessage(Message msg) { String sql INSERT INTO messages(content, author, create_time) VALUES(?, ?, ?); try (Connection conn DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, msg.getContent()); pstmt.setString(2, msg.getAuthor()); pstmt.setTimestamp(3, new java.sql.Timestamp(msg.getCreateTime().getTime())); return pstmt.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); // 开发期必须打印上线要改日志框架 return false; } } public java.util.ListMessage getAllMessages() { String sql SELECT id, content, author, create_time FROM messages ORDER BY create_time DESC; java.util.ListMessage list new java.util.ArrayList(); try (Connection conn DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement pstmt conn.prepareStatement(sql); ResultSet rs pstmt.executeQuery()) { while (rs.next()) { Message msg new Message(); msg.setId(rs.getInt(id)); msg.setContent(rs.getString(content)); msg.setAuthor(rs.getString(author)); msg.setCreateTime(rs.getTimestamp(create_time)); list.add(msg); } } catch (SQLException e) { e.printStackTrace(); } return list; } }关键点try-with-resources自动关闭Connection/PreparedStatement/ResultSet避免连接泄漏serverTimezoneGMT%2B8MySQL 5.7必须显式指定时区否则create_time存入为0000-00-00java.sql.Timestamp转换java.util.Date不能直接set必须转成Timestamp。4.2 list.jsp用JSTL替代脚本片段EL表达式必须配合c:forEach% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8% % taglib urihttp://java.sun.com/jsp/jstl/core prefixc% !DOCTYPE html html head meta charsetUTF-8 title留言列表/title stylebody{font-family:Arial,sans-serif;margin:40px}/style /head body h2所有留言/h2 a href${pageContext.request.contextPath}/index.jsp我要留言/a brbr c:if test${empty messageList} p暂无留言/p /c:if c:forEach items${messageList} varmsg varStatusstatus div styleborder:1px solid #ccc;padding:10px;margin:10px 0; strong${msg.author}/strong span stylecolor:#999;font-size:0.9em; ${fn:substring(msg.createTime, 0, 19)} !-- JSTL fn函数截取时间 -- /span p${msg.content}/p /div /c:forEach /body /html注意事项% taglib ... %必须存在否则c:forEach会报错${pageContext.request.contextPath}获取项目路径比硬写/MyMessageBoard安全fn:substring需要引入JSTL函数库在WEB-INF/lib下放jstl-1.2.jarTomcat 9自带但需确认EL表达式${msg.content}自动调用getMessage()无需写getMsg().getContent()。5. 避坑EclipseTomcat环境下5个高频翻车现场与根治方案5.1 现象启动Tomcat后访问http://localhost:8080/MyMessageBoard显示404原因项目未发布到Tomcat或Context Path配置错误。解决右键项目 → Properties → Targeted Runtimes → 勾选已配置的Tomcat v9.0 → Apply再右键Tomcat Server → Add and Remove → 把项目加进去最后检查Servers视图里项目状态是否为“Started”。5.2 现象JSP中%request.getParameter(content)%输出乱码如“????”原因GET请求参数编码未设request.setCharacterEncoding()对GET无效。解决在web.xml中添加connector port8080 protocolHTTP/1.1 URIEncodingUTF-8 /需修改Tomcat/conf/server.xml或统一用POST提交表单。5.3 现象ClassNotFoundException: com.mysql.jdbc.Driver原因MySQL驱动jar包没放对位置或驱动类名过时MySQL 8.0用com.mysql.cj.jdbc.Driver。解决确认jar包在WEB-INF/lib下MySQL 5.7用com.mysql.jdbc.DriverMySQL 8.0用com.mysql.cj.jdbc.Driver并在MessageDAO.java中Class.forName()里写对。5.4 现象java.lang.NullPointerException在request.getAttribute(messageList)处原因Servlet中request.setAttribute()后没forward()或JSP里${messageList}写错变量名。解决检查Servlet中是否执行了forward()JSP中EL表达式变量名必须与setAttribute()第一个参数完全一致区分大小写。5.5 现象Eclipse控制台报SEVERE: Error listenerStart项目启动失败原因web.xml语法错误如标签未闭合、WEB-INF/lib下有冲突jar包如两个不同版本log4j。解决打开Servers视图 → 双击Tomcat → 打开Overview→ 点击Open launch configuration→ 在Arguments页签末尾加-Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCEtrue重启后错误详情会打印在Console。6. 文档说明怎么写才不是摆设从“老师看了点头”到“自己半年后还能复现”6.1 README.md必须包含这四个区块环境清单、一键启动步骤、数据库初始化SQL、常见问题速查表我一般会把文档写成可执行的“运行说明书”而不是作文。比如# JavaWeb留言板课程设计文档 ## ✅ 环境要求实测通过 - Eclipse IDE for Enterprise Java and Web Developers 2023-09 - Apache Tomcat 9.0.83 - MySQL 5.7.32或8.0.28需调整驱动类名 - JDK 1.8.0_361 ## ▶️ 三步启动复制粘贴即可 1. 启动MySQL服务sudo service mysql startLinux或双击mysqld.exeWindows 2. 创建数据库执行sql/init.sql中的建表语句 3. 在Eclipse中右键项目 → Run As → Run on Server → 选择Tomcat v9 ## 数据库初始化sql/init.sql sql CREATE DATABASE IF NOT EXISTS message_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE message_db; CREATE TABLE messages ( id INT PRIMARY KEY AUTO_INCREMENT, content TEXT NOT NULL, author VARCHAR(50) DEFAULT 匿名用户, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );❓ 常见问题速查现象定位命令解决方案访问/msg报404tail -f logs/catalina.out检查web.xml中servlet-mapping的url-pattern是否匹配表单action中文存入MySQL变问号SELECT character_set_database;执行ALTER DATABASE message_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Eclipse提示“Dynamic Web Module 4.0 requires Java 1.8 or newer”Project Properties → Project Facets → Java → 1.8右键项目 → Properties → Project Facets → Java → 选1.8Apply### 6.2 源代码注释不是写“这里创建连接”而是写“为什么用try-with-resources” 我在每个关键方法开头加一行// [决策依据]注释比如 java // [决策依据] 不用Connection Pool课程设计要求展示JDBC原生操作且并发量为0连接池反而增加复杂度 public boolean saveMessage(Message msg) { ... } // [决策依据] 用PreparedStatement而非Statement防止SQL注入且课程设计明确要求体现安全编码意识 String sql INSERT INTO messages(content, author, create_time) VALUES(?, ?, ?);这种注释让老师一眼看到你的设计思考也让你半年后重看代码时不用翻教材就能懂当初为什么这么写。6.3 最后交付前必做的三件事删掉调试日志、验证URL路径、导出WAR包删日志把所有e.printStackTrace()换成System.err.println(DEBUG: e.getMessage())上线环境严禁打印堆栈验路径在index.jsp里写%request.getContextPath()%访问页面确认输出是/MyMessageBoard而非/导WAR右键项目 → Export → WAR file → 选WebContent为Web root → 生成MyMessageBoard.war扔到Tomcat/webapps下能独立运行证明项目自包含。我带过三届学生做这个作业最常被退回的不是功能缺陷而是文档里写着“数据库密码123456”结果老师用这个密码真连上了——安全意识比代码能力更重要。现在我自己的项目哪怕只是本地测试PASSWORD也一定从config.properties读绝不硬编码。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从 CHANGELOG.md 到插件指纹:WPScan 如何用变更日志精准识别 WordCamp Dashboard Widget 版本 2026/9/28 2:46:03

从 CHANGELOG.md 到插件指纹:WPScan 如何用变更日志精准识别 WordCamp Dashboard Widget 版本

网络安全漏洞扫描渗透测试应用安全CLI 【免费下载链接】wpscan WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contactwpscan.com 项目地址: ht…

阅读更多 →
区块链做网站避坑指南:3步省下50%冤枉钱 2026/9/28 2:46:03

区块链做网站避坑指南:3步省下50%冤枉钱

区块链做网站避坑指南:3步省下50%冤枉钱 找建站公司报价时,你是不是也心里直打鼓?对方张口就是“区块链概念”、“去中心化架构”,报价单上全是看不懂的术语,总价轻松破万甚至破十万。你明明只是想要个展示项目或者落地页,却担心自己不懂行被当成“…

阅读更多 →
Webiny React 依赖审计与现代化迁移指南:基于 dependencies/react.md 的完整解读 2026/9/28 2:46:03

Webiny React 依赖审计与现代化迁移指南:基于 dependencies/react.md 的完整解读

CMS后端前端 【免费下载链接】webiny-js Open-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at…

阅读更多 →
NoneBot2 中的 aiohttp 驱动适配器:纯客户端 HTTP/WebSocket 连接的实现与使用 2026/9/28 2:46:03

NoneBot2 中的 aiohttp 驱动适配器:纯客户端 HTTP/WebSocket 连接的实现与使用

后端即时通讯 【免费下载链接】nonebot2 跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python 项目地址: https://gitcode.com/gh_mirrors/no/nonebot2 点击查看 免费下载 NoneBot2 的 nonebot.drivers.aiohttp …

阅读更多 →
动物图像数据集清洗实战:从28K原始图到生产级训练数据 2026/9/28 2:46:03

动物图像数据集清洗实战:从28K原始图到生产级训练数据

简介:本资源是一个面向计算机视觉初学者与AI实践者的动物图像分类数据集,适用于图像识别、数据增强、模型训练与迁移学习等典型CV任务。数据集涵盖狗、猫、马、蜘蛛、蝴蝶、鸡、羊、牛、松鼠、大象共10类常见动物,总计约28,000张中等质量JPG/…

阅读更多 →
mGBA 贡献指南:从 Issue 提报到编码规范与 MPL 2.0 许可合规的完整实践 2026/9/28 2:45:56

mGBA 贡献指南:从 Issue 提报到编码规范与 MPL 2.0 许可合规的完整实践

游戏开发 【免费下载链接】mgba mGBA Game Boy Advance Emulator 项目地址: https://gitcode.com/gh_mirrors/mg/mgba 点击查看 免费下载 mGBA 是一个以 C 和 C 编写的 Game Boy Advance 模拟器,同时支持 Game Boy / Game Boy Color 与 Super Game Boy&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉