ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Java JSP的汽车维修保养管理系统:架构、事务与部署实战

基于Java JSP的汽车维修保养管理系统:架构、事务与部署实战 简介这是一份基于 JavaJSP 的汽车维修保养管理系统完整源码与数据库文件面向毕业设计场景适合计算机专业学生完成课程设计或毕设项目。系统采用 JSP、jQuery 前端Servlet、JDBC 后端按管理员与用户双角色划分覆盖车主信息管理、保养管理、维修管理、年检保险管理、预约信息管理等核心模块其中车主信息包含车辆档案预约信息支持维修保养登记各模块均具备完整的增删改查与权限控制流程。压缩包共 166 个文件大小约 4.29MB包含 72 个 JSP 页面、17 个 JavaScript 脚本、7 个 Java 类、1 个 SQL 数据库脚本以及 CSS、图片、JAR 包等配套资源目录结构清晰可按说明导入数据库并启动项目。目前已有 41 人学习下载适合作为理解传统 JSPServlet Web 开发模式的入门参考。通过这套源码读者可快速掌握系统表结构设计、会话管理、分页查询与权限拦截的实现思路也能直接调整配置用于毕业设计演示或二次开发。1. 汽车维修保养管理系统为什么我劝你先别嫌弃 JSP如果只看到“javajsp”就往“过时技术”里归类那你可能会错过一个很实用的落地样本。这类汽车维修保养管理系统的真实使用场景是二类修理厂、快修连锁和4S店售后车间每天有车辆进店、开单、领料、结算、回访纸质单子满天飞配件库存全靠老师傅脑子记。一套基于 javajsp 的维修保养管理系统本质是把“接车—派工—领料—结算—台账”这条业务链搬进浏览器让前台录入、车间看单、老板查账各干各的活。它面向的不只是毕业设计更是那些想低成本把店面数据管起来的小团队。我早年接过一个类似项目客户只提一个要求能用、别贵、别让我换电脑。这就是 JSP 方案的天然优势——部署一个 Tomcat装个 MySQL浏览器打开就能用。这篇文章我会顺着数据建模、权限与请求链路、工单流转和事务把一套可跑的 Spring 之前的老派 Java Web 方案拆给你看最后把我在部署和排错时踩过的坑都交代清楚。2. 从标题拆系统JSP Servlet MySQL 的架构为什么够用2.1 标题里的“javajsp”到底指什么标题写“基于javajsp”实际项目里通常不是一个 Java 后端 API 加 JSP 前端而是经典的 JSP Servlet JavaBean JDBC 的 MVC 结构。JSP 负责视图Servlet 负责控制器JavaBean / DAO 负责业务和数据库访问。这个组合没有 Spring 全家桶那么省事但胜在结构清楚每个页面请求都能在 Web.xml 里找到对应的 Servlet 映射谁在处理什么逻辑一眼见底。对维护这类系统的人来说排错路径短不用在自动配置的黑匣子里绕。标题里的“源码数据库”是另一个关键信号这类系统交付时数据库脚本不是可选项而是核心资产。因为维修保养系统的业务数据高度依赖表结构工单、配件、客户、结算这几张表的关系一旦定下来功能就定了一半。没有数据库脚本源码只是一堆没法起飞的 JSP 页面没有业务数据流转所有页面都是空壳。我一般会用以下分层去组织这类项目这也是最容易被面试官追问的 Java Web 经典分层浏览器端JSP 页面 JavaScript CSS负责表单提交和列表展示控制层Servlet负责接收请求、调用业务、跳转页面业务层Service / DAO负责权限校验、工单生成、库存扣减数据层MySQL负责存储客户、车辆、工单、配件流水2.2 数据库建模五张核心表的设计与字段取舍维修保养系统的数据模型无论界面怎么变核心就是“人—车—单—件—钱”这五条线。最常踩的坑是贪多一上来就把回访记录、保险到期提醒、员工绩效全设计进去结果字段冗余业务写不下去。我给你的建议是先建五张基础表跑通后再扩展。以 MySQL 为例核心表设计如下customer客户表存姓名、手机号、地址。手机号要做唯一索引因为门店最常用的查询入口就是手机号。vehicle车辆表存车牌号、品牌型号、VIN、行驶里程。一个客户名下可以有多辆车所以 vehicle 表要带 customer_id 外键。work_order工单表主表记录单号、车辆 ID、接待员、当前状态待派工/维修中/待结算/已完成、进店里程、描述。part配件表存配件编码、名称、库存数量、成本价、售价。work_order_item工单明细表存每次维修/保养用到的配件和工时项含数量、单价、总价。先说一个经验之谈工单明细表一定要独立出来不要在主表里放“配件1、配件2、工时1”这种逗号拼接的懒设计。统计每张单子的毛利、每月配件消耗量全靠明细表的行记录。用分组聚合查一下就知道每辆车最常换的配件是什么这对门店备货很有价值。以下是建库时最基础的四张表 SQL落库后记得加 character set 和 collation不然后面中文乱码问题会特别难排查。CREATE DATABASE IF NOT EXISTS auto_service DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE auto_service; CREATE TABLE customer ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, phone VARCHAR(20) NOT NULL UNIQUE, address VARCHAR(200), created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB; CREATE TABLE vehicle ( id INT PRIMARY KEY AUTO_INCREMENT, customer_id INT NOT NULL, plate_no VARCHAR(20) NOT NULL UNIQUE, brand VARCHAR(50), model VARCHAR(50), vin VARCHAR(50), mileage INT DEFAULT 0, FOREIGN KEY (customer_id) REFERENCES customer(id) ) ENGINEInnoDB; CREATE TABLE part ( id INT PRIMARY KEY AUTO_INCREMENT, part_no VARCHAR(30) NOT NULL UNIQUE, name VARCHAR(100) NOT NULL, stock INT NOT NULL DEFAULT 0, cost_price DECIMAL(10,2), sale_price DECIMAL(10,2) ) ENGINEInnoDB; CREATE TABLE work_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(30) NOT NULL UNIQUE, vehicle_id INT NOT NULL, user_id INT NOT NULL, status TINYINT DEFAULT 0, description VARCHAR(500), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_status (status), FOREIGN KEY (vehicle_id) REFERENCES vehicle(id) ) ENGINEInnoDB;这段建表脚本看起来平平无奇但有三个参数我是特意写出来的很多初学者会漏掉。第一ENGINEInnoDB必须显式指定因为后面扣配件库存时要靠事务和行锁MyISAM 不支持行级锁第二DEFAULT CURRENT_TIMESTAMP让创建时间自动维护省得插入数据时手动传时间第三KEY idx_status (status)是一个功能型索引门店要经常按“维修中”“待结算”这类状态筛选工单没有这个索引的列表页数据量大了会明显变慢。工具上我习惯用 dbx 这类可视化客户端建表但到了交付阶段一定要把 SQL 脚本导出成 .sql 文件这份文件才是源码的一部分。2.3 为什么不建议把系统做成前后端分离这里要说个反直觉的结论今天做企业内部管理系统JSP 不一定比 Vue Spring Boot 差。前后端分离适合面向公网、多端复用、界面交互复杂的项目但维修保养系统的使用场景很固定就是店里三台电脑上的 Chrome 浏览器用户是四十多岁的车间师傅和前台大姐。他们要的是“开单—提交—打印”三步走完而不是一个带 loading 动画的单页应用。JSP 这套方案另外一个现实优势是部署轻。一个 Tomcat 实例加上数据库连接配置就完成交付不用配 Nginx 反向代理不用考虑跨域问题更不用给客户电脑装 Node 环境。对卖源码、做外包的人来说交付成本低意味着后期维护解释成本也低。如果你是真做商业项目我反而推荐在这个架构里把 JDBC 换成连接池其他保持不变。3. 请求链路从登录开始Servlet 与 JSP 如何分工3.1 登录会话Filter 拦截与 Session 校验做这类系统时我一向把登录功能放在最前面去写。这不只是因为它简单而是因为所有后续页面都要依赖“当前登录用户是谁”这个信息。常见做法是用户在 login.jsp 输入账号密码提交到 LoginServlet校验成功后把用户信息写进 Session同时写一个 Filter 拦截所有 .jsp 和 .do 请求检查 Session 里有没有登录标记。Servlet 3.0 之后可以直接用WebServlet注解不用在 web.xml 里写一长串映射。给一个最小的登录接口WebServlet(/login) public class LoginServlet extends HttpServlet { private static final long serialVersionUID 1L; Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); // 实际项目中这里要接 DAO 查询不能拿明文口令去比对 if (admin.equals(username) 123456.equals(password)) { // 用 Session 保存登录态后续 Filter 判断 userInfo 是否存在 request.getSession().setAttribute(userInfo, username); response.sendRedirect(request.getContextPath() /order/list.jsp); } else { request.setAttribute(errorMsg, 账号或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); } } }这里有两个参数要说明。request.setCharacterEncoding(UTF-8)必须放在最前面因为 POST 表单提交的中文参数在 Tomcat 里默认按 ISO-8859-1 解码不设置编码会把“张工”变成乱码sendRedirect和forward的区别在于重定向会发起一次新的请求路径要带上request.getContextPath()而 forward 是服务器内部跳转路径里不用带项目名。这段代码里的密码比对是演示用生产环境至少要做加盐哈希这是 Java 面试题里常被追问的点。3.2 一个工单列表页是怎么渲染出来的登录进去后的第一个页面通常是工单列表。JSP 页面里最忌讳写一大堆 Java 脚本片段那会把页面搞成一个没法维护的大杂烩。推荐把数据查询放在 Servlet 里然后把结果放进 request 域最后在 JSP 里用 JSTL 和 EL 表达式渲染。这里给一段列表查询的 Servlet 实现重点在防止 SQL 注入和参数传递WebServlet(/order/list) public class OrderListServlet extends HttpServlet { private static final long serialVersionUID 1L; Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 状态筛选0全部 1待派工 2维修中 3待结算 4已完成 String statusParam request.getParameter(status); int status (statusParam null || statusParam.isEmpty()) ? 0 : Integer.parseInt(statusParam); // DAO 返回 ListWorkOrderVOjoin 了客户名和车牌号 OrderDao dao new OrderDao(); ListWorkOrderVO orderList dao.findByStatus(status); request.setAttribute(orderList, orderList); request.getRequestDispatcher(/order/list.jsp).forward(request, response); } }参数status的处理方式是这类系统查询的通用套路先判断是否有参数没有就给默认值避免空指针。findByStatus内部应该是SELECT ... WHERE status ?的预编译查询严禁用字符串拼接 status 进去。JSP 拿到orderList后用c:forEach循环渲染表格每一行的操作列放“编辑”“派工”“结算”入口用${item.id}拼到 URL 参数里。这种“Servlet 取数 JSP 展示”的分工恰好呼应了后端开发里视图与逻辑分离的基本原则。3.3 JSP 页面里的 jstl 标签与请求参数传递很多新手写 JSP 列表页喜欢在% %里面写 for 循环这是最让后来接手的人头疼的风格。JSTL 的核心价值是把循环和条件判断从 Java 代码变成标签让美工也能看懂页面结构。拿工单列表的一段渲染代码来说% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % table classtable table-bordered thead tr th工单号/thth车牌/thth客户/thth状态/thth操作/th /tr /thead tbody c:forEach items${orderList} varitem varStatusstatus tr td${item.orderNo}/td td${item.plateNo}/td td${item.customerName}/td td c:choose c:when test${item.status 2}维修中/c:when c:when test${item.status 3}待结算/c:when c:otherwise已完成/c:otherwise /c:choose /td td a href${pageContext.request.contextPath}/order/detail?id${item.id}查看/a a href${pageContext.request.contextPath}/order/edit.jsp?id${item.id}编辑/a /td /tr /c:forEach /tbody /tablevarStatus这个属性提供了一个循环计数器在需要给表格行加序号时会很实用。${pageContext.request.contextPath}是 JSP 里获取项目根路径的标准写法用它拼接链接可以避免部署到不同目录名时链接全部失效的问题。引用 JSTL 之前要确认web.xml的版本是 2.5 以上否则 JSP 2.0 之前的容器不认 EL 表达式页面上会出现一大片$(...)的裸字符串。页面里的表单提交也遵循同一个原则能用actionxxx的 servlet 映射就不写onclick里的 JS 拼接。前后端联调时抓包看浏览器Form Data里的参数名是否与 Servlet 里getParameter取的名字一致这是排查多数 400 错误的入口。4. 把维修单跑通工单流转与配件库存的事务处理4.1 开单页面的事务性设计维修保养系统的业务核心是“一张工单从创建到完成要同时修改多张表”写入 work_order 主表、写入 work_order_item 明细表、扣减 part 表库存、更新 vehicle 表的里程。任何一个环节失败都不能让前面已经写入的数据留下半截。开单页面的 JSP 表单通常会提交以下字段vehicleId、description、items一个 JSON 字符串包含配件 ID、数量、工时费。为什么用 JSON 字符串而不是多个同名参数因为一个工单包含的明细数量不固定用items这一个字段包起来Servlet 里用 Gson 解析成 List 对象代码更整洁也避免 JSP 端拼超长表单。form action${pageContext.request.contextPath}/order/save methodpost input typehidden namevehicleId value${vehicle.id} / input typehidden nameitems iditemsHidden / div classform-group label故障描述/label textarea namedescription classform-control/textarea /div button typebutton onclickcollectItems()保存工单/button /form script function collectItems() { // 假设页面表格里每次添加的配件行都存在 array var rows []; document.querySelectorAll(.item-row).forEach(function(row) { rows.push({ partId: row.dataset.partId, qty: row.querySelector(.qty).value, price: row.querySelector(.price).value }); }); document.getElementById(itemsHidden).value JSON.stringify(rows); document.querySelector(form).submit(); } /script这个页面的设计要点是前端只负责收集数据真正的业务拼装交给 Servlet。items在隐藏域里以 JSON 形式传到后端Servlet 里统一做解析、校验、入库。要特别注意collectItems这个函数里对.item-row的遍历如果页面里还有别的表格选择器要限定在工单表格的容器里否则会把无关行采集进去。4.2 事务与行锁扣库存别扣成负数在后端处理保存逻辑时第一件事是开启事务。用 JDBC 写原生事务的代码很啰嗦但对于不想引入 Spring 的项目它就是最可靠的方式。事务的核心逻辑是把 auto commit 关掉所有操作成功后统一提交任何一个异常就回滚。扣库存的操作还要注意并发——两个接待员同时给不同车辆开同一配件不能让库存在 UPDATE 的一瞬间变成负数。下面这段代码是事务处理的标准框架Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn DriverManager.getConnection(dbUrl, dbUser, dbPassword); // 第 1 步开启事务 conn.setAutoCommit(false); // 第 2 步插入工单主表拿到自增主键 String insertOrder INSERT INTO work_order(order_no, vehicle_id, user_id, status, description) VALUES (?, ?, ?, 1, ?); ps conn.prepareStatement(insertOrder, Statement.RETURN_GENERATED_KEYS); ps.setString(1, orderNo); ps.setInt(2, vehicleId); ps.setInt(3, userId); ps.setString(4, description); ps.executeUpdate(); rs ps.getGeneratedKeys(); int orderId rs.next() ? rs.getInt(1) : 0; // 第 3 步逐条解析明细并插入 for (ItemVO item : itemList) { // 扣库存这里用 UPDATE 加条件防止负库存 String deductSql UPDATE part SET stock stock - ? WHERE id ? AND stock ?; ps conn.prepareStatement(deductSql); ps.setInt(1, item.qty); ps.setInt(2, item.partId); ps.setInt(3, item.qty); int rows ps.executeUpdate(); if (rows 0) { throw new RuntimeException(配件库存不足ID: item.partId); } String insertItem INSERT INTO work_order_item(order_id, part_id, qty, price) VALUES (?, ?, ?, ?); ps conn.prepareStatement(insertItem); ps.setInt(1, orderId); ps.setInt(2, item.partId); ps.setInt(3, item.qty); ps.setBigDecimal(4, item.price); ps.executeUpdate(); } // 第 4 步提交事务 conn.commit(); } catch (Exception e) { if (conn ! null) conn.rollback(); throw new ServletException(工单保存失败, e); } finally { if (rs ! null) rs.close(); if (ps ! null) ps.close(); if (conn ! null) conn.setAutoCommit(true); if (conn ! null) conn.close(); }这段代码的写法是这类系统里最值得反复看的模板。Statement.RETURN_GENERATED_KEYS让executeUpdate后可以拿到数据库自增的主键不用单独再查一遍。扣库存的关键在WHERE id ? AND stock ?如果库存足够UPDATE 影响行数是 1如果不足影响行数是 0据此抛异常触发回滚。这种写法比先 SELECT 再判断再 UPDATE 更安全因为它把“扣减”和“校验”合并成一条原子语句行级锁天然保护了并发场景下不超卖。finally块里恢复autoCommit这个动作是为了连接归还给连接池时状态干净。如果用连接池却忘了这一句下一次借用这条连接时setAutoCommit(true)的默认值已经被改变会发生“上个事务没提交下个请求莫名查到脏数据”这种极其隐蔽的问题。4.3 结算与毛利统计别在 JSP 里算报表店长最关心的数据是每天的营收和毛利因此结算页除了展示工单明细外还要把“本次收入”和“配件成本”算出来。这个计算不要放在 JSP 里用脚本片段做应该在 SQL 层直接聚合好再传给页面。常见做法是用一条 JOIN 查询把工单明细的销售金额与配件成本匹配起来SELECT o.order_no, SUM(i.qty * i.price) AS total_amount, SUM(i.qty * p.cost_price) AS total_cost, SUM(i.qty * (i.price - p.cost_price)) AS profit FROM work_order o JOIN work_order_item i ON o.id i.order_id JOIN part p ON i.part_id p.id WHERE o.id ? GROUP BY o.id;这个查询通过JOIN part才能实时拿到配件成本profit就是毛利。注意一个细节work_order_item表里要保留price字段作为当时卖出的快照不能结算时实时读part.sale_price。因为配件可能已经调价你无法修改历史单据上的金额。这个取舍对财务统计影响很大——销售金额取快照成本取实时这是行业里普遍接受的记账逻辑。5. 部署与联调避坑亲身踩过的 5 个问题5.1 “ClassNotFoundException”与 MySQL 驱动版本不匹配现象启动 Tomcat 或访问首页时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因驱动 jar 没有放进 WEB-INF/lib 目录或者放进去的驱动包与被连的 MySQL 版本不兼容。MySQL 8.x 的驱动类名已经改名成com.mysql.cj.jdbc.Driver还在按旧写法配置com.mysql.jdbc.Driver马上就会翻车。解决确认 MySQL 版本后选对应驱动。MySQL 8.0 用mysql-connector-java-8.0.x.jarJDBC url 也要带时区参数例如jdbc:mysql://localhost:3306/auto_service?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai。没有serverTimezone参数会直接报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized这个报错容易让人误以为是乱码问题。5.2 页面中文乱码的“三层编码”问题现象表单提交到 MySQL 后查出来是带问号的乱码页面显示???。原因编码问题从来不是一个点而是一条链。第一层是数据库连接 URL 里的字符集参数第二层是表结构本身的 character set第三层是 JSP 页面的pageEncoding。我见过有人调了一天最后发现建表时没加DEFAULT CHARACTER SET utf8mb4数据库默认字符集是 latin1。解决按链路查三层全部统一为 utf8mb4。建表时在建库脚本里加DEFAULT CHARACTER SET utf8mb4连接 URL 加useUnicodetruecharacterEncodingutf8JSP 页面头部写成% page contentTypetext/html; charsetUTF-8 pageEncodingUTF-8 %。如果已经建表可以用ALTER TABLE customer CONVERT TO CHARACTER SET utf8mb4;修改这属于 mysql 数据库修改结构改完要确认原有数据没有二次乱码。5.3 JSP 页面修改后不生效现象改了 list.jsp 里的一个中文字段刷新浏览器还是旧内容。原因Tomcat 默认对 JSP 做了预编译修改后如果服务器没有触发重新编译或者浏览器把页面缓存住了就会显示旧页面。很多人在找编译路径其实有更大概率是浏览器缓存。解决按 Ctrl F5 强制刷新解决不了的命名为“JSP页面让加载完后刷新一次”的诉求就是这个问题。常见做法是在 JSP 的head里加一段禁用缓存的 Meta 标签但这只对当前页面有效治标不治本。更稳妥的办法是重新部署整个应用把 Tomcat 的work目录清掉或者直接在 manager 页面点 Reload。5.4 Tomcat 8.5 之后访问列表页面报 400现象表单提交时只要有中文参数Tomcat 8.5 就返回 400 Bad RequestTomcat 7 同样代码却没事。原因Tomcat 8.5 开始对 URL 参数的合法性检查更严格尤其对%之类的特殊字符。JSP 里用 GET 传递中文搜索关键词浏览器会对中文做百分号编码但某些编码方式会带上不合法的字节序列。解决这类带中文参数的请求一律改成 POST 提交或者在 Tomcat 的server.xml里给 Connector 增加URIEncodingUTF-8参数。前者是治本后者也需要配合修改表单提交方式才彻底。别把精力花在找“隐藏配置”上改 POST 就老实安稳。5.5 数据库备份恢复时外键报错现象交付阶段把数据库导到客户机器上执行 SQL 脚本时报外键约束失败。原因导出的 SQL 文件里表顺序乱了customer 表还没建vehicle 表就先执行 FOREIGN KEY 引用自然失败。解决用数据库工具的“导出结构”功能后检查文件里的建表顺序或者干脆在脚本开头SET FOREIGN_KEY_CHECKS 0;导入完毕后恢复为 1。我的经验是交付时不要只给一份全量 SQL最好再附一份init.sql只建库建表和一份data.sql只插初始数据方便别人分步执行。6. 上线前的最后几百米备份、连接池与自查清单把系统从开发机搬到门店去用之前有几个动作值得花半天做完。第一个是连接池别用 JDBC 的DriverManager.getConnection裸连。门店规模虽小但访问高峰时前台、车间、老板室同时开页面裸连会导致 MySQL 连接数不够用页面卡死。换成 commons-dbcp 或 c3p0 之后数据库连接得到复用页面响应速度会有肉眼可见的提升。连接池的最小配置大概是这样的Resource namejdbc/autoService authContainer typejavax.sql.DataSource maxTotal20 maxIdle8 maxWaitMillis10000 driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/auto_service?useUnicodetrueamp;characterEncodingutf8amp;serverTimezoneAsia/Shanghai usernameroot passwordyourpass/在META-INF/context.xml里配上这个 ResourceJava 代码里通过Context.lookup(java:comp/env/jdbc/autoService)拿到 DataSource后续的 DAO 层所有连接都从这里取。这里maxTotal和maxIdle是必调参数店面 3 台电脑、每台开 2 个浏览器 Tab并发量也就 6 到 10maxTotal20完全够用maxWaitMillis10000的意义是连接池满时让请求等待 10 秒而不是无限阻塞否则高峰期页面会长时间白屏。第二个动作是设置数据库备份计划这一步很多人会拖到最后门店电脑一旦中毒或硬盘损坏客户数据全没。最简单的做法是用 MySQL 自带的 mysqldump 写一个脚本配合 Windows 任务计划每天凌晨执行mysqldump -u root -pYourPass --default-character-setutf8mb4 auto_service backup_$(date %Y%m%d_%H%M).sql find backup/ -name *.sql -mtime 30 -exec rm {} \;脚本里第二行的find是清理 30 天前的备份文件避免服务器硬盘被累积的 SQL 文件占满。把脚本放到店里的电脑上双硬盘建议备份到另一块盘或者网络共享目录不要和数据库文件放在同一个磁盘里。这里提醒一句那些数据库同步软件在单门店场景下用不上别指望靠它来当备份它解决的是多店数据汇总的问题。第三个动作是上线前的自查清单我每次交付都会按这个顺序过一遍所有页面是否走 Session 拦截未登录用户直连 URL 是否被 Filter 挡住默认管理员密码是否改掉工单打印页面是否用media print把按钮、菜单隐藏数据库定期备份任务是否已经创建这套基于 javajsp 的维修保养管理系统业务面不大但五脏俱全。我做过好几个同类型的项目最深的体会是JSP 项目的坑大多不在 Java 代码本身而在环境一致性、字符集和数据库状态这些周边地方。把上面的检查项养成习惯再遇到页面 500、中文乱码、连接超时大概率能快速定位而不是靠运气刷新。希望这些踩坑记录能帮你少走几段弯路。本文还有配套的精品资源点击获取
返回列表