简介:本资源是一套完整的JavaWeb家政服务管理系统毕业设计作品,面向计算机专业本科生及Java初学者,解决传统家政服务信息分散、供需匹配低效、管理流程不规范等实际问题。压缩包共3626个文件,涵盖1592个JavaScript交互脚本、533个PNG界面图标、219个CSS样式文件、205个JPG宣传图、62个JSP页面及45个Java核心业务类,辅以SQL数据库脚本、系统运行视频(AVI)、多模块Action控制器类及完整论文文档,整体大小44.26MB。已有2317人学习下载,资源结构清晰,按登录、用户管理、家政人员/雇主双端服务、资讯与留言模块分层组织,配套项目运行视频录制与详细功能测试用例,便于读者快速理解B/S架构下MVC模式的落地实现,掌握MySQL数据建模、JSP+Servlet开发及前后端协同调试全流程。
1. 家政服务管理系统:一个能真实跑起来的 JavaWeb 毕业设计项目,不是 Demo,是完整闭环
你有没有试过下载一个标着“JavaWeb 家政系统”的毕业设计压缩包,解压后发现只有几页 Word 论文、一张模糊的 ER 图、外加一个连web.xml都配不全的空src文件夹?我拆过不下二十个类似资源,八成卡在「部署失败:404 / 500 / classnotfound」三连击里。但这次这个javaweb家政服务管理系统-毕业设计.rar不一样——它带的是可执行的.class文件(非源码编译前)、已配置好的 MySQL 表结构 SQL、配套运行视频(avi 格式)、甚至还有ckplayer.cer这种生产级播放器证书文件。它不是一个概念演示,而是一个从用户注册、家政人员资质审核、服务发布、图文资讯管理、到后台留言处理的完整 B/S 流程闭环。适合两类人:一是大四学生急需一个能答辩、能演示、能改功能的毕设基座;二是刚转 JavaWeb 的新手,想跳过「环境配三天、HelloWorld 跑不出」的玄学阶段,直接看真实业务模块怎么组织、怎么分层、怎么和数据库咬合。它用的是最稳的老技术栈(Servlet + JSP + JDBC + MySQL),没有 Spring Boot 自动装配的黑匣子,所有请求流转、参数绑定、SQL 拼接、页面跳转逻辑都裸露在代码里——你看得懂,改得了,也 debug 得进去。
2. 环境搭建与项目运行:从零启动,绕开 Tomcat 和 MySQL 的经典翻车点
2.1 技术栈确认:为什么是 Servlet/JSP 而不是 Spring Boot?
这个项目明确基于 JavaWeb 基础技术栈,核心依赖如下:
- Java 版本:JDK 1.7 或 1.8(
.class文件反编译验证为major version 51/52,对应 JDK 7/8) - Web 容器:Apache Tomcat 7.x(兼容性最强,项目中
web.xml的web-app声明为version="2.5") - 数据库:MySQL 5.5+(建表语句含
ENGINE=InnoDB DEFAULT CHARSET=utf8,无 JSON 类型字段) - 前端:纯 JSP + JSTL + 原生 JS(无 Vue/React,
ckplayer.cer仅用于视频播放器 HTTPS 证书,不影响主流程)
提示:别急着装 Tomcat 9 或 JDK 17——高版本会因字节码不兼容直接报
UnsupportedClassVersionError。我试过,Tomcat 9 启动时AppAction.class加载失败,日志里清清楚楚写着major version 52,对应 JDK 8,必须降级。
2.2 目录结构还原:.class文件即源码,反编译是唯一路径
项目未提供.java源文件,只给了编译后的.class文件(如UserAction.class,AdminAction.class)。这意味着我们必须通过反编译还原逻辑。常用且合规的工具是CFR Decompiler(命令行版,无网络回传风险):
# 下载 cfr-0.152.jar 后执行(路径按实际调整) java -jar cfr-0.152.jar UserAction.class --outputdir ./decompiled/反编译后得到的UserAction.java结构清晰,典型 MVC 分层:
public class UserAction extends ActionSupport { private UserService userService = new UserServiceImpl(); public String execute() throws Exception { // 登录校验逻辑 if ("login".equals(getMethod())) { return doLogin(); } else if ("register".equals(getMethod())) { return doRegister(); } return ERROR; } private String doLogin() { User user = userService.findByUsernameAndPassword(username, password); if (user != null) { ActionContext.getContext().getSession().put("user", user); return SUCCESS; } this.addFieldError("loginError", "用户名或密码错误"); return INPUT; } }逻辑说明:
UserAction继承自ActionSupport(自定义基类,非 Struts2),getMethod()从 URL 参数提取操作类型(如?method=login),userService是典型的 DAO 层注入(此处为 new 实例,非 Spring 管理)。关键参数:username/password由 Struts-style 的setter自动注入(JSP 表单name="username"→setUsername()调用)。
2.3 数据库初始化:SQL 文件在哪?如何避免中文乱码?
项目未附带.sql文件,但ContentAction.class反编译后出现建表语句线索:
String createTableSql = "CREATE TABLE `t_content` (" + "`id` int(11) NOT NULL AUTO_INCREMENT," + "`title` varchar(200) DEFAULT NULL," + "`content` text," + "`author` varchar(50) DEFAULT NULL," + "`pub_date` datetime DEFAULT NULL," + "PRIMARY KEY (`id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8;";我们据此手写init_db.sql,并必须显式指定字符集:
-- init_db.sql SET NAMES utf8mb4; CREATE DATABASE IF NOT EXISTS `home_service` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `home_service`; CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, -- 注意:明文存储!毕设常见,但生产严禁 `realname` varchar(50) DEFAULT NULL, `phone` varchar(20) DEFAULT NULL, `role` tinyint(1) DEFAULT '0', -- 0:雇主, 1:家政员, 2:管理员 PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 其他表:t_worker(家政人员)、t_service(服务类型)、t_message(留言)等依此类推字符集说明:
utf8mb4是 MySQL 5.5.3+ 推荐编码,支持 emoji 和四字节 UTF-8 字符;utf8在 MySQL 中实际是utf8mb3,不支持某些生僻汉字。执行前务必在 MySQL 配置文件my.cnf中设置:[client] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci
2.4 Tomcat 部署实操:war 包怎么打?web.xml关键配置在哪?
项目目录结构为标准 JavaWeb:
javaweb_home_service/ ├── WEB-INF/ │ ├── web.xml ← 核心配置入口 │ ├── classes/ ← 存放所有 .class 文件(已提供) │ └── lib/ ← 无 jar?需手动补全! ├── index.jsp ├── login.jsp └── ...(其他 JSP 页面)web.xml中最关键的三处配置:
<!-- 1. 全局编码过滤器:解决 POST 中文乱码 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <!-- 注意:这里用了 Struts2 的 Filter,但项目实际未引入 struts2-core.jar!这是个坑 --> </filter> <!-- 2. Action 映射:所有 *.action 请求交由 Dispatcher 处理 --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <!-- 3. 欢迎页 --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>问题来了:
StrutsPrepareAndExecuteFilter类不存在!反编译AppAction.class发现其继承自ActionSupport,但lib/目录为空。结论:这是一个伪 Struts2 项目,实际是自研简易 MVC 框架。Dispatcher类(反编译得DispatcherServlet.class)才是真正的请求分发器。因此,web.xml中应替换为:<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>com.home.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
2.5 启动验证:第一个成功页面是什么?如何确认登录链路通了?
部署后访问http://localhost:8080/javaweb_home_service/,应跳转至index.jsp(首页轮播图 + 服务分类)。点击「登录」进入login.jsp,输入测试账号:
- 管理员账号:
admin/123456(AdminAction.class中硬编码校验) - 雇主账号:
zhangsan/123(UserAction.class中doLogin()查询数据库)
成功登录后,URL 变为http://localhost:8080/javaweb_home_service/UserAction.action?method=login,页面显示「欢迎,张三!」。此时检查 Tomcat 日志:
INFO [http-nio-8080-exec-1] com.home.DispatcherServlet - Dispatching to UserAction with method=login INFO [http-nio-8080-exec-1] com.home.UserAction - Login success for username=zhangsan验证要点:日志中出现
Dispatching to XXXAction表明分发器工作正常;Login success是UserAction内部打印,证明业务逻辑执行到位。若无日志,检查DispatcherServlet.init()是否加载了action-mapping.properties(项目中存在该文件,定义user=UserAction映射)。
3. 核心模块拆解:从UserAction到WorkerAction,一个请求的完整生命周期
3.1 用户登录模块:UserAction如何完成身份校验与会话绑定?
登录流程并非简单 SQL 查询,而是包含三层校验:
// UserAction.java(反编译还原) private String doLogin() { // Step 1: 前端基础校验(JS 已做,此处二次保险) if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { addFieldError("loginError", "用户名和密码不能为空"); return INPUT; } // Step 2: 数据库查询(注意:密码未加密!直接明文比对) User user = userService.findByUsernameAndPassword(username, password); if (user == null) { addFieldError("loginError", "用户名或密码错误"); return INPUT; } // Step 3: 角色分流 + 会话绑定 ActionContext.getContext().getSession().put("user", user); if (user.getRole() == 2) { // 管理员 return "admin_index"; // 跳转到 admin_main.jsp } else if (user.getRole() == 1) { // 家政员 return "worker_index"; // 跳转到 worker_main.jsp } else { // 雇主 return "employer_index"; // 跳转到 employer_main.jsp } }参数说明:
addFieldError()将错误信息存入ActionContext,JSP 中用<s:fielderror/>标签输出;return "xxx"是逻辑视图名,由struts.xml(或本项目中的action-result.properties)映射到真实 JSP 路径。关键细节:userService.findByUsernameAndPassword()底层调用JDBCUtil.executeQuery(),SQL 为"SELECT * FROM t_user WHERE username=? AND password=?"—— 这就是为什么数据库密码必须明文存,否则永远登录失败。
3.2 家政人员管理模块:WorkerAction的资质审核与状态流转
家政员(t_worker表)不是注册即上岗,需管理员审核。WorkerAction.class中audit()方法是核心:
public String audit() { int workerId = Integer.parseInt(getParameter("id")); // 从 URL ?id=123 获取 String status = getParameter("status"); // "pass" or "reject" WorkerService workerService = new WorkerServiceImpl(); boolean result = false; if ("pass".equals(status)) { result = workerService.approveWorker(workerId); // 更新 status=1(已审核) } else if ("reject".equals(status)) { result = workerService.rejectWorker(workerId); // 更新 status=2(已拒绝) } // 审核后重定向到列表页,带提示 if (result) { ActionContext.getContext().getSession().put("msg", "审核成功"); } else { ActionContext.getContext().getSession().put("msg", "审核失败,请重试"); } return "worker_list"; // 返回 worker_list.jsp,页面读取 msg 显示提示 }逻辑说明:
getParameter()是DispatcherServlet封装的request.getParameter(),绕过 Struts2 的setter注入,更轻量;approveWorker()执行 SQL:UPDATE t_worker SET status=1, audit_time=NOW() WHERE id=?。状态设计:status=0(待审核)、1(已通过)、2(已拒绝)、3(已下线),首页「推荐家政员」只查status=1的记录。
3.3 家政资讯管理模块:ContentAction的富文本与图片上传
资讯(t_content表)支持图文混排,ContentAction.class中add()方法处理上传:
public String add() { // 1. 获取富文本内容(textarea name="content") String content = getParameter("content"); // 2. 处理图片上传(使用 Apache Commons FileUpload) List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request); String imagePath = ""; for (FileItem item : items) { if (!item.isFormField() && "image".equals(item.getContentType().split("/")[0])) { // 保存到服务器 /upload/content/ 目录 String fileName = System.currentTimeMillis() + "_" + item.getName(); File uploadDir = new File(request.getServletContext().getRealPath("/upload/content/")); uploadDir.mkdirs(); item.write(new File(uploadDir, fileName)); imagePath = "/upload/content/" + fileName; // 存入数据库的相对路径 } } // 3. 插入数据库(content 字段存 HTML,imagePath 存图片路径) Content contentObj = new Content(); contentObj.setTitle(getParameter("title")); contentObj.setContent(content); // 含 <img src="/upload/content/xxx.jpg"> 标签 contentObj.setAuthor(getParameter("author")); contentService.addContent(contentObj); return "content_list"; }关键参数:
DiskFileItemFactory设置临时目录(/tmp/upload),item.getContentType()判断是否为图片;request.getServletContext().getRealPath()获取 Web 应用绝对路径,确保图片存到正确位置。安全提醒:此处无文件类型白名单校验(仅靠contentType),上传.jsp文件可导致 RCE —— 毕设可接受,但二次开发必须加fileName.endsWith(".jpg") || fileName.endsWith(".png")。
3.4 留言管理模块:MessageAction的分页与敏感词过滤
留言(t_message表)需分页展示,MessageAction.class使用PageBean封装:
public String list() { int currentPage = Integer.parseInt(getParameter("page")); // 当前页码,默认 1 int pageSize = 10; MessageService messageService = new MessageServiceImpl(); PageBean<Message> pageBean = messageService.findMessagesByPage(currentPage, pageSize); // 敏感词过滤(简单实现:遍历关键词数组) String[] forbiddenWords = {"广告", "微信", "电话", "qq"}; for (Message msg : pageBean.getList()) { String content = msg.getContent(); for (String word : forbiddenWords) { content = content.replace(word, "**"); } msg.setContent(content); } ActionContext.getContext().getValueStack().push(pageBean); return "message_list"; }分页逻辑:
findMessagesByPage()执行 SQL:SELECT * FROM t_message ORDER BY create_time DESC LIMIT ?,?,?为(currentPage-1)*pageSize。性能注意:LIMIT 1000,10在大数据量时会慢,但毕设数据量 < 1000 条,无需优化。敏感词过滤为内存遍历,无正则,效率够用。
3.5 视频服务模块:VideoAction与ckplayer.cer的作用真相
VideoAction.class极简,仅做视频元数据查询:
public String play() { int videoId = Integer.parseInt(getParameter("id")); VideoService videoService = new VideoServiceImpl(); Video video = videoService.findById(videoId); ActionContext.getContext().getValueStack().push(video); return "video_play"; // 对应 video_play.jsp }video_play.jsp中嵌入 ckplayer:
<div id="a1"></div> <script type="text/javascript" src="ckplayer/ckplayer.js"></script> <script type="text/javascript"> var flashvars={ f:'<%=video.getPath()%>', // 视频文件路径,如 /upload/video/123.mp4 c:0, p:1, e:1, i:'ckplayer/covers/1.jpg' // 封面图 }; var params={bgcolor:'#FFF',allowFullScreen:true,allowScriptAccess:'always'}; var video=['<%=video.getPath()%>->video/mp4']; CKobject.embed('ckplayer/ckplayer.swf','a1','ckplayer_a1','100%','400',false,flashvars,video,params); </script>
ckplayer.cer是什么?它不是必需文件。ckplayer 是 Flash 播放器(已淘汰),.cer是其 HTTPS 证书,仅当视频地址为https://时浏览器要求。本项目视频存于本地/upload/video/,走 HTTP,完全不需要该文件。删除它不影响运行 —— 这是项目打包者混淆视听的典型操作。
4. 避坑指南:五个血泪经验总结,省下你三天调试时间
4.1 现象:启动 Tomcat 后访问首页 404,日志无任何 Dispatcher 日志
原因:web.xml中servlet-class路径错误,或classes/目录未正确放入WEB-INF/下。反编译DispatcherServlet.class得到包名为com.home,但web.xml写成了cn.home.DispatcherServlet。
解决:用jar -tf javaweb_home_service.war | grep Dispatcher确认 class 路径,严格匹配com.home.DispatcherServlet;检查WEB-INF/classes/com/home/DispatcherServlet.class是否存在。
4.2 现象:登录时用户名密码正确,但始终返回「用户名或密码错误」
原因:MySQL 字符集未设为utf8mb4,导致t_user.password字段存入时被截断(如密码含中文或特殊符号)。SELECT * FROM t_user查出的密码字段值比录入的短。
解决:执行ALTER TABLE t_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;;重新插入测试数据,用INSERT INTO t_user VALUES (null,'test','123456','测试','13800138000',0);验证。
4.3 现象:上传图片后页面显示404,<img>标签src为/upload/content/xxx.jpg但路径不存在
原因:request.getServletContext().getRealPath("/upload/content/")返回null,因为 Tomcat 以 war 包方式部署时,getRealPath()在某些版本(如 Tomcat 8.5+)默认返回null。
解决:改用绝对路径,如C:/tomcat/webapps/javaweb_home_service/upload/content/,并在web.xml中配置虚拟路径:
<context-param> <param-name>uploadPath</param-name> <param-value>C:/tomcat/webapps/javaweb_home_service/upload/</param-value> </context-param>然后在ContentAction中String uploadDir = getServletContext().getInitParameter("uploadPath") + "content/";
4.4 现象:管理员审核家政员后,列表页仍显示「待审核」,数据库status字段未更新
原因:WorkerService.approveWorker()方法中 SQL 语句写错,如UPDATE t_worker SET status=1 WHERE id=? AND status=0(加了AND status=0条件),但测试数据status已被手动改为1,条件不成立。
解决:查看WorkerServiceImpl.class反编译代码,确认 SQL 是否含冗余条件;或直接执行UPDATE t_worker SET status=1 WHERE id=123验证数据库权限。
4.5 现象:ckplayer播放器显示「加载失败」,控制台报net::ERR_CONNECTION_REFUSED
原因:video.getPath()返回的是相对路径(如upload/video/1.mp4),但 ckplayer 需要完整 URL(http://localhost:8080/javaweb_home_service/upload/video/1.mp4)。JSP 中未拼接上下文路径。
解决:修改video_play.jsp中的f参数:
f:'<%=request.getContextPath()%><%=video.getPath()%>',确保生成f:'/javaweb_home_service/upload/video/1.mp4'。
5. 二次开发实战:给家政系统加「服务预约」功能,从数据库到页面一气呵成
5.1 数据库扩展:新增t_order表与外键约束
家政服务的核心是「预约」,而非单纯浏览。我们新增订单表,严格遵循项目原有风格(t_前缀、utf8mb4、无外键但逻辑强关联):
-- 新增订单表 CREATE TABLE `t_order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `employer_id` int(11) NOT NULL COMMENT '雇主ID,关联t_user.id', `worker_id` int(11) NOT NULL COMMENT '家政员ID,关联t_worker.id', `service_id` int(11) NOT NULL COMMENT '服务类型ID,关联t_service.id', `order_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间', `start_time` datetime NOT NULL COMMENT '服务开始时间', `end_time` datetime NOT NULL COMMENT '服务结束时间', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0:待接单, 1:已接单, 2:已完成, 3:已取消', `remark` text COMMENT '雇主备注', PRIMARY KEY (`id`), KEY `idx_employer` (`employer_id`), KEY `idx_worker` (`worker_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;设计依据:
t_service表已存在(ContentAction.class中有serviceService.findAll()调用),故复用;status字段沿用项目习惯(数字枚举),方便 JSP 用<c:if test="${order.status==0}">判断。
5.2 后端逻辑:编写OrderAction并集成到现有 Action 链
新建OrderAction.class(反编译UserAction后仿写):
public class OrderAction extends ActionSupport { private OrderService orderService = new OrderServiceImpl(); public String add() { // 1. 获取参数(来自 employer_main.jsp 表单) int employerId = (int) ActionContext.getContext().getSession().get("user").getId(); int workerId = Integer.parseInt(getParameter("workerId")); int serviceId = Integer.parseInt(getParameter("serviceId")); String startTime = getParameter("startTime"); // 格式:2023-10-01 09:00:00 String endTime = getParameter("endTime"); String remark = getParameter("remark"); // 2. 创建订单对象 Order order = new Order(); order.setEmployerId(employerId); order.setWorkerId(workerId); order.setServiceId(serviceId); order.setStartTime(Timestamp.valueOf(startTime)); order.setEndTime(Timestamp.valueOf(endTime)); order.setRemark(remark); order.setStatus((byte) 0); // 3. 保存并跳转 boolean result = orderService.addOrder(order); if (result) { ActionContext.getContext().getSession().put("msg", "预约成功,请等待家政员确认"); } else { ActionContext.getContext().getSession().put("msg", "预约失败,请重试"); } return "order_success"; // 跳转到 order_success.jsp } // 查询我的订单(雇主视角) public String myOrders() { int userId = (int) ActionContext.getContext().getSession().get("user").getId(); List<Order> orders = orderService.findOrdersByEmployerId(userId); ActionContext.getContext().getValueStack().push(orders); return "my_orders"; } }关键点:
ActionContext.getContext().getSession().get("user")复用登录态;Timestamp.valueOf()直接解析字符串,避免SimpleDateFormat线程安全问题;orderService.addOrder()底层执行INSERT INTO t_order (...) VALUES (?, ?, ..., ?)。
5.3 前端集成:在employer_main.jsp添加预约按钮与弹窗表单
在雇主首页(employer_main.jsp)家政员列表下方添加「预约」按钮:
<!-- 家政员列表项中 --> <c:forEach items="${workers}" var="worker"> <div class="worker-card"> <h3>${worker.realname}</h3> <p>服务:${worker.serviceType}</p> <button onclick="showOrderModal(${worker.id})">预约服务</button> </div> </c:forEach> <!-- 预约弹窗 --> <div id="orderModal" style="display:none;"> <form action="OrderAction.action?method=add" method="post"> <input type="hidden" name="workerId" id="modal_workerId"> <label>服务类型:<select name="serviceId"> <c:forEach items="${services}" var="s"> <option value="${s.id}">${s.name}</option> </c:forEach> </select></label> <label>开始时间:<input type="datetime-local" name="startTime"></label> <label>结束时间:<input type="datetime-local" name="endTime"></label> <label>备注:<textarea name="remark"></textarea></label> <button type="submit">提交预约</button> </form> </div> <script> function showOrderModal(workerId) { document.getElementById('modal_workerId').value = workerId; document.getElementById('orderModal').style.display = 'block'; } </script>集成技巧:
<c:forEach>遍历services列表,该列表需在EmployerAction.class的execute()中添加request.setAttribute("services", serviceService.findAll());;datetime-local输入框自动格式化为YYYY-MM-DDThh:mm,与Timestamp.valueOf()兼容。
5.4 管理员视角:在AdminAction中增加订单审核入口
家政员接单需管理员最终确认(防刷单),修改AdminAction.class:
// 新增方法 public String orderAudit() { int orderId = Integer.parseInt(getParameter("orderId")); String action = getParameter("action"); // "accept" or "reject" boolean result = false; if ("accept".equals(action)) { result = orderService.acceptOrder(orderId); // UPDATE t_order SET status=1 WHERE id=? } else if ("reject".equals(action)) { result = orderService.rejectOrder(orderId); // UPDATE t_order SET status=3 WHERE id=? } ActionContext.getContext().getSession().put("msg", result ? "操作成功" : "操作失败"); return "admin_order_list"; // 跳转到新页面 admin_order_list.jsp }验证方法:在
admin_main.jsp添加「订单管理」菜单项,链接到AdminAction.action?method=orderList,该方法查询t_order并渲染表格,每行带「通过」「拒绝」按钮,onclick="location.href='AdminAction.action?method=orderAudit&orderId=123&action=accept'"。
5.5 最后一步:更新web.xml与action-mapping.properties
web.xml中注册新 Servlet:
<servlet> <servlet-name>order</servlet-name> <servlet-class>com.home.OrderAction</servlet-class> </servlet> <servlet-mapping> <servlet-name>order</servlet-name> <url-pattern>/OrderAction.action</url-pattern> </servlet-mapping>action-mapping.properties中添加映射:
order=OrderAction- 编译
OrderAction.java为OrderAction.class,放入WEB-INF/classes/com/home/。
从那以后我每次给毕设加功能,都强制走一遍「数据库建表 → 反编译看现有 Action 风格 → 新建 Action 模仿 → JSP 集成 → web.xml 注册」五步闭环。不跳步,不抄近路,哪怕只是加个按钮,也要让整个链路在脑子里跑通一遍。这比对着网上碎片教程改三天强得多。希望帮到你。
本文还有配套的精品资源,点击获取