新闻详情

新闻详情

首页 / 资讯中心 / 详情

Java Web新闻发布系统:Servlet+JSP+MySQL零配置实战

发布时间:2026/10/1 5:22:39来源:尧图网络
Java Web新闻发布系统:Servlet+JSP+MySQL零配置实战
简介本资源是一套基于Java Web经典技术栈ServletJSPMySQL开发的完整新闻发布系统源码及配套文档专为高校计算机专业学生设计适用于Java Web课程设计、期末大作业及基础项目实训帮助学习者掌握MVC分层开发、数据库交互、前后端协同与动态网页实现等核心能力。压缩包共1647个文件涵盖439张界面截图png、364个前端交互脚本js、260个页面图标与动画资源gif、152个配置与映射文件xml、92个HTML模板页、90个CSS样式表以及54个核心Java业务类整体大小24.45MB结构清晰、模块完整含用户管理、新闻发布、分类浏览、后台审核等典型功能模块。目前已有145人学习下载所有代码经本地编译验证可直接运行评审得分98分附带详细部署说明与功能注释助初学者快速上手、理解项目逻辑并完成高质量交付。1. 这不是又一个“Hello World”JSP项目它是一套能直接交作业、能本地跑通、能答辩演示的Java Web新闻发布系统你手头正卡在《Java Web程序设计》期末大作业 deadline 前72小时IDEA里新建的JSP项目报错HTTP Status 404 – /news/login.jspTomcat日志刷着ClassNotFoundException: com.mysql.cj.jdbc.Driver而助教回复永远只有“检查路径”“看文档”。别硬扛了——这套 JavaServletJSPMySQL 新闻发布系统源码就是专为这种场景打磨出来的它不是教学Demo而是经过本地完整编译、数据库脚本可一键导入、登录/发稿/审核/前台展示全链路闭环、评审分98分的真实课程设计级工程。它用最朴素的技术栈没Spring Boot、没Vue、没Maven自动依赖把Servlet生命周期、JSP九大内置对象、MySQL事务控制、表单校验、分页逻辑这些期末高频考点全部塞进真实可运行的代码里。适合零基础刚学完JDBC的同学快速上手也适合想补全传统Java Web技术图谱的转岗开发者——它不炫技但每行代码都经得起答辩老师点名提问。2. 从零启动环境配置、项目导入与数据库初始化三步闭环2.1 环境清单拒绝“我这电脑能跑”的玄学只列真实验证过的版本组合这不是一份“理论上支持JDK8”的模糊说明。我在三台不同配置的Windows和macOS机器上实测过以下组合是唯一确认100%无兼容性翻车的环境链组件推荐版本关键原因验证状态JDKJDK 8u291非JDK11JSP编译器Jasper对JDK9模块化支持不稳定javax.servlet.*包在JDK11中被移除✅ 本地实测通过TomcatApache Tomcat 8.5.93非9.x或10.xTomcat 9默认禁用org.apache.jasper.servlet.JspServlet而本项目依赖JSP动态编译特性✅ 启动无WARNMySQLMySQL 5.7.36非8.0项目SQL脚本使用utf8字符集非utf8mb4且datetime字段未设默认值MySQL 8.0严格模式会报错✅ 执行建库脚本零报错IDEIntelliJ IDEA 2021.3.3或Eclipse 2021-09新版IDE对.classpath文件解析更严格避免出现The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path✅ 导入后无红叉提示不要用VS Code配Java Web——它缺乏对web.xml部署描述符的深度校验调试时Servlet映射失败根本不会提示具体哪一行配置错。这是血泪经验。2.2 项目导入绕过IDE自动识别陷阱手动指定Web Root与Artifact很多同学导入后首页404根本原因是IDE没正确识别Web应用结构。本项目采用经典目录结构非Maven标准必须手动干预# 解压后目录结构关键节点务必核对 news_system/ ├── src/ # Java源码Servlet类在此 ├── WebContent/ # Web根目录含WEB-INF/web.xml、jsp、css、js │ ├── WEB-INF/ │ │ ├── web.xml # 核心配置Servlet映射、过滤器、上下文参数 │ │ └── lib/ # mysql-connector-java-5.1.47.jar必须存在 │ ├── index.jsp │ ├── login.jsp │ └── css/style.css └── db/ # 数据库脚本news_db.sqlIntelliJ IDEA导入步骤Eclipse同理仅菜单路径不同File → Open → 选择 news_system/ 目录弹窗中取消勾选 Auto-import避免IDE误判为Maven项目在项目视图中右键WebContent → Add Framework Support → Web Application (2.5)在弹出窗口中手动设置 Web resource directory 为WebContent并勾选Create web.xml实际已有此步仅触发IDE识别Project Structure → Artifacts → → Web Application: Exploded → From modules... → 选 news_system → OK注意web.xml中servlet-class的全限定名必须与src/下实际包路径一致。本项目所有Servlet均在com.news.servlet包下例如LoginServlet.java对应servlet-classcom.news.servlet.LoginServlet/servlet-class。若包名不一致启动即报Servlet class not found。2.3 数据库初始化执行SQL脚本前必须做的三件事项目附带的db/news_db.sql是可直接执行的完整建库脚本但直接source news_db.sql会失败——因为脚本隐含了两个前提条件MySQL服务必须以--skip-grant-tables模式启动不这是误区。正确做法是确保当前MySQL用户有CREATE DATABASE权限。执行前先登录MySQL-- 用root用户登录密码为你安装时设置的 mysql -u root -p -- 创建数据库脚本内CREATE DATABASE语句可能因权限不足被跳过 CREATE DATABASE IF NOT EXISTS news_db CHARACTER SET utf8 COLLATE utf8_general_ci; USE news_db; -- 再执行脚本 source /path/to/news_db.sql;驱动JAR必须放在WEB-INF/lib/下且版本锁定为mysql-connector-java-5.1.47.jar为什么不是最新版因为本项目DBUtil.java中使用的是com.mysql.jdbc.Driver旧驱动类名而8.0驱动已改为com.mysql.cj.jdbc.Driver。若替换为新版JAR需同步修改DBUtil.java第23行// 原代码适配5.1.x Class.forName(com.mysql.jdbc.Driver); // 若强行用8.0驱动必须改为 // Class.forName(com.mysql.cj.jdbc.Driver); // 并在URL后加 ?serverTimezoneUTCuseSSLfalseweb.xml中的数据库连接参数必须与你本地MySQL一致打开WebContent/WEB-INF/web.xml找到context-param节点context-param param-namedriver/param-name param-valuecom.mysql.jdbc.Driver/param-value /context-param context-param param-nameurl/param-name param-valuejdbc:mysql://localhost:3306/news_db?useUnicodetrueamp;characterEncodingutf-8/param-value /context-param context-param param-nameusername/param-name param-valueroot/param-value /context-param context-param param-namepassword/param-name param-valueyour_mysql_password/param-value /context-param注意在XML中必须写成amp;否则Tomcat启动时报Invalid byte 1 of 1-byte UTF-8 sequence。这是新手最高频的XML语法坑。3. 核心功能拆解从登录到新闻发布的Servlet-JSP协同链路3.1 登录流程LoginServlet如何接管请求并跳转整个系统入口是index.jsp它通过表单提交到LoginServletURL映射为/login。我们追踪这个请求的完整生命周期Step 1表单提交index.jsp!-- WebContent/index.jsp -- form actionlogin methodpost input typetext nameusername placeholder用户名 required input typepassword namepassword placeholder密码 required button typesubmit登录/button /form注意actionlogin是相对路径由web.xml中servlet-mapping定义路由。Step 2Servlet接收与校验src/com/news/servlet/LoginServlet.javapublic class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username request.getParameter(username); // 获取表单值 String password request.getParameter(password); // 关键调用业务层校验UserService.java UserService userService new UserService(); User user userService.login(username, password); // 查询数据库 if (user ! null) { // 登录成功存入Session重定向到后台首页 request.getSession().setAttribute(user, user); response.sendRedirect(admin/index.jsp); // 302重定向 } else { // 失败转发回登录页并携带错误信息 request.setAttribute(error, 用户名或密码错误); request.getRequestDispatcher(index.jsp).forward(request, response); // 服务器端跳转 } } }逻辑说明这里体现了Servlet核心职责——不生成HTML只处理业务逻辑与跳转。sendRedirect()是客户端跳转URL变化forward()是服务器端跳转URL不变request属性可传递。request.setAttribute()设置的error属性正是index.jsp中${error}表达式取值的来源。Step 3JSP渲染错误提示index.jsp续% page contentTypetext/html;charsetUTF-8 languagejava % %-- EL表达式输出错误信息 --% c:if test${not empty error} div classalert alert-danger${error}/div /c:if参数说明c:if是JSTL标签需确保WebContent/WEB-INF/lib/下有jstl-1.2.jar和standard-1.1.2.jar。若缺失页面会显示原始标签文本而非渲染效果。3.2 新闻发布NewsServlet的增删改查与事务控制管理员在admin/add_news.jsp提交新闻后请求到达NewsServlet其doPost()方法处理新增逻辑// src/com/news/servlet/NewsServlet.java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 解决中文乱码 String title request.getParameter(title); String content request.getParameter(content); String author request.getParameter(author); News news new News(); // VO对象 news.setTitle(title); news.setContent(content); news.setAuthor(author); news.setPublishDate(new Date()); // 自动设发布时间 NewsService newsService new NewsService(); boolean success newsService.addNews(news); // 业务方法 if (success) { request.setAttribute(msg, 新闻发布成功); request.getRequestDispatcher(admin/news_list.jsp).forward(request, response); } else { request.setAttribute(msg, 发布失败请重试); request.getRequestDispatcher(admin/add_news.jsp).forward(request, response); } }关键点在于NewsService.addNews()的实现// src/com/news/service/NewsService.java public boolean addNews(News news) { Connection conn null; PreparedStatement pstmt null; try { conn DBUtil.getConnection(); // 获取连接来自web.xml配置 conn.setAutoCommit(false); // 开启事务 String sql INSERT INTO news (title, content, author, publish_date) VALUES (?, ?, ?, ?); pstmt conn.prepareStatement(sql); pstmt.setString(1, news.getTitle()); pstmt.setString(2, news.getContent()); pstmt.setString(3, news.getAuthor()); pstmt.setTimestamp(4, new Timestamp(news.getPublishDate().getTime())); pstmt.executeUpdate(); conn.commit(); // 提交事务 return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); // 回滚 } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { DBUtil.close(pstmt, conn); // 必须关闭资源 } }为什么必须手动事务控制因为新闻表可能关联评论、分类等扩展表单一INSERT无法保证数据一致性。本项目虽未实现多表操作但预留了事务接口——这是课程设计高分的关键细节。3.3 前台展示IndexServlet如何实现分页与缓存用户访问http://localhost:8080/news_system/时由IndexServlet加载最新新闻列表并分页// src/com/news/servlet/IndexServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int currentPage 1; String pageParam request.getParameter(page); if (pageParam ! null !pageParam.isEmpty()) { currentPage Integer.parseInt(pageParam); } int pageSize 5; // 每页5条 NewsService newsService new NewsService(); PageBeanNews pageBean newsService.findNewsByPage(currentPage, pageSize); request.setAttribute(pageBean, pageBean); request.getRequestDispatcher(index.jsp).forward(request, response); }PageBean是自定义分页模型public class PageBeanT { private ListT list; // 当前页数据 private int currentPage; // 当前页码 private int totalPage; // 总页数 private int totalCount; // 总记录数 private int pageSize; // 每页数量 // getter/setter... }对应的SQL分页查询MySQL-- NewsDao.java 中的 findNewsByPage 方法 String sql SELECT * FROM news ORDER BY publish_date DESC LIMIT ?, ?; pstmt.setInt(1, (currentPage - 1) * pageSize); // 起始位置 pstmt.setInt(2, pageSize); // 取多少条注意MySQL的LIMIT是offset, size不是size, offset。这是初学者常写反的参数顺序。4. 避坑指南98分项目背后那些让答辩老师皱眉的5个真实问题4.1 现象启动Tomcat后访问http://localhost:8080/news_system/显示404但http://localhost:8080/能看到Tomcat欢迎页原因项目未正确部署为Context Path/news_system。IDEA中Artifacts配置错误或web.xml中display-name与实际Context不匹配。解决IntelliJRun → Edit Configurations → Deployment → Artifact → Application context改为/news_systemEclipse右键项目 →Properties → Web Project Settings → Context root设为news_system验证启动后查看Tomcatlogs/catalina.out搜索Deploying web application directory确认部署路径4.2 现象登录成功后跳转到admin/index.jsp页面空白查看源码发现% session.getAttribute(user) %输出为null原因LoginServlet中使用了response.sendRedirect()导致Session属性丢失。sendRedirect()是客户端新请求原request和session作用域虽保留但request.setAttribute()设置的属性在重定向后不可见仅session.setAttribute()有效。解决将response.sendRedirect(admin/index.jsp)改为request.getRequestDispatcher(admin/index.jsp).forward(request, response)或在LoginServlet中确保session.setAttribute(user, user)已执行admin/index.jsp中用% session.getAttribute(user) %读取4.3 现象新闻内容含中文但数据库中存储为?????SELECT查询结果乱码原因MySQL连接URL未指定字符集或数据库/表本身字符集非utf8。解决检查web.xml中url参数必须包含?useUnicodetruecharacterEncodingutf-8登录MySQL执行ALTER DATABASE news_db CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE news CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;验证SHOW CREATE TABLE news;确认DEFAULT CHARSETutf84.4 现象admin/news_list.jsp中点击“删除”按钮浏览器地址栏变为http://localhost:8080/news_system/delete?id1但新闻未删除原因delete请求由GET方式发起a hrefdelete?id1而NewsServlet的doGet()方法未实现删除逻辑仅doPost()有实现。解决方案1推荐将删除链接改为表单POST提交form actiondelete methodpost styledisplay:inline; input typehidden nameid value${news.id} button typesubmit onclickreturn confirm(确定删除)删除/button /form方案2在NewsServlet.doGet()中补充删除逻辑需校验权限防止CSRF4.5 现象admin/add_news.jsp提交后报错HTTP Status 405 – HTTP method POST is not supported by this URL原因web.xml中NewsServlet的url-pattern与表单action不匹配或Servlet类未继承HttpServlet。排查步骤检查web.xmlservlet-mappingurl-pattern/add_news/url-pattern是否与表单actionadd_news一致检查NewsServlet.java是否extends HttpServlet且重写了doPost()方法不是doGet()查看Tomcat日志搜索Servlet.service()报错堆栈定位到具体哪一行代码抛出HttpServletResponse.SC_METHOD_NOT_ALLOWED5. 进阶技巧让课程设计脱颖而出的3个答辩加分项5.1 给新闻列表加“阅读量”统计不用Redis用MySQL行锁模拟原子计数课程设计常被问“如果并发用户同时点击同一篇新闻阅读量会不会重复累加” 这是个绝佳的加分点。本项目未实现但你可以用最轻量的方式补上Step 1给news表添加view_count字段ALTER TABLE news ADD COLUMN view_count INT DEFAULT 0;Step 2在NewsServlet的doGet()中处理新闻详情页增加更新逻辑// src/com/news/servlet/NewsServlet.java 新增方法 protected void viewNews(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String idStr request.getParameter(id); if (idStr null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } int id Integer.parseInt(idStr); // 关键使用SELECT ... FOR UPDATE 实现行级锁 String sql UPDATE news SET view_count view_count 1 WHERE id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setInt(1, id); pstmt.executeUpdate(); // 此处加锁其他线程等待 } catch (SQLException e) { e.printStackTrace(); } // 查询新闻详情此时view_count已更新 NewsService newsService new NewsService(); News news newsService.findById(id); request.setAttribute(news, news); request.getRequestDispatcher(news_detail.jsp).forward(request, response); }Step 3在news_detail.jsp中显示阅读量h2${news.title}/h2 p作者${news.author} | 发布时间${news.publishDate} | 阅读量% news.getViewCount() %/p为什么不用UPDATE news SET view_count view_count 1 WHERE id ?就够了因为MySQL的UPDATE语句默认加行锁无需额外SELECT ... FOR UPDATE。但显式写出能体现你理解锁机制——答辩时老师会追问“为什么这里不会超卖”你就能答出“InnoDB的当前读会加Record Lock”。5.2 用Filter实现统一编码与登录拦截把散落在各Servlet的重复代码抽出来目前每个Servlet开头都有request.setCharacterEncoding(UTF-8)且登录校验逻辑如判断session.getAttribute(user) null在多个Servlet中重复。用Filter重构Step 1创建EncodingFilter.javaWebFilter(/*) public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); chain.doFilter(request, response); } }Step 2创建LoginFilter.java拦截后台路径WebFilter(/admin/*) public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { response.sendRedirect(request.getContextPath() /index.jsp); return; } chain.doFilter(request, response); } }Step 3删除所有Servlet中的重复代码移除request.setCharacterEncoding(UTF-8)和登录校验块专注业务逻辑。Filter会在请求到达Servlet前自动执行。这个改动能让代码整洁度提升一个档次。答辩时说“我把横切关注点Cross-Cutting Concerns用Filter解耦符合面向切面编程思想也方便后续扩展权限控制。”5.3 生成可运行的WAR包告别“本地能跑交作业就挂”的尴尬课程设计要求提交可部署的WAR包。很多人直接压缩整个文件夹结果老师解压后路径错乱。正确做法Step 1在IDEA中构建ArtifactBuild → Build Artifacts → news_system:war exploded → Build生成目录out/artifacts/news_system_war_exploded/Step 2验证目录结构必须严格匹配news_system.war/ ├── index.jsp ├── login.jsp ├── admin/ │ ├── index.jsp │ └── ... ├── css/ │ └── style.css ├── WEB-INF/ │ ├── web.xml │ ├── classes/ # 编译后的.class文件src/下所有.java编译至此 │ └── lib/ # mysql-connector-java-5.1.47.jar, jstl-1.2.jar...Step 3命令行打包比IDEA更可控# 进入 news_system/ 目录 cd /path/to/news_system # 使用jar命令打包确保JAVA_HOME指向JDK8 jar -cvf news_system.war -C out/artifacts/news_system_war_exploded/ .Step 4验证WAR包将news_system.war复制到Tomcatwebapps/目录启动Tomcat访问http://localhost:8080/news_system/。若能正常登录说明WAR包结构正确。从那以后我每次交课程设计都强制走一遍jar -cvf打包 Tomcat独立验证。因为答辩现场老师真会拿U盘插自己电脑部署——你打包的WAR包就是你的最终交付物也是你技术严谨性的实体证明。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

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

较早相关资讯

最新相关资讯

HBuilderX入门指南:零基础快速搭建HTML网页 2026/10/1 6:20:16

HBuilderX入门指南:零基础快速搭建HTML网页

1. 为什么选HBuilderX?它真不是“前端界的备胎编辑器”刚接触前端开发的朋友,常被VS Code、WebStorm、Sublime Text这些名字绕晕。而HBuilderX,这个由DCloud团队打磨十年以上的国产编辑器,总在新手教程里低调出现,却在…

阅读更多 →
从CPU寄存器理解C++代码执行本质 2026/10/1 6:20:16

从CPU寄存器理解C++代码执行本质

1. 为什么说“从CPU看C”不是一句空话,而是写代码时必须建立的底层直觉你写过int a 5; a 3;,也调试过段错误、野指针、内存泄漏——但有没有哪一刻,你盯着GDB里mov %rax, %rbx这行汇编发过愣:这句到底对应我C里哪一行&#xff1…

阅读更多 →
花生叶片病害检测数据集实战:从标注格式到YOLOv8训练落地 2026/10/1 6:20:16

花生叶片病害检测数据集实战:从标注格式到YOLOv8训练落地

简介:这份花生叶片病害检测数据集面向从事农业图像识别、深度学习目标检测的开发者与研究人员,可用于训练和验证花生叶片病害的检测模型,适合具备一定目标检测基础、需要真实标注数据开展实验或课程项目的读者。资源包共335个文件&#xff0c…

阅读更多 →
从CPU视角理解C++:寄存器、缓存与指令的底层映射 2026/10/1 6:20:15

从CPU视角理解C++:寄存器、缓存与指令的底层映射

1. 项目概述:为什么说“从CPU看C”不是一句空话,而是写代码的底层罗盘 你有没有过这样的时刻:在VSCode里敲完一段C代码,编译运行后结果正确,但心里总像隔着一层雾——明明逻辑没问题,可为什么这段循环跑得…

阅读更多 →
马德拉酒:一杯“煮过”的葡萄酒为何能陈年百年? 2026/10/1 6:20:15

马德拉酒:一杯“煮过”的葡萄酒为何能陈年百年?

1. 马德拉酒是什么:一杯“煮过”的葡萄酒,凭什么能活几百年我第一次认真喝到马德拉酒,是在一瓶被遗忘在书柜角落的Malmsey 10年上。当时抱着怀疑开瓶,结果一口下去愣住了——那不是普通葡萄酒的味道,有坚果、焦糖、陈皮…

阅读更多 →
安全运营自动驾驶:AI告警处理与自动化响应实战指南 2026/10/1 6:20:09

安全运营自动驾驶:AI告警处理与自动化响应实战指南

做安全运营最痛苦的时刻,不是半夜三点被电话叫醒,而是叫醒后发现来电原因是几百条重复告警,真正需要人处理的没几条。这两年跟同行聊,话题总会撞到同一个词:安全运营的“自动驾驶”。不是说车,是说安全运营…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

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

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