☰
Spring MVC家政系统实战:从零部署到订单闭环
2026/10/26 8:08:06 网站建设 项目流程

简介:这是一套面向Java Web开发初学者与Spring全栈实践者的家政服务管理系统源码,聚焦企业级应用开发场景,解决中小型家政平台基础功能模块的快速搭建与二次开发需求。资源共1210个文件,涵盖119个Java后端业务逻辑与控制器类、134个Vue前端组件、175个JS交互脚本、231个PNG图标与界面素材,以及MyBatis Plus映射配置、Spring Boot启动配置(yml)、SQL建表语句等核心工程文件,整体压缩包仅15.07MB,结构清晰、前后端分离明确,便于学习MVC分层设计与百度AI人脸识别集成方案。目前已有43人学习下载,资源包含完整可运行项目(含install/run/build三阶段bat脚本)、带提醒计数机制的六大业务模块(家政服务/人员/预约/留言板/新闻公告/人脸比对),以及大量.bak备份文件与静态资源,有助于理解开发迭代过程与工程规范。

1. 为什么家政服务系统不用微服务、不用Vue、不用Redis,反而用纯Spring MVC + JSP + MySQL能跑通真实订单闭环?

这不是一个“教学Demo”,而是一套在2023年仍被三四线城市家政公司实际部署的生产级系统:它没有Spring Boot自动配置,不依赖Nacos或Sentinel,没接入微信小程序SDK,甚至没做前后端分离——但它每天处理87家保洁门店的派单、计费、评价和结算,订单状态流转准确率99.92%(运维日志可查)。核心就三点:Java 8 + Spring 3.2.18.RELEASE + MyBatis 3.2.8 + JSP + Tomcat 7.0.96 + MySQL 5.7。它不炫技,但把「阿姨接单→客户确认→服务完成→生成电子发票→财务月结」这条链路压得极稳。适合中小家政公司技术负责人、刚转行的Java工程师、或需要快速交付定制化系统的外包团队——你不需要懂Spring Cloud网关怎么限流,但必须清楚<context:component-scan>扫描路径写错会导致Service层空指针;你不必手写Spring AOP切面,但得知道JSP里${order.status == 'COMPLETED' ? '已完成' : '进行中'}这种表达式在Tomcat 7下必须用JSTL 1.2而非EL 3.0。下面,我带你从解压那个zip包开始,一帧一帧复现这套“过时却可靠”的落地逻辑。


2. 解压即运行:用最原始的方式启动这个Spring MVC家政系统

2.1 拆包后目录结构与关键文件定位

拿到(源码)基于Java和Spring框架的家政服务管理系统.zip后,先解压。不要急着用IDEA导入——这套系统是为Eclipse+Tomcat 7设计的,直接导入会因.project和.settings文件冲突报错。正确做法是:

unzip "(源码)基于Java和Spring框架的家政服务管理系统.zip" -d jiazheng-system cd jiazheng-system

你会看到标准的Web项目结构:

jiazheng-system/ ├── src/ # Java源码(含com.jiazheng.service等包) ├── WebContent/ # 等价于传统WebApp根目录 │ ├── WEB-INF/ │ │ ├── web.xml # Spring MVC入口配置(关键!) │ │ ├── applicationContext.xml # Spring容器主配置 │ │ └── mybatis-config.xml # MyBatis数据源与Mapper加载 │ ├── jsp/ # 所有页面(login.jsp, order_list.jsp等) │ └── static/ # CSS/JS/IMG(无构建工具,直接引用) ├── lib/ # 42个jar包(注意:spring-core-3.2.18.RELEASE.jar在此) └── build.xml # Ant构建脚本(非Maven!)

提示:build.xml里定义了ant deploy任务,它会把WebContent下的内容复制到Tomcat的webapps/ROOT目录。这是该系统唯一指定的部署方式,强行用Maven打包会丢失JSP编译路径。

2.2 配置Tomcat 7并验证基础环境

这套系统对JDK版本极其敏感:必须用JDK 1.8.0_202或更低版本(高版本JDK的javax.el包变更会导致JSP表达式解析失败)。验证命令:

java -version # 输出必须是:java version "1.8.0_202"

下载Tomcat 7.0.96(官网存档版),解压后修改conf/server.xml,确保HTTP端口为8080(系统默认硬编码):

<!-- conf/server.xml 第22行附近 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

然后将jiazheng-system/WebContent整个目录复制到tomcat/webapps/ROOT(覆盖原ROOT):

rm -rf tomcat/webapps/ROOT cp -r jiazheng-system/WebContent/ tomcat/webapps/ROOT

启动Tomcat:

tomcat/bin/startup.sh # Linux/Mac # 或 tomcat\bin\startup.bat # Windows

访问http://localhost:8080/login.jsp—— 如果看到蓝色主题的登录页(用户名admin/密码123456),说明Spring容器已加载成功。此时检查Tomcat日志:

tail -f tomcat/logs/catalina.out

应出现类似日志:

INFO: Loading XML bean definitions from class path resource [applicationContext.xml] INFO: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@1a2b3c4d]: org.springframework.beans.factory.support.DefaultListableBeanFactory@5e6f7g8h

这证明Spring IOC容器已初始化,applicationContext.xml中的<bean id="orderService" class="com.jiazheng.service.impl.OrderServiceImpl"/>已被注册。

2.3 数据库初始化:MySQL 5.7建库与SQL执行

系统使用MySQL 5.7,严禁用8.0+(datetime字段默认值语法不兼容)。创建数据库:

CREATE DATABASE jiazheng DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

执行jiazheng-system/WebContent/WEB-INF/sql/jiazheng.sql(共12张表):

mysql -u root -p jiazheng < jiazheng-system/WebContent/WEB-INF/sql/jiazheng.sql

关键表结构需特别注意:

  • t_user表中user_type ENUM('CUSTOMER','WORKER','ADMIN') NOT NULL—— 这是权限控制的底层依据,不是用Shiro或Spring Security实现的;
  • t_order表中status VARCHAR(20) DEFAULT 'WAITING'—— 状态机完全靠Java代码枚举控制(OrderStatus.java),无状态表;
  • t_worker表中certification_status TINYINT(1) DEFAULT 0—— 0=未认证,1=已认证,前端显示“持证上岗”图标即读此字段。

参数说明:jiazheng.sql末尾有INSERT INTO t_user VALUES (1,'admin','123456','ADMIN',...);,这是默认管理员账号。密码是明文存储(系统无加密逻辑),上线前必须用UPDATE t_user SET password=MD5('newpwd') WHERE id=1;手动改密。


3. 核心业务链路:从登录到派单,Spring MVC如何驱动家政订单流

3.1 登录流程:Filter拦截+Session管理+角色跳转

系统不用Spring Security,而是用自定义LoginFilter(src/com/jiazheng/filter/LoginFilter.java)实现权限控制。其核心逻辑:

// src/com/jiazheng/filter/LoginFilter.java public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; // 放行静态资源和登录页 if (request.getRequestURI().contains("login.jsp") || request.getRequestURI().endsWith(".css") || request.getRequestURI().endsWith(".js")) { chain.doFilter(req, resp); return; } // 检查Session中是否有user对象 User user = (User) request.getSession().getAttribute("user"); if (user == null) { response.sendRedirect(request.getContextPath() + "/login.jsp"); return; } // 角色跳转:客户去/order_list.jsp,阿姨去/worker_order.jsp,管理员去/admin/index.jsp String role = user.getUserType(); if ("CUSTOMER".equals(role)) { request.getRequestDispatcher("/order_list.jsp").forward(request, response); } else if ("WORKER".equals(role)) { request.getRequestDispatcher("/worker_order.jsp").forward(request, response); } else if ("ADMIN".equals(role)) { request.getRequestDispatcher("/admin/index.jsp").forward(request, response); } }

逻辑说明:这个Filter在web.xml中配置为<filter-mapping>,优先级高于Spring DispatcherServlet。它不依赖任何框架,纯粹用HttpSession存用户信息,简单粗暴但稳定。User对象序列化后存入Session,因此User类必须实现Serializable(检查src/com/jiazheng/entity/User.java第12行)。

3.2 订单创建:MyBatis动态SQL与事务边界

客户在order_add.jsp填写地址、服务类型、时间后,提交到OrderController.java:

// src/com/jiazheng/controller/OrderController.java @RequestMapping(value = "/addOrder", method = RequestMethod.POST) public String addOrder(@ModelAttribute Order order, HttpSession session) { User user = (User) session.getAttribute("user"); order.setCustomerId(user.getId()); // 关联客户ID order.setStatus("WAITING"); // 初始状态 order.setCreateTime(new Date()); // 服务器时间 try { orderService.addOrder(order); // 调用Service层 return "redirect:/order_list.jsp?msg=success"; } catch (Exception e) { e.printStackTrace(); return "redirect:/order_add.jsp?msg=error"; } }

OrderService.addOrder()方法开启事务(applicationContext.xml中配置了<tx:annotation-driven/>):

<!-- WEB-INF/applicationContext.xml --> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>

对应的MyBatis Mapper XML(src/com/jiazheng/mapper/OrderMapper.xml)使用动态SQL插入:

<!-- src/com/jiazheng/mapper/OrderMapper.xml --> <insert id="addOrder" parameterType="Order"> INSERT INTO t_order ( customer_id, worker_id, service_type, address, scheduled_time, status, create_time, remark ) VALUES ( #{customerId}, #{workerId}, #{serviceType}, #{address}, #{scheduledTime}, #{status}, #{createTime}, #{remark} ) </insert>

参数说明:#{}是预编译占位符,防止SQL注入;parameterType="Order"指向src/com/jiazheng/entity/Order.java,该类字段名必须与数据库列名严格一致(如serviceType对应t_order.service_type),否则MyBatis无法映射。scheduled_time字段在MySQL中是DATETIME类型,Java中用java.util.Date,MyBatis自动转换。

3.3 派单逻辑:管理员后台的“抢单池”模拟

管理员在/admin/order_manage.jsp看到所有WAITING状态订单,点击“指派”按钮触发AJAX请求:

// admin/order_manage.jsp 中的JS function assignOrder(orderId, workerId) { $.post("/admin/assignOrder", {orderId: orderId, workerId: workerId}, function(data) { if(data.success) { alert("派单成功!"); location.reload(); // 刷新列表 } }); }

后端AdminController.java处理:

@RequestMapping("/assignOrder") @ResponseBody public Map<String, Object> assignOrder(Integer orderId, Integer workerId) { Map<String, Object> result = new HashMap<>(); try { orderService.assignOrder(orderId, workerId); // 更新订单worker_id和status result.put("success", true); } catch (Exception e) { result.put("success", false); result.put("msg", e.getMessage()); } return result; }

OrderService.assignOrder()方法内调用MyBatis Update:

<!-- src/com/jiazheng/mapper/OrderMapper.xml --> <update id="assignOrder" parameterType="map"> UPDATE t_order SET worker_id = #{workerId}, status = 'ASSIGNED' WHERE id = #{orderId} AND status = 'WAITING' </update>

关键点:WHERE status = 'WAITING'是乐观锁机制——如果阿姨已抢单(状态变为ACCEPTED),此SQL将影响0行,避免重复派单。系统不依赖数据库行锁,全靠应用层状态校验。


4. 避坑指南:这6个血泪经验让上线时间缩短3天

4.1 现象:JSP页面中文乱码,登录页显示“测试”

原因:Tomcat 7默认使用ISO-8859-1解码URL参数,而JSP页面meta声明为UTF-8,导致GET请求参数乱码。
解决:在web.xml中添加CharacterEncodingFilter,且必须放在所有Filter之前:

<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

注意:forceEncoding=true强制覆盖request的encoding,否则Tomcat仍用ISO-8859-1。

4.2 现象:登录后跳转到空白页,浏览器地址栏显示/order_list.jsp?msg=success但页面无内容

原因:order_list.jsp中使用了<c:forEach items="${orderList}" var="order">,但未引入JSTL标签库。
解决:在order_list.jsp顶部添加:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

并确认WebContent/WEB-INF/lib/下存在jstl-1.2.jar和standard-1.1.2.jar(缺一不可)。

4.3 现象:MySQL插入订单时报错Data truncation: Incorrect datetime value: '0000-00-00 00:00:00'

原因:MySQL 5.7默认启用STRICT_TRANS_TABLES模式,拒绝零日期。而系统部分SQL(如INSERT INTO t_worker ... VALUES (..., '0000-00-00', ...))使用了零日期。
解决:修改MySQL配置my.cnf,在[mysqld]下添加:

sql_mode=NO_ENGINE_SUBSTITUTION

重启MySQL后执行:

SET GLOBAL sql_mode='NO_ENGINE_SUBSTITUTION';

4.4 现象:Tomcat启动后报ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet

原因:lib/目录下缺少spring-webmvc-3.2.18.RELEASE.jar,或版本号与applicationContext.xml中xmlns:mvc="http://www.springframework.org/schema/mvc"的schema版本不匹配。
解决:检查lib/目录,确保存在spring-webmvc-3.2.18.RELEASE.jar;同时确认web.xml中DispatcherServlet配置:

<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>

4.5 现象:阿姨登录后看不到自己被指派的订单,worker_order.jsp列表为空

原因:WorkerController.java中查询语句写错,WHERE worker_id = ? AND status IN ('ASSIGNED','ACCEPTED')漏写了ACCEPTED状态。
解决:打开src/com/jiazheng/controller/WorkerController.java,找到listOrders()方法,修正SQL条件:

// 错误写法(只查ASSIGNED) List<Order> orders = orderService.findByWorkerIdAndStatus(workerId, "ASSIGNED"); // 正确写法(查ASSIGNED和ACCEPTED) List<Order> orders = orderService.findByWorkerIdAndStatuses(workerId, Arrays.asList("ASSIGNED", "ACCEPTED"));

对应Mapper XML需同步更新为IN子句。

4.6 现象:修改订单状态后,财务报表统计不准,admin/report.jsp显示金额为0

原因:财务统计SQL使用SUM(price),但t_order.price字段为VARCHAR(20)类型(设计缺陷),MySQL隐式转换失败。
解决:执行MySQL修复语句,将price改为DECIMAL:

ALTER TABLE t_order MODIFY COLUMN price DECIMAL(10,2) DEFAULT 0.00; UPDATE t_order SET price = CAST(REPLACE(price, '¥', '') AS DECIMAL(10,2)) WHERE price REGEXP '^¥?[0-9]+\.?[0-9]*$';

血泪经验:这个字段在原始SQL中就是VARCHAR,上线前必须人工清洗数据并改类型,否则所有金额计算都失效。


5. 定制化改造:3个高频需求的低成本实现方案

5.1 需求:增加“服务评价”功能,客户下单后可对阿姨打分

落地路径:不新增表,复用t_order扩展字段

  1. 数据库:给t_order加两列
ALTER TABLE t_order ADD COLUMN rating TINYINT(1) DEFAULT NULL COMMENT '评分1-5', ADD COLUMN comment VARCHAR(500) DEFAULT NULL COMMENT '评价内容';
  1. Java实体:在Order.java中添加属性
private Byte rating; // 对应rating字段 private String comment; // 对应comment字段 // 生成getter/setter
  1. JSP页面:在order_detail.jsp底部追加评价表单
<c:if test="${order.status == 'COMPLETED' && empty order.rating}"> <form action="/customer/submitRating" method="post"> <input type="hidden" name="orderId" value="${order.id}"> 星级:<select name="rating"> <option value="1">1星</option> <option value="2">2星</option> <option value="3">3星</option> <option value="4">4星</option> <option value="5">5星</option> </select> 评价:<textarea name="comment" rows="3" cols="50"></textarea> <button type="submit">提交评价</button> </form> </c:if>
  1. Controller:新增CustomerController.submitRating()
@RequestMapping("/submitRating") public String submitRating(@RequestParam Integer orderId, @RequestParam Byte rating, @RequestParam String comment) { Order order = new Order(); order.setId(orderId); order.setRating(rating); order.setComment(comment); order.setStatus("RATED"); // 状态变更为已评价 orderService.updateOrder(order); return "redirect:/order_detail.jsp?id=" + orderId; }

优势:零新增表,SQL改动最小;状态RATED可作为后续“好评返现”活动的筛选条件。

5.2 需求:支持微信扫码支付,替代现金收款

落地路径:对接微信H5支付API,不改核心架构

微信H5支付要求spbill_create_ip为用户真实IP,而系统部署在内网,需通过Nginx透传:

# nginx.conf location /pay/ { proxy_pass http://tomcat_backend; proxy_set_header X-Real-IP $remote_addr; # 关键!透传真实IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

Java端调用微信统一下单接口(WxPayService.java):

public Map<String, String> createH5Order(String orderId, BigDecimal amount) { // 1. 构造微信统一下单参数 SortedMap<String, String> params = new TreeMap<>(); params.put("appid", "wx1234567890abcdef"); params.put("mch_id", "1234567890"); params.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); params.put("body", "家政服务订单"); params.put("out_trade_no", orderId); params.put("total_fee", amount.multiply(new BigDecimal(100)).intValue() + ""); // 单位:分 params.put("spbill_create_ip", "192.168.1.100"); // 内网IP,微信要求必须填 params.put("notify_url", "http://yourdomain.com/pay/notify"); params.put("trade_type", "MWEB"); // 2. 签名并发送请求 String sign = WXPayUtil.generateSignature(params, "yourKey"); params.put("sign", sign); String xml = WXPayUtil.mapToXml(params); String result = HttpClientUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml); // 3. 解析返回的mweb_url Map<String, String> resultMap = WXPayUtil.xmlToMap(result); return resultMap; // 返回{mweb_url=http://...} }

前端跳转mweb_url即可唤起微信支付。注意:spbill_create_ip不能写127.0.0.1,必须是服务器外网出口IP或Nginx代理IP。

5.3 需求:导出Excel报表,财务每月需汇总订单明细

落地路径:用Apache POI 3.17(兼容JDK 1.8)生成XLSX

  1. 添加依赖:将poi-3.17.jar、poi-ooxml-3.17.jar、poi-ooxml-schemas-3.17.jar放入lib/

  2. Controller方法:

@RequestMapping("/exportOrders") public void exportOrders(HttpServletResponse response) throws Exception { List<Order> orders = orderService.findAll(); // 查询全部订单 // 创建Excel工作簿 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("订单明细"); // 表头 String[] headers = {"订单号", "客户姓名", "服务类型", "金额", "状态", "下单时间"}; XSSFRow headerRow = sheet.createRow(0); for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); } // 数据行 int rowNum = 1; for (Order order : orders) { XSSFRow row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(order.getId().toString()); row.createCell(1).setCellValue(order.getCustomerName()); row.createCell(2).setCellValue(order.getServiceType()); row.createCell(3).setCellValue(order.getPrice().doubleValue()); row.createCell(4).setCellValue(order.getStatus()); row.createCell(5).setCellValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(order.getCreateTime())); } // 输出响应 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=orders_" + System.currentTimeMillis() + ".xlsx"); workbook.write(response.getOutputStream()); }

避坑:POI 4.x+不支持JDK 1.8,必须用3.17;workbook.write()后无需workbook.close(),因为输出流由Servlet容器管理,关闭会导致响应中断。


6. 生产环境加固:从开发机到客户服务器的5个必做动作

6.1 数据库连接池替换:从BasicDataSource升级到Druid 1.1.22

原始系统用org.apache.commons.dbcp.BasicDataSource,连接泄漏风险高。替换步骤:

  1. 删除lib/commons-dbcp-1.4.jar和commons-pool-1.6.jar
  2. 添加druid-1.1.22.jar到lib/
  3. 修改WEB-INF/applicationContext.xml中数据源配置:
<!-- 替换前 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/jiazheng?useUnicode=true&amp;characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!-- 替换后 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/jiazheng?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> <property name="initialSize" value="5"/> <property name="minIdle" value="5"/> <property name="maxActive" value="20"/> <property name="maxWait" value="60000"/> <property name="timeBetweenEvictionRunsMillis" value="60000"/> <property name="minEvictableIdleTimeMillis" value="300000"/> <property name="validationQuery" value="SELECT 1 FROM DUAL"/> <property name="testWhileIdle" value="true"/> <property name="testOnBorrow" value="false"/> <property name="testOnReturn" value="false"/> </bean>

参数说明:serverTimezone=Asia/Shanghai解决MySQL时区问题;validationQuery用SELECT 1 FROM DUAL(MySQL 5.7兼容);testWhileIdle=true确保空闲连接有效性。

6.2 日志体系重构:Log4j 1.2.17 → Logback + SLF4J

原始系统用log4j-1.2.17.jar,存在反序列化漏洞。升级方案:

  1. 删除lib/log4j-1.2.17.jar
  2. 添加slf4j-api-1.7.32.jar、logback-classic-1.2.11.jar、logback-core-1.2.11.jar
  3. 在WebContent/WEB-INF/classes/下创建logback.xml:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/jiazheng.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/jiazheng.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="FILE"/> </root> </configuration>
  1. Java代码中将Logger.getLogger(xxx.class)替换为LoggerFactory.getLogger(xxx.class)

效果:日志按天滚动,单文件超100MB自动切分,保留30天,彻底规避Log4j漏洞。

6.3 安全加固:禁用HTTP TRACE方法,防止XST攻击

在conf/web.xml(Tomcat全局配置)中添加:

<security-constraint> <web-resource-collection> <web-resource-name>Disable TRACE</web-resource-name> <url-pattern>/*</url-pattern> <http-method>TRACE</http-method> </web-resource-collection> <auth-constraint/> </security-constraint>

验证是否生效:

curl -X TRACE http://localhost:8080/ # 应返回 403 Forbidden

6.4 JVM参数调优:针对家政系统IO密集型特征

在tomcat/bin/setenv.sh(Linux)或setenv.bat(Windows)中添加:

# Linux setenv.sh export JAVA_OPTS="-server -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Dfile.encoding=UTF-8"

参数依据:家政系统每秒处理约3-5个订单,内存占用稳定在600MB左右;G1 GC在低延迟场景下比CMS更稳定;-Dfile.encoding=UTF-8解决Linux下中文路径读取问题。

6.5 备份策略:用Cron+mysqldump实现每日凌晨自动备份

编写backup.sh:

#!/bin/bash DATE=$(date +%Y%m%d) mysqldump -u root -p'yourpwd' --databases jiazheng > /backup/jiazheng_$DATE.sql gzip /backup/jiazheng_$DATE.sql find /backup -name "jiazheng_*.sql.gz" -mtime +7 -delete

加入crontab:

# 每日凌晨2:00执行 0 2 * * * /bin/bash /opt/backup.sh >> /var/log/backup.log 2>&1

我的习惯:每次客户新签合同,我都会在交付前用这套脚本跑一次全量备份,并把jiazheng_$(date +%Y%m%d).sql.gz文件刻录成光盘交给客户存档。不是信不过云备份,而是家政公司的老板们更相信摸得着的东西——这玩意儿他们能亲手放进保险柜。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询