首页/新闻资讯/正文详情

JSP+JavaBean+Servlet三层架构实战:登录注册留言板课程设计

发布时间:2026/11/2 20:17:39 来源:云帆数科 栏目:资讯中心
JSP+JavaBean+Servlet三层架构实战:登录注册留言板课程设计
简介这是一份面向JavaWeb初学者与课程实践者的完整入门项目源码围绕JSP、JavaBean与Servlet采用简单MVC模式实现登录注册、留言板与分页展示功能适合用来理解三层结构如何协作、完成课程设计或作为练手项目参考。压缩包共78个文件约1.86MB包含14个java源文件与对应class、14个jsp页面、10个css样式、9个xml配置及properties、jar等依赖文件另附sql建库脚本覆盖模型层读写数据库、视图层展示信息、控制层衔接前后端的完整链路。资源已有1613人学习下载读者可从中获得可直接运行的工程结构、数据库表设计思路与分页实现方式并借助清晰的目录分层快速定位各模块代码便于对照学习与二次改造。1. 从一份“能跑就行”的课程设计说起每年到了课程设计季总有人拿着一个能登录、能留言、但代码全塞在 JSP 里的项目来找我问能不能直接交。我一般会反问一句如果导师让你加一个“留言必须登录后才能发”的功能你打算改几个文件多数人答不上来。这就是 jspjavabeanservlet 这套经典 JavaWeb 组合真正要解决的问题——不是把功能堆出来而是把登录、注册、留言板这三块拆成职责清晰的层让需求变更时只动一处。这套方案适合正在做 JavaWeb 课程设计、毕业设计的学生也适合需要快速搭一个带用户体系的留言系统原型的从业者。下面按需求、设计、实现、避坑、验收的顺序把整套东西讲透。2. 需求与分层设计为什么必须把 JSP 里的 Java 代码赶出去2.1 三个核心用例的真实边界登录、注册、留言板听起来简单但每个用例背后都有一串容易被忽略的边界条件。登录要处理“用户不存在”“密码错误”“已登录重复访问登录页”三种情况注册要处理“用户名重复”“两次密码不一致”“必填项为空”留言板要处理“未登录不能发留言”“留言内容为空”“留言按时间倒序展示”。这些条件如果不在设计阶段列清楚写到一半就会发现 JSP 页面里到处是 if-else改一个判断要翻三个文件。我一般会先把用例写成一张表明确每个用例的输入、校验规则、成功跳转和失败提示再决定代码放哪一层。这张表不需要多正式但它决定了后面 Servlet 里写什么、JavaBean 里放什么。用例输入校验规则成功去向失败提示登录用户名、密码非空、用户存在、密码匹配留言板列表页用户名或密码错误注册用户名、密码、确认密码非空、用户名唯一、两次密码一致登录页对应字段错误提示发留言留言内容已登录、内容非空留言板列表页请先登录 / 内容不能为空2.2 三层结构Servlet 管流程、JavaBean 管数据、JSP 管展示这套技术栈的分层逻辑很明确Servlet 接收请求、调用业务、决定跳转JavaBean 承载数据用户、留言并提供 getter/setterJSP 只负责把数据渲染成 HTML。关键在于“JSP 里不写 Java 逻辑代码”只允许用 EL 表达式和 JSTL 标签取值。很多人翻车就翻在这里——图省事在 JSP 里写% ... %查数据库结果页面和业务搅在一起后面加个分页都无从下手。具体到模块划分我通常拆成四块用户模块注册、登录、退出、留言模块发布、列表、数据访问模块DAO封装 JDBC、公共模块数据库连接工具、字符编码过滤器。每块对应一组类包名按controller、service、dao、bean分开。这样导师问“你的业务逻辑在哪”你能直接指到 service 层而不是含糊地说“在 JSP 里”。2.3 数据库表设计两张表撑起整个系统用户表和留言表是最小可用集合。用户表存 id、用户名、密码、注册时间留言表存 id、用户 id、内容、发布时间。留言表通过 user_id 关联用户表展示时联表查出用户名。密码字段长度要留够即使课程设计阶段存明文也建议按哈希后的长度设计比如 64 位避免后面想加加密时改表结构。CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE t_message ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, content VARCHAR(500) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES t_user(id) );username加唯一约束是注册查重的最后一道防线应用层查重和数据库约束双保险能避免并发下插入重复用户。content限制 500 字前端 textarea 也同步加maxlength两边对齐。外键在课程设计里可以保留方便理解关联关系如果导师不要求去掉也不影响功能。3. 核心模块实现从注册校验到留言落库的完整链路3.1 注册与登录Servlet 里的流程控制与 Session 管理注册的 Servlet 做三件事取参数、调 service 校验并插入、根据结果转发。登录则在校验通过后把用户对象放进HttpSession后续留言模块靠 session 判断是否登录。这里有个细节登录成功后用重定向而不是转发避免刷新页面重复提交表单。WebServlet(/login) public class LoginServlet extends HttpServlet { private UserService userService new UserService(); protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); // 基础非空校验避免空指针进入业务层 if (username null || username.trim().isEmpty() || password null || password.isEmpty()) { req.setAttribute(error, 用户名和密码不能为空); req.getRequestDispatcher(/login.jsp).forward(req, resp); return; } User user userService.login(username, password); if (user null) { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); } else { // 登录成功写入 session供留言模块鉴权 req.getSession().setAttribute(loginUser, user); resp.sendRedirect(req.getContextPath() /message/list); } } }这段代码的关键点在两个分支的跳转方式失败用forward保留请求域里的错误信息页面能显示提示成功用sendRedirect让浏览器重新发起请求地址栏变成留言列表页刷新不会重复登录。loginUser这个 session 键名要在整个项目里统一留言模块判断登录状态时用的就是它。参数校验放在 Servlet 最前面是为了让 service 层只处理“格式正确”的输入职责更干净。3.2 JavaBean 与 DAO数据承载和 JDBC 收口JavaBean 就是标准的私有字段加 getter/setterUser 和 Message 各一个。真正需要设计的是 DAO 层——所有 JDBC 代码收口在这里Servlet 和 service 不直接碰 Connection。我一般写一个DBUtil负责加载驱动、获取连接、关闭资源DAO 里用 try-with-resources 或 finally 保证释放。public class MessageDao { public ListMessage findAll() { ListMessage list new ArrayList(); String sql SELECT m.id, m.content, m.create_time, u.username FROM t_message m JOIN t_user u ON m.user_id u.id ORDER BY m.create_time DESC; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Message msg new Message(); msg.setId(rs.getInt(id)); msg.setContent(rs.getString(content)); msg.setCreateTime(rs.getTimestamp(create_time)); msg.setUsername(rs.getString(username)); // 联表带出用户名 list.add(msg); } } catch (SQLException e) { throw new RuntimeException(查询留言失败, e); } return list; } }联表查询把用户名一起带出来JSP 渲染时就不用再根据 user_id 二次查库避免 N1 问题。ORDER BY create_time DESC保证最新留言在最上面这是留言板的基本体验。异常包装成 RuntimeException 往上抛由 Servlet 统一处理DAO 里不打印堆栈也不吞异常。PreparedStatement全程使用杜绝拼接 SQL 带来的注入风险这一点在答辩时经常被问到。3.3 留言板展示与发布JSP 只做渲染EL 和 JSTL 取值列表页用 JSTL 的forEach遍历 request 域里的留言集合EL 表达式直接取属性。发布留言的 Servlet 先检查 session 里有没有loginUser没有就跳登录页有则取内容、非空校验、调 DAO 插入、重定向回列表页。% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % c:forEach items${messageList} varmsg div classmsg-item span classauthor${msg.username}/span span classtime${msg.createTime}/span p${msg.content}/p /div /c:forEachJSP 里看不到一行 Java 逻辑取的全是 Servlet 提前放进 request 的属性。messageList这个键名要和 Servlet 里req.setAttribute(messageList, list)严格对应拼错就是空白页这是新手最常见的翻车点之一。发布留言的 Servlet 里鉴权判断要放在取参数之前未登录直接重定向避免无谓的处理。4. 避坑与排查这套组合最容易翻车的五个地方4.1 中文乱码POST 和 GET 要分开治现象是注册后用户名变成问号或者留言内容存进库全是乱码。原因通常是请求体编码没设或者 Tomcat 对 GET 参数的默认解码方式不一致。解决方式在 Servlet 取参数前统一req.setCharacterEncoding(UTF-8)更稳妥的做法是写一个 CharacterEncodingFilter 挂在/*上全站生效GET 请求如果还有问题检查 Tomcat 的 connector 配置里 URIEncoding 是否为 UTF-8。数据库连接串也要带characterEncodingutf8三层都对齐才不会漏。4.2 刷新重复提交登录和留言都要防现象是登录成功后按 F5浏览器提示重复提交表单或者留言发了两条。原因是成功后用了 forward请求还停在 POST 上。解决办法就是前面强调的所有“写操作”成功后一律sendRedirect让浏览器发起新的 GET 请求。这是 PRG 模式Post-Redirect-Get课程设计里加上这一条答辩时能明显看出你懂流程控制。4.3 Session 失效与未登录访问鉴权要前置现象是没登录也能直接访问留言发布接口或者登录后过一会操作又跳回登录页。前者是鉴权漏了后者是 session 超时。解决所有需要登录的 Servlet 在 doGet/doPost 开头统一判断req.getSession().getAttribute(loginUser)为空就重定向到登录页session 超时时间在 web.xml 里按需配置课程设计默认 30 分钟一般够用。更规范的做法是抽一个 BaseServlet 或过滤器做统一拦截避免每个 Servlet 重复写判断。4.4 数据库连接泄漏连接池不是可选项现象是演示几次后系统卡死日志里报连接数超限。原因是每次请求都新建连接且没关闭或者异常路径下资源没释放。解决用 try-with-resources 确保 Connection、Statement、ResultSet 按序关闭连接频繁的场景引入连接池如 Druid 或 DBCP在 DBUtil 里从数据源取连接。课程设计阶段哪怕不用池也必须保证关闭逻辑在 finally 或 try-with-resources 里这是血泪经验。4.5 JSP 找不到类或 404包名与路径对不上现象是编译报错找不到 JavaBean或者访问/login报 404。原因通常是类没放在WEB-INF/classes对应包下、WebServlet路径和表单 action 不一致、或者 JSP 里 taglib 的 uri 写错。排查顺序先看编译输出目录里有没有 class 文件再核对表单 action 和注解路径是否完全一致含大小写最后检查 JSTL 的 jar 是否放进WEB-INF/lib。这类问题没有捷径就是逐项对。5. 验收与答辩怎么证明这套东西真的能交付验收不是把项目跑起来点一遍就完事而是要能回答“边界情况怎么处理”。我一般会准备一份自测清单按用例逐条走注册时故意用已存在的用户名、两次密码不一致、留空提交登录时输错密码、未登录直接访问留言发布地址留言时提交空内容、超长内容、连续快速提交两次。每条都要看到预期的提示或跳转而不是白屏或 500 错误。这份清单同时也是答辩时导师最可能抽查的点提前走一遍现场就不慌。答辩陈述建议按“需求—分层—关键实现—边界处理”四段讲控制在五分钟内。重点讲清楚三件事为什么 JSP 里不写 Java 代码、session 怎么管登录状态、写操作为什么用重定向。可以准备一张简单的分层示意图Servlet→Service→DAO→数据库比念代码有效得多。如果导师追问“密码为什么存明文”坦诚说明课程设计阶段聚焦流程并指出改进方向是加盐哈希比硬编理由更稳。验收项操作预期结果注册查重用已存在用户名注册提示用户名已存在不插入登录鉴权未登录访问发布接口重定向到登录页空内容留言提交空白留言提示内容不能为空重复提交登录成功后刷新不重复登录停留列表页中文显示注册中文用户名并发留言页面和数据库均正常显示从那以后我每次带人做这类项目都强制先过一遍这张验收表再谈优化因为大部分“看起来能跑”的代码都倒在边界条件上。希望这套结构和清单能帮你把课程设计交得踏实一点。本文还有配套的精品资源点击获取

相关推荐

学术写作AI检测与规避技术全解析
学术写作AI检测与规避技术全解析

1. 学术写作的检测困境与AI工具崛起 最近在指导研究生论文时,发现一个越来越明显的现象:学术检测系统正在从单纯的"查重"升级为"查重查AI"的双重检测模式。上周有位学生的初稿在Turnitin上显示重复率12%,看起来不错&… · 2026/11/2 20:17:39

大模型入门到实战:从Transformer原理到Agent开发全景图
大模型入门到实战:从Transformer原理到Agent开发全景图

1. 先搞清楚大模型到底是个什么东西1.1 一次带团队后的重新出发——为什么需要系统性的学习资料两年前我刚开始接触大模型的时候,完全靠碎片化学习:今天看一篇讲 Transformer 的文章,明天刷一个 LoRA 的教程,后天再试一个 vLLM 部… · 2026/11/2 20:17:39

大模型系统性入门:从认知框架到本地部署与微调实战
大模型系统性入门:从认知框架到本地部署与微调实战

大模型的系统性入门,最怕的不是看不懂论文,而是被一堆碎片知识带偏方向。今天看到某个框架的教程,明天收藏某个微调实战,资料存了几十个G,真要动手时却发现连“模型到底在做什么”都没弄清楚。我接触大模型这些年&… · 2026/11/2 20:17:39

网页天气可视化工具开发:API调用与Canvas渲染实践
网页天气可视化工具开发:API调用与Canvas渲染实践

1. 项目概述:网页天气可视化工具开发实录去年夏天连续两周的暴雨预警让我意识到,市面上大多数天气应用都只提供枯燥的数字预报。作为前端开发者和数据可视化爱好者,我决定动手打造一个能直观展现天气变化的网页应用。这个项目融合了第三方天气… · 2026/11/2 20:58:01

IEC104主站源码解析:APCI/ASDU、总召与遥测实现
IEC104主站源码解析:APCI/ASDU、总召与遥测实现

简介:这份资源是面向电力自动化、SCADA 系统开发者与工控通信学习者的 IEC 60870-5-104 主站协议实现源码,适合已具备网络编程与 C/C 基础、希望深入理解 104 主站通信细节的中高级开发者。压缩包共 28 个文件、约 302KB,以 cpp 与 h 源文件为… · 2026/11/2 20:58:01

Python os 模块实战:跨平台路径、目录遍历与进程避坑
Python os 模块实战:跨平台路径、目录遍历与进程避坑

上周帮人看一个数据清洗脚本,本地 Windows 上跑了小半年没出过事,扔到一台 Linux 机器上第一行就抛FileNotFoundError——路径里硬编码了反斜杠,再叠加一句os.chdir()换工作目录,相对路径全乱套。这类问题不复杂,但排查… · 2026/11/2 20:58:01

MATLAB mean数组均值:维度参数与omitnan缺失值处理
MATLAB mean数组均值:维度参数与omitnan缺失值处理

1. 先把"均值"这件事想清楚:从标量到矩阵的思维转换很多人第一次在 MATLAB 里写mean的时候,脑子里想的是一维数组求平均:几个数加起来除以个数,完事。等到真的拿它去处理实验数据、图像矩阵、传感器时序,才发… · 2026/11/2 20:58:01

Navicat SQL格式化功能解析与应用实践
Navicat SQL格式化功能解析与应用实践

1. Navicat的SQL格式化功能概述 作为数据库开发人员,我们经常需要处理复杂的SQL查询语句。这些语句可能包含多个子查询、连接条件和嵌套函数,导致代码行数膨胀,可读性下降。Navicat Premium提供的SQL格式化功能正是解决这一痛点的利器。 SQL… · 2026/11/2 20:58:01

从零学AI工程:数据、部署、监控的避坑指南与实战路线
从零学AI工程:数据、部署、监控的避坑指南与实战路线

从零开始学AI工程:我踩过的坑,和真正值得走的路线“ai engineering from scratch”这个话题,我其实一开始是带着怀疑的——两年前市面上讲AI的课程,十个里面有九个都在教你怎么调sklearn、怎么跑通一个pytorch的官方demo&#xff… · 2026/11/2 20:57:01

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

雷达信号调制技术解析:从LFM到伪线性调频原理与应用
雷达信号调制技术解析:从LFM到伪线性调频原理与应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

基于MAX14431与TM4C123的工业SPI隔离电路设计全攻略
基于MAX14431与TM4C123的工业SPI隔离电路设计全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

PLFM_RADAR:相位线性调频雷达信号处理框架
PLFM_RADAR:相位线性调频雷达信号处理框架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 1:01:15

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码