ARTICLE DETAIL

资讯详情

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

JavaWeb新闻发布系统源码拆解:Servlet+JSP三层架构与分页上传实战解析

JavaWeb新闻发布系统源码拆解:Servlet+JSP三层架构与分页上传实战解析 简介这是一套基于JavaWeb的新闻发布系统毕业设计完整资料包面向计算机专业毕业生、Java Web学习者及需要实战项目的开发者。资源围绕可运行的源代码、数据库SQL脚本与毕业论文展开覆盖新闻管理、栏目分类、评论互动、用户登录等核心功能代码采用ServletJSPDAO分层帮助理解请求处理、业务逻辑与数据访问的完整链路。压缩包内共556个文件大小11.65MB包含26个Java核心类、21个JSP视图、12个Jar依赖库以及224个JS、80个PNG、30个CSS等前端页面资源后端逻辑与前端界面一一对应同时附有1个SQL数据库脚本和doc格式论文可直接导入数据库并参考写作。开发环境说明与部署常见问题解答也已包含可帮助规避Tomcat、数据库连接等典型问题。目前已有123人学习下载适合作为毕业设计蓝本、框架实战练习或求职项目经验积累。1. 把 JavaWeb 新闻发布系统拆开看这套 Servlet JSP 源码到底能练出什么聊到 JavaWeb 新闻发布系统很多人的第一反应是“又是毕设老三样”。但真把这份源码的类文件摊开——NewsServlet、NewsDao、CommentDao、IndexServlet、UserServlet、ImageUploadServlet——你会发现它是一套非常典型的 Servlet JSP DAO 三层结构。没有 Spring 全家桶的包装反而把请求分发、JDBC 操作、分页查询、文件上传这些 JavaWeb 核心考点全暴露在明面上。对于做毕业设计、准备校招面试基础轮、或者需要一个干净模板做二次开发的人来说这种“裸奔”结构的项目比框架整合项目更有拆解价值。它能让你在一两天内把 JavaWeb 的完整请求链路跑通也知道哪些地方最容易翻车。2. 请求分发链路从 NewsServlet 到 DAO 的三层结构与分页参数2.1 项目结构与请求流转的底层逻辑这套项目里没有 Spring MVC 那套注解路由而是用最原始的 Servlet 映射 业务分发来驱动整个系统。拿到源码包后第一件事不是急着在 IDEA 里跑起来而是先把类名和职责对上InitServlet应用启动时初始化通常用来加载分类列表到内存或配置文件IndexServlet首页入口负责组装新闻列表和分类数据NewsServlet新闻操作的统一入口列表、详情、新增、删除、修改都走它CommentServlet评论提交与列表查询UserServlet登录、注册、登出NewsTypeServlet新闻分类维护LinkServlet友情链接维护ImageUploadServlet图片上传处理。这套命名非常直白对应的就是后台管理菜单和前台页面模块。请求流转是一条单向链路浏览器发起 URL 请求 → 容器根据 web.xml 映射找到对应的 Servlet → Servlet 调用业务方法 → 业务方法调 DAO → DAO 拼 JDBC 执行 SQL → 结果逐层返回 → Servlet 转发或重定向到 JSP 页面。看源码时建议先从 NewsServlet 下手它是整个系统里业务分支最多的类。常见的做法是 doGet 和 doPost 共用同一个 dispatcher然后通过 action 参数区分具体操作protected void service(HttpServletRequest request, HttpServletResponse response) { String action request.getParameter(action); if (list.equals(action)) { // 分页查询新闻列表 } else if (detail.equals(action)) { // 查看新闻详情 } else if (add.equals(action)) { // 跳转到新增页面 } else if (save.equals(action)) { // 保存新闻含插入正文 } else if (delete.equals(action)) { // 删除新闻 } }action 参数的值必须和 JSP 页面表单里提交的 action 完全一致否则会直接掉进 else 分支返回空页面。这个参数是整套请求分发机制的唯一约定改错一个字符就是请求 404 或者页面空白。源码里各个 Servlet 之间没有继承统一的 BaseServlet每个类单独实现 service 或 doGet/doPost 方法。好处是逻辑直观坏处是代码重复率高。读代码时重点看两个地方RequestDispatcher 的 forward 跳转和 sendRedirect 的重定向前者用于带着 request 域中的数据到 JSP 渲染后者用于表单提交后防止重复提交。2.2 分页参数设计page 与 pageSize 的计算规则新闻列表是用户访问最频繁的页面分页查询的实现质量直接决定你能不能在答辩时讲清楚。这套项目里分页走的是传统 limit 方式传 page 和 pageSize 两个参数给 DAOSQL 动态拼 limit 偏移量。看 NewsDao 的分页方法时注意这个核心逻辑public ListNews findPage(int page, int pageSize) { int offset (page - 1) * pageSize; String sql SELECT id, title, category_id, author, publish_time FROM news ORDER BY publish_time DESC LIMIT ?, ?; PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, offset); ps.setInt(2, pageSize); // 执行查询并封装结果 }offset (page - 1) * pageSize 这条公式是整个分页的命根子。page 为 1 时偏移量是 0查第一页page 为 2 时偏移量是 pageSize跳过第一页的数据。前端页面上显示“上一页 / 下一页”时也要在 URL 里带上 page 参数否则每次点击都会回到第一页。总页数的计算在 Service 层通常用 ceil 处理int totalCount newsDao.countAll(); int totalPage (int) Math.ceil((double) totalCount / pageSize);countAll 对应的是 SELECT COUNT(*) FROM news这条统计 SQL 和列表 SQL 必须保持同样的过滤条件否则列表页数和实际数据对不上。如果源码里加了分类筛选那么 count 和 findPage 都要同时带 categoryId 条件这就是一个容易踩的隐藏坑。3. 数据库设计与首页渲染news_category 与 news 表结构的取舍3.1 表结构设计与外键约束的关键点这套系统 SQL 文件里最核心的表是 news新闻表、news_category分类表、t_comment评论表也有项目叫 comment和 t_user用户表。SQL 文件导入后先用 Navicat 或 DBeaver 把表关系理清再动代码。新闻表是一张信息密度很高的表设计时大部分字段是必填的字段名类型约束说明idint主键自增新闻唯一标识titlevarchar(100)非空新闻标题contenttext非空正文内容category_idint外键关联 news_category.idauthorvarchar(50)可空作者imagevarchar(255)可空封面图路径publish_timedatetime默认当前时间发布时间click_countint默认 0点击量category 表就简单得多id 自增主键 name 分类名。两个表通过 category_id 建立一对多关系一张分类对应多条新闻。创建表时建议加上外键约束并在 category_id 上建普通索引查询按分类筛选时会快不少CREATE TABLE news_category ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE news ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, content TEXT NOT NULL, category_id INT NOT NULL, author VARCHAR(50), image VARCHAR(255), publish_time DATETIME DEFAULT CURRENT_TIMESTAMP, click_count INT DEFAULT 0, INDEX idx_category (category_id), CONSTRAINT fk_news_category FOREIGN KEY (category_id) REFERENCES news_category(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字符集用 utf8mb4 而不是 utf8这点很多毕设项目都忽略。utf8 在 MySQL 里最多存 3 字节遇到表情符号会直接报 Incorrect string value 错误utf8mb4 是完整的 4 字节支持。另外注意到外键策略了吗这里没有指定 ON DELETE 规则默认是 RESTRICT。也就是说后台分类管理中想删除一个下面还有新闻的分类数据库会直接拒绝。3.2 IndexServlet 首页数据组装与 JSP 渲染的传值方式首页 IS 上展示的内容通常是顶部导航栏分类列表、中间最新新闻列表、侧边栏热门新闻。这里涉及一个知识点一次请求如何组装多个数据集。IndexServlet 的做法是循环向分类列表里填充每类新闻的数据属于经典的手动组装public class IndexServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) { // 1. 查询所有分类 ListNewsType typeList newsTypeDao.findAll(); // 2. 查询最新新闻列表 ListNews newestList newsDao.findTopN(10); // 3. 查询点击量最高的新闻 ListNews hotList newsDao.findByClickCount(8); req.setAttribute(typeList, typeList); req.setAttribute(newestList, newestList); req.setAttribute(hotList, hotList); req.getRequestDispatcher(/index.jsp).forward(req, resp); } }findTopN 在 DAO 层对应的 SQL 是 ORDER BY publish_time DESC LIMIT 10findByClickCount 对应 ORDER BY click_count DESC LIMIT 8。两个方法都需要在 SQL 层面控制返回条数而不是查全表后在 Java 里截取。JSP 页面里用 JSTL 标签循环输出注意页面顶部要引入标签库% taglib urihttp://java.sun.com/jsp/jstl/core prefixc % ul c:forEach items${newestList} varnews li a hrefnews?actiondetailid${news.id}${news.title}/a span${news.publishTime}/span /li /c:forEach /ulitemList 的 key 必须和 request.setAttribute 时的 key 完全一致。新闻标题如果是用户输入的富文本在列表页输出前建议做 HTML 转义否则标题里插一段 script 就是存储型 XSS。这是新闻类系统面试时高频被问到的安全问题源码里如果没做防御你可以自己加一个简单的 HtmlUtils 处理。4. 后台管理闭环NewsTypeServlet 与 ImageUploadServlet 的增删改查和文件上传4.1 NewsTypeServlet 分类维护的完整 CRUD 流程后台管理里新闻分类维护是最典型的 CRUD 场景。NewsTypeServlet 走的还是 action 分发模式没有用独立的方法路由。新增分类和编辑分类都走 save action通过是否携带 id 参数判断是插入还是更新protected void doPost(HttpServletRequest req, HttpServletResponse resp) { request.setCharacterEncoding(UTF-8); String action req.getParameter(action); if (add.equals(action)) { // 把表单数据封装成 NewsType 对象调用 DAO 插入 NewsType type new NewsType(); type.setName(req.getParameter(name)); newsTypeDao.save(type); resp.sendRedirect(type?actionlist); } else if (update.equals(action)) { // 必须有 id否则无法定位记录 int id Integer.parseInt(req.getParameter(id)); NewsType type newsTypeDao.findById(id); type.setName(req.getParameter(name)); newsTypeDao.update(type); resp.sendRedirect(type?actionlist); } }这里有一个非常重要的细节doPost 里第一行必须设置 request 编码否则表单提交的中文分类名到后端全是问号。还有 update 操作必须先按 id 查出原对象再把新名字 set 上去避免把其他字段误置为 null。源码里如果直接 new 对象只填 id 和 name那么旧记录的备注、排序字段就会丢。删除分类时要注意外键约束默认 RESTRICT 会导致删除失败。源码里如果没有先删除该分类下所有新闻再删分类的逻辑那后台点击删除按钮就会报 SQLIntegrityConstraintViolationException。建议改成逻辑删除——给 category 表加一个 status 字段删除时 UPDATE status 0新闻列表查询时只展示 status 1 的分类。这样既不破坏外键关系也不丢历史新闻。4.2 ImageUploadServlet 文件上传与存储路径的决定性细节图片上传是新闻发布系统里的高频功能稿件封面、正文插图都依赖它。这套项目里的 ImageUploadServlet 用的是 Servlet 3.0 的 Part 接口没有引入 commons-fileupload 外部库所以 web.xml 里对应 Servlet 声明需要配置 multipart 支持MultipartConfig( maxFileSize 5 * 1024 * 1024, // 单个文件最大 5MB maxRequestSize 10 * 1024 * 1024, // 整个请求最大 10MB fileSizeThreshold 1024 * 1024 // 超过 1MB 写入临时文件 ) public class ImageUploadServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) { Part part req.getPart(file); // 表单里文件域的 name String fileName extractFileName(part); // 保存到指定目录 String uploadPath getServletContext().getRealPath(/upload); part.write(uploadPath File.separator fileName); // 返回可访问的 URL 给前端 resp.getWriter().write(upload/ fileName); } }extractFileName 是封装的工具方法核心逻辑是截取 Part 头里 filename 的值。这里最大的坑是 getRealPath(/upload) 拿到的其实是项目部署目录在 IDEA 里跑的时候是 target 目录下的临时路径重启 Tomcat 后上传的图片就没了。我一般会改成配置文件里指定绝对路径比如 D:/news_upload/然后把这个路径映射成虚拟目录给前端访问。另一种做法是在 Tomcat 的 server.xml 里配 Context 的虚拟路径映射但那样会让项目换个环境就起不来不利于答辩演示。上传文件名的处理上源码里如果直接把用户原始文件名写到磁盘两个用户传同名图片就会互相覆盖。要在服务端做唯一化处理String ext fileName.substring(fileName.lastIndexOf(.)); String uuidName UUID.randomUUID().toString().replace(-, ) ext;用 UUID 重新命名后存盘数据库里只存 uuidName前端回显时拼上访问前缀就能显示。注意 ext 要控制后缀类型只允许 jpg、png、gif防止有人传 jsp 文件伪装成图片配合 Tomcat 目录执行权限问题就是拿站姿势。5. 避坑记录Tomcat 版本、字符集、SQL 与上传路径的四个坑5.1 Servlet 类编译报错或页面 404Tomcat 10 的 jakarta 命名空间现象项目导入 IDEA 后一堆 Servlet 相关的 import 全部飘红编译都过不去或者能编译但启动后访问页面直接 404Tomcat 日志里提示 ClassNotFoundException: javax.servlet.ServletException。原因Tomcat 10 开始把 Servlet API 的包名从 javax.servlet 迁移到了 jakarta.servlet传统 JavaWeb 项目用的是 javax.servlet.http.HttpServlet在 Tomcat 10 里根本找不到类。现在很多教程默认配 Tomcat 9 以下新手如果自己下载了最新版 Tomcat 10就会撞上这个坑。解决下载 Tomcat 9 重新配置 IDEA 的 Run Configuration把 Server 指向 Tomcat 9 的目录。如果想在 Tomcat 10 上跑就得把所有 import 批量替换成 jakarta.servlet工作量大且容易漏。5.2 中文全部变成问号请求编码与连接串编码双重缺失现象列表页标题和内容正常但后台新增新闻填了中文保存后数据库里存的是 ??前台显示也全是问号。原因两层问题叠加。第一层是请求没设置编码Tomcat 默认用 ISO-8859-1 解码 POST 表单中文天然乱码第二层是 JDBC 连接串没加 characterEncodingUTF-8即使请求编码对了数据插入 MySQL 时还是按错误字符集转换。解决写一个全局 Filter 设置 request 和 response 的编码public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { request.setCharacterEncoding(UTF-8); response.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); chain.doFilter(request, response); }JDBC 连接串完整写法是jdbc:mysql://localhost:3306/news?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiuseSSLfalse数据库连接串里没带 serverTimezone 的还会在 MySQL 8.0 下报时区错误这也是常见附加坑。5.3 分页第二页开始空白limit 偏移量写死现象首页第一页新闻正常显示点击“下一页”后 URL 变成了 ?actionlistpage2但页面还是第一页的数据或者直接空白。原因DAO 层的分页 SQL 把偏移量写死了比如 LIMIT 0, 5page 参数传进来完全没用另一种是页面上的上一页/下一页链接没有拼接 page 参数每次点击都从默认的 page1 开始。解决把页码当前值从 request 参数读取偏移量用 (page-1) * pageSize 计算且每一条分页链接上都要带当前页参数。调试时在控制台打印最终执行的 SQL一眼能看出 LIMIT 后面的值对不对。5.4 上传图片重启后丢失或裂图保存到了部署临时目录现象后台提交新闻带封面图当时显示正常但重启 Tomcat 后图片全部 404或者图片上传后立即回显刷新页面就裂图。原因getServletContext().getRealPath() 在 IDEA 开发模式下解析到的是 target/项目名/ 目录每次重新构建会清空图片自然被连带删除。解决把保存路径拎到项目外部比如 Windows 下固定为 D:/newsUpload/数据库里存相对路径前端使用独立的文件访问 URL。部署到生产环境时再根据服务器磁盘重新规划路径但代码里不要出现相对路径拼接。6. 部署与验证在 IDEA 里把整套 JavaWeb 新闻系统跑起来的关键三步拿到源码后最快的验证路径是先导数据库再配 Tomcat最后过一遍三个核心页面。先说数据库部分。新建一个 news 库导入项目里的 SQL 文件然后确认连接配置——看 db.properties 或 JDBC 工具类里的用户名密码是否和本地 MySQL 一致。这里要确认 MySQL 服务真的在运行用 Navicat 能连上不代表 IDEA 里能连上要看连接串的端口和编码参数。然后配置 IDEA 的 Run Configuration。Project Structure 里把 Artifact 设置为 Web Application Exploded点击右侧的坑位图标——Deployment 里选这个 ArtifactApplication context 填 /news。Server 选项卡里配好 Tomcat 9 的路径。系统里已经装 Tomcat 10 的记得先换掉这是复现成本最低的版本选择。启动后在浏览器里依次验证三个页面验证点访问地址通过标准前台首页http://localhost:8080/news/分类导航显示、新闻列表有数据、图片正常新闻详情首页点击任意新闻标题正文完整、评论列表加载后台管理/admin/login.jsp 或对应登录路径用户名密码登录后能进后台能新增新闻登录后第一件事是新增一条带中文标题和图片的新闻。如果这条新闻存进去是乱码、图片裂图、或者保存后列表看不到——恭喜你把第 5 章的坑全部踩了一遍。从那以后我接手任何 JavaWeb 项目第一件事永远是看它的 web.xml 版本和 Tomcat 版本第二件事是确认数据库连接串里的字符集参数这两个字段没问题项目基本就能跑通了。这个小习惯帮我避免过至少十次“代码明明没问题但就是跑不起来”的排查希望帮到你。本文还有配套的精品资源点击获取
返回列表