资讯详情

资讯详情

JavaEE网上书店实战项目:Servlet+JSP+JDBC完整MVC电商系统

简介这是一份面向计算机专业本科生及Java初学者的JavaEE全栈实践项目资源适用于课程设计、毕业设计或Web开发入门实战帮助学习者系统掌握企业级B/S架构应用的开发流程与关键技术。资源包含88个文件以40个JSP页面负责前端展示与交互、11个Java源码含Servlet、DAO、Service等核心逻辑、1个SQL建库脚本完整MySQL表结构与初始化数据为主干辅以CSS样式、XML配置、JAR依赖及MyEclipse工程元数据文件整体压缩包仅519KB轻量易部署。已有3144人学习下载说明其结构清晰、开箱即用是少有的兼顾教学性与工程规范性的中小型项目范例。学习者可直接导入IDE运行完整体验用户注册登录、图书浏览搜索、购物车管理、订单提交及后台基础管理等7大模块同时通过源码深入理解Servlet-JSP-MVC分层、JPA数据库操作、会话控制与前后端协同机制为后续Spring Boot进阶打下扎实基础。1. 一个能跑通、能改、能交差的JavaEE网上书店不是Demo是完整MVC闭环连购物车并发扣减和订单状态机都写死了你是不是也遇到过这种事课程设计 deadline 前三天搜到一堆“JavaEE网上书店”点开——只有 login.jsp 和 index.jsp连数据库字段都没建全或者毕业设计答辩前夜发现购物车加了两次商品却只存一条记录后台订单列表空荡荡连个 MySQL 连接池配置都藏在 web.xml 里用硬编码写死这个项目不是那种“能编译就行”的教学玩具。它是一套真正走完用户注册→浏览图书→加入购物车→下单支付→管理员审核→发货完成全流程的 JavaEE 实战工程包含完整的三层架构Servlet JSP JDBC、事务控制JDBC 手动 commit/rollback、会话管理HttpSession 持久化购物车、以及一个带状态流转的订单模块未支付→已支付→已发货→已完成。它用的是最朴素但最扎实的 JavaEE 技术栈Servlet 3.0、JSP 2.2、JSTL 1.2、MySQL 5.7不依赖 Spring Boot 魔法所有逻辑都在 src 目录下裸写你能看清每一行 request.getParameter() 是怎么变成 SQL 参数的也能亲手把 checkout.jsp 里的表单 action 改成新接口。适合课程设计赶工、毕设基础框架搭建、或想补一补传统 JavaEE Web 开发肌肉记忆的开发者。2. 项目结构与技术选型为什么不用 Spring因为这里每层都是手写的“教科书级”实现这个项目没有 pom.xml没有 starter没有自动装配——它用的是最原始也最透明的 JavaEE 工程结构。整个 WAR 包解压后目录清晰得像一张手绘架构图每个文件夹名都在告诉你它该干什么。我拆包时第一反应是这不像学生作业倒像是某高校实验室给大三学生布置的“去框架化 Web 开发训练营”结业作品。它刻意回避了现代框架的黑匣子把所有关键决策都暴露在源码里比如为什么用 Filter 而不是 Servlet 拦截登录态为什么购物车对象要序列化进 HttpSession 而不是存在数据库为什么订单状态更新要加 synchronized 块这些都不是玄学而是写在代码注释和类命名里的设计权衡。2.1 工程目录结构src 下全是干货WEB-INF 里藏着所有配置真相项目采用标准 JavaEE Web 应用布局无任何 IDE 特有文件如 .idea 或 .project可直接导入 Eclipse / IntelliJ / NetBeans。核心结构如下src/ ├── cn.bookstore.dao/ # 数据访问层纯 JDBC 封装含 ConnectionUtil单例连接池 ├── cn.bookstore.domain/ # 实体层Book、User、Order、OrderItem 等 POJO含 toString() 和 equals() ├── cn.bookstore.service/ # 业务层BookService、OrderService含事务边界try-catch-rollback ├── cn.bookstore.web.servlet/ # 控制层LoginServlet、CartServlet、OrderServlet 等处理 HTTP 请求 ├── cn.bookstore.web.filter/ # 过滤器LoginFilter拦截未登录访问后台、EncodingFilter统一 UTF-8 └── cn.bookstore.util/ # 工具类PageBean分页封装、UUIDUtil生成唯一订单号 WebContent/ (即 WebRoot) ├── WEB-INF/ │ ├── web.xml # 核心配置servlet-mapping、filter-mapping、welcome-file-list │ ├── lib/ # 仅 4 个 jarmysql-connector-java-5.1.47.jar、jstl-1.2.jar、standard-1.1.2.jar、servlet-api.jar │ └── views/ # JSP 页面按功能分组/user/、/admin/、/common/、/cart/ ├── static/ # 静态资源CSS、JS、images无前端框架纯原生 JS 表单校验 └── index.jsp # 入口页含图书轮播分类导航热销榜提示web.xml是本项目的“宪法”。它定义了所有请求路由比如/cart/add映射到CartServlet/order/create映射到OrderServlet。没有注解驱动所有路径必须在这里显式声明。这是理解整个请求链路的起点。2.2 技术栈选择逻辑为什么坚持 JDBC 而非 Hibernate为什么用 JSPJSTL 而非 Thymeleaf这不是技术怀旧而是教学场景下的理性选择JDBC 手写 DAOBookDaoImpl.java中每个executeQuery()都配了PreparedStatement的setString()、setInt()调用参数位置、SQL 注入防护、结果集遍历逻辑全部可见。学生能一眼看出“查图书列表”对应哪条 SQL也能快速定位“为什么搜索中文书名返回空”——八成是setCharacterEncoding(UTF-8)漏写了。JSP JSTL EL所有页面用c:forEach遍历图书列表用${user.username}输出登录信息用fmt:formatDate格式化订单时间。没有模板引擎抽象层HTML 和 Java 逻辑边界清晰。cart/show.jsp里购物车总价计算直接写${fn:sum(cart.items.*.subtotal)}函数调用链路短调试时打断点就能看到cart.items到底有几个元素。无 JSON/AJAX 大杂烩所有交互走传统表单提交POST 服务端跳转response.sendRedirect()。OrderServlet处理完创建订单后重定向到order/success.jspURL 变为/order/success.jsp?oid20240520102345。这种模式对初学者友好——F5 刷新不会重复下单浏览器地址栏永远反映当前状态。2.3 数据库设计MySQL 表结构直击电商核心外键约束索引已就位SQL 文件bookstore.sql创建 5 张表关系严谨字段命名规范全小写下划线且已执行SET FOREIGN_KEY_CHECKS1;。关键设计点表名主键外键关键索引说明usersuid(PK, VARCHAR 32)—idx_username用户表密码用 MD5(明文salt) 存储salt 存于users.salt字段booksbid(PK, VARCHAR 32)—idx_category,idx_name图书表category为分类编码如 java, python非外键便于扩展ordersoid(PK, VARCHAR 32)uid→users.uididx_uid,idx_status订单主表status为 tinyint0未支付, 1已支付, 2已发货, 3已完成order_itemsitemid(PK, BIGINT auto_inc)oid→orders.oid,bid→books.bididx_oid,idx_bid订单明细表支持同一订单多本书、同一本书多次下单cart_itemscid(PK, BIGINT auto_inc)uid→users.uid,bid→books.bididx_uid购物车临时表用户登出即清空非持久化注意orders.oid使用UUIDUtil.getUUID()生成如20240520102345_8a9b3c4d5e6f7g8h前缀为日期随机串避免连续 ID 泄露业务量。order_items.quantity允许为 0用于标记“已取消项”而非物理删除。3. 核心模块拆解从购物车加购到订单创建看一个请求如何穿越 7 层调用我们以“用户将《Java编程思想》加入购物车”为例追踪从点击按钮到页面刷新的完整链路。这不是理论流程图而是真实代码逐层穿透——每一层都暴露了关键判断、异常分支和状态变更点。你能在CartServlet.java里看到request.getSession().getAttribute(cart)如何被强转为Cart对象也能在Cart.java的addBook()方法里看到synchronized(this)如何防止并发重复添加同一本书。这才是 JavaEE Web 开发的“血肉”。3.1 加购请求入口CartServlet.doPost() —— URL 路由与参数解析当用户点击图书页的“加入购物车”按钮表单提交到/cart/add触发CartServlet的doPost()方法。注意它不处理 GET 请求强制 POST防爬虫刷单。// src/cn/bookstore/web/servlet/CartServlet.java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String bid request.getParameter(bid); // 必须传 bid否则 400 if (bid null || bid.trim().isEmpty()) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, 图书ID不能为空); return; } Book book new BookDaoImpl().findBookById(bid); // 查数据库获取图书详情 if (book null) { request.setAttribute(msg, 图书不存在请检查链接); request.getRequestDispatcher(/jsps/msg.jsp).forward(request, response); return; } Cart cart getOrCreateCart(request); // 关键从 session 获取或新建购物车 cart.addBook(book); // 调用购物车业务逻辑 // 重定向到购物车展示页避免 F5 刷新重复加购 response.sendRedirect(request.getContextPath() /cart/show); }逻辑说明getOrCreateCart()从HttpSession中取Cart对象若为 null 则 new 一个并 setAttribute。addBook()内部会检查是否已存在同 bid 图书存在则 quantity否则新增 item。response.sendRedirect()是防止表单重复提交的黄金法则——它让浏览器发起新 GET 请求URL 变为/cart/show此时刷新不会再次触发加购。3.2 购物车对象Cart.java —— 线程安全的内存容器与状态聚合Cart是一个典型的领域模型它不继承任何框架类纯 POJO但封装了电商核心逻辑合并同类项、计算总价、限制最大数量。// src/cn/bookstore/domain/Cart.java public class Cart { private MapString, CartItem map new HashMap(); // key: book.bid, value: CartItem private double total; // 实时总价每次 add/remove 后重新计算 public synchronized void addBook(Book book) { String bid book.getBid(); CartItem item map.get(bid); if (item null) { item new CartItem(); item.setBook(book); item.setQuantity(1); map.put(bid, item); } else { int newQty item.getQuantity() 1; if (newQty 10) { // 防止恶意刷单单本书最多加 10 本 throw new RuntimeException(单本书最多购买10本); } item.setQuantity(newQty); } recalculateTotal(); // 重新计算总价 } private void recalculateTotal() { total 0.0; for (CartItem item : map.values()) { total item.getSubtotal(); // subtotal book.price * quantity } } // getter/setter 省略... }参数说明synchronized修饰addBook()是关键。当多个请求如用户快速连点同时操作同一 session 的 cart 对象时此锁保证map.get()和map.put()原子性避免ConcurrentModificationException或数量错乱。recalculateTotal()在每次变更后调用确保cart.total始终准确无需每次展示时遍历计算——这是性能与一致性的平衡。3.3 订单创建OrderServlet.createOrder() —— 事务边界与状态机落地从购物车结算到生成订单是整个项目最复杂的事务操作涉及orders、order_items、cart_items三张表的写入且必须原子性。OrderServlet将事务控制完全交给OrderService自己只做参数校验和跳转。// src/cn/bookstore/web/servlet/OrderServlet.java protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String address request.getParameter(address); String name request.getParameter(name); String phone request.getParameter(phone); if (address null || name null || phone null) { request.setAttribute(msg, 收货信息不完整); request.getRequestDispatcher(/cart/show).forward(request, response); return; } User user (User) request.getSession().getAttribute(user); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } try { Order order orderService.createOrder(user.getUid(), address, name, phone); request.setAttribute(order, order); request.getRequestDispatcher(/jsps/order/success.jsp).forward(request, response); } catch (Exception e) { e.printStackTrace(); request.setAttribute(msg, 订单创建失败 e.getMessage()); request.getRequestDispatcher(/cart/show).forward(request, response); } }逻辑说明createOrder()是事务方法位于OrderServiceImpl.java。它开启数据库连接先插入orders表status0再批量插入order_items从用户 session 的 cart 中读取最后清空cart_items表或清空 session cart。任一环节失败catch块中执行conn.rollback()所有变更回滚。success.jsp页面显示order.oid和order.total并提供“查看订单详情”链接指向/order/detail?oidxxx。4. 运行与部署从零开始启动绕过 90% 的新手报错别急着mvn clean package——这个项目没有 Maven。它是一个纯粹的 Dynamic Web Project部署方式古老但稳定导出 WAR 包丢进 Tomcat 的webapps目录。但中间有 3 个致命陷阱踩中一个页面就报 500 或白屏。我当年在实验室帮 A 同学 debug 了 4 小时最终发现是mysql-connector-java.jar版本不对。以下步骤经实测Tomcat 8.5.99 MySQL 5.7.42验证有效。4.1 环境准备JDK、Tomcat、MySQL 版本与配置要点JDK必须 JDK 8u202 或更高因UUIDUtil使用java.util.UUID.randomUUID().toString()低版本无此 API。JAVA_HOME指向 JDK 根目录PATH包含%JAVA_HOME%\bin。Tomcat推荐 Apache Tomcat 8.5.x官方支持 Servlet 3.1。解压后修改conf/server.xml确认Connector port8080未被占用conf/tomcat-users.xml添加 manager 用户用于后续热部署role rolenamemanager-gui/ user usernameadmin password123456 rolesmanager-gui/MySQL安装 MySQL 5.78.0 需额外配置useSSLfalseserverTimezoneUTC。创建数据库bookstore字符集utf8mb4排序规则utf8mb4_unicode_ci。执行bookstore.sql导入表结构与初始数据含测试用户test/test123。提示bookstore.sql中CREATE DATABASE bookstore DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这一行不能删否则中文书名存入后变问号。如果已建库用ALTER DATABASE bookstore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;修正。4.2 项目导入与 WAR 打包Eclipse/IntelliJ 手动配置指南Eclipse 步骤File → New → Dynamic Web Project项目名填bookstoreTarget runtime选已配置的 Tomcat 8.5Configuration选Java EE 7 Web Profile兼容 Servlet 3.1Finish后右键项目 →Properties → Project Facets勾选Dynamic Web Module 3.1、Java 1.8、JavaScript 1.0将下载的src文件夹拖入Java Resources/srcWebContent拖入WebContentProject → Properties → Deployment Assembly确认src→/WEB-INF/classesWebContent/WEB-INF/lib/*.jar→/WEB-INF/libRight-click project → Export → WAR file保存为bookstore.war。IntelliJ 步骤File → New → Project from Existing Sources选项目根目录选择Import project as general projectFile → Project Structure → Modules添加Web模块Web resource directory设为WebContentArtifacts → → Web Application: Archive输出路径设为out/artifacts/bookstore_war_explodedBuild → Build Artifacts → bookstore:war → Build。注意无论哪种 IDEWEB-INF/lib下必须有且仅有 4 个 jar。servlet-api.jar不能放在lib下Tomcat 自带否则启动报ClassCastException。若报NoClassDefFoundError: javax/servlet/jsp/JspFactory说明jstl.jar或standard.jar缺失或版本不匹配必须 1.2。4.3 启动与验证访问首页、登录、加购三步确认环境 OK将bookstore.war复制到tomcat/webapps/目录启动 Tomcatbin/startup.batWindows或bin/startup.shLinux/Mac观察logs/catalina.out确认无SEVERE错误出现INFO: Server startup in [xxx] ms浏览器访问http://localhost:8080/bookstore/应看到首页轮播图和图书列表点击右上角“登录”输入test / test123成功跳转到用户中心任选一本图书点击“加入购物车”页面跳转到/cart/show显示图书名称、单价、数量、小计、总计若第 4 步登录失败检查users表中test用户的password是否为MD5(test123abc)abc是bookstore.sql中salt字段值。排查技巧若首页空白打开浏览器开发者工具F12看 Network 标签页找index.jsp的响应内容。如果是HTTP 500看logs/localhost.date.log如果是HTTP 404检查web.xml中welcome-file-list是否为welcome-fileindex.jsp/welcome-file若 CSS/JS 不加载确认static/路径在index.jsp中引用为link relstylesheet href${pageContext.request.contextPath}/static/css/common.css。5. 常见问题排查那些让我凌晨三点还在看 catalina.out 的血泪经验这个项目看似简单但部署时的报错极具迷惑性。很多错误不是代码 bug而是环境、配置、版本的隐式耦合。我把过去帮 12 个同学 debug 的高频问题浓缩成 5 条每条都按“现象 → 原因 → 解决”给出可立即执行的方案。别跳过这一节——它能帮你省下至少 3 小时。5.1 现象首页打开空白浏览器控制台报Failed to load resource: the server responded with a status of 404 ()但index.jsp确实在WebContent/下原因web.xml中welcome-file-list配置错误或 Tomcat 未正确识别项目上下文路径。常见于手动复制文件而非 WAR 部署导致web.xml未被 Tomcat 加载。解决检查WebContent/WEB-INF/web.xml确认welcome-file-list块存在且内容为welcome-file-list welcome-fileindex.jsp/welcome-file /welcome-file-list确认项目部署路径若将bookstore.war放入webapps/则访问http://localhost:8080/bookstore/若解压为webapps/bookstore/文件夹则路径相同。切勿访问http://localhost:8080/那是 Tomcat 根。强制刷新浏览器缓存CtrlF5或尝试访问http://localhost:8080/bookstore/index.jsp直接路径。5.2 现象登录时输入正确账号密码页面跳转到login.jsp并提示“用户名或密码错误”但数据库中数据无误原因密码比对逻辑使用了 salt而bookstore.sql中users.salt字段值未被正确读取或UserDaoImpl.java中findUserByUsername()方法未拼接 salt。解决登录 MySQL执行SELECT username, password, salt FROM users WHERE usernametest;确认salt值为abc默认值打开src/cn/bookstore/dao/UserDaoImpl.java找到findUserByUsername()方法确认其密码校验逻辑为String inputPass MD5Utils.md5(inputPassword user.getSalt()); // 关键必须拼接 salt if (inputPass.equals(user.getPassword())) { ... }若MD5Utils类不存在检查src/cn/bookstore/util/下是否有MD5Utils.java其md5(String str)方法是否为标准 MD5 实现16 进制小写 32 位字符串。5.3 现象购物车页面显示“购物车为空”但CartServlet.addBook()已执行session.getAttribute(cart)返回非 null原因Cart对象未实现Serializable接口导致 Tomcat 在 session 持久化如重启时序列化失败session.getAttribute()返回 null后续请求新建空 cart。解决打开src/cn/bookstore/domain/Cart.java确认类声明为public class Cart implements Serializable添加private static final long serialVersionUID 1L;固定值避免反序列化失败同样检查CartItem.java、Book.java、User.java是否均实现Serializable。5.4 现象创建订单时页面报500 java.lang.NoClassDefFoundError: com/mysql/jdbc/Driver但mysql-connector-java-5.1.47.jar已在WEB-INF/lib/下原因JAR 包版本与 MySQL 服务器不兼容。mysql-connector-java-5.1.x仅支持 MySQL 5.5-5.7若用 MySQL 8.0需升级到8.0.28并在ConnectionUtil.java的 JDBC URL 后加参数。解决查看 MySQL 版本mysql --version若为 MySQL 8.0下载mysql-connector-java-8.0.28.jar替换WEB-INF/lib/下旧 jar修改src/cn/bookstore/util/ConnectionUtil.java中的 URL// MySQL 5.7 用 private static final String URL jdbc:mysql://localhost:3306/bookstore?useUnicodetruecharacterEncodingUTF-8; // MySQL 8.0 用必须加 serverTimezone private static final String URL jdbc:mysql://localhost:3306/bookstore?useUnicodetruecharacterEncodingUTF-8serverTimezoneUTCuseSSLfalse;5.5 现象管理员后台admin/index.jsp打开后左侧菜单栏显示乱码如“图Êé”但数据库和页面 HTML 均声明 UTF-8原因web.xml中未配置CharacterEncodingFilter或EncodingFilter.java的init()方法未设置request.setCharacterEncoding(UTF-8)。解决检查web.xml确认filter和filter-mapping存在filter filter-nameencodingFilter/filter-name filter-classcn.bookstore.web.filter.EncodingFilter/filter-class /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping打开src/cn/bookstore/web/filter/EncodingFilter.java确认doFilter()方法中有request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); chain.doFilter(request, response);6. 二次开发实战从“能跑”到“能用”三个必改点与一个后悔药机制拿到这个项目很多人第一反应是“交差”但如果你真想把它变成自己的作品或者为后续课程打基础有三个地方必须动手改——不是为了炫技而是解决真实痛点。我当年在某高校实验室带课时发现 80% 的学生卡在这三步登录态失效太快、购物车不能跨设备同步、订单状态无法人工干预。下面给出具体改法、验证方式以及一个我自用的“后悔药”机制确保改崩了也能秒级回滚。6.1 必改点一延长 Session 有效期解决“看两页书就掉登录”的体验灾难默认 Tomcat 的session-timeout是 30 分钟用户浏览图书列表、查看详情、加购稍一犹豫就跳回登录页。这不是安全是反人类。改法极简只需两处改法修改WebContent/WEB-INF/web.xml在web-app根节点内添加session-config session-timeout120/session-timeout !-- 单位分钟 -- /session-config在LoginServlet.java的登录成功逻辑后强制设置 session 最后访问时间// src/cn/bookstore/web/servlet/LoginServlet.java HttpSession session request.getSession(true); session.setMaxInactiveInterval(120 * 60); // 120 分钟单位秒 session.setAttribute(user, user);验证登录后打开浏览器开发者工具 → Application → Storage → Cookies找到JSESSIONID看Expires / Max-Age是否为当前时间 120 分钟。然后等待 35 分钟刷新任意页面确认未跳转登录页。提示session.setMaxInactiveInterval()优先级高于web.xml两者设不同值时以后者为准。生产环境建议设为 30 分钟此处为开发体验优化。6.2 必改点二购物车持久化到数据库支持“手机加购、电脑下单”当前购物车只存 session用户关浏览器或换设备就丢失。要支持跨终端必须落库。我们复用现有cart_items表改造CartServlet和Cart类改法在Cart.java中添加saveToDB(String uid)方法调用CartDaoImpl.saveCart(uid, this.map.values())修改CartServlet.doPost()的addBook()后追加User user (User) request.getSession().getAttribute(user); if (user ! null) { cart.saveToDB(user.getUid()); // 登录用户才持久化 }在CartServlet.showCart()中从数据库加载购物车若 session 无 cartCart cart (Cart) session.getAttribute(cart); if (cart null user ! null) { cart new CartDaoImpl().loadCartByUid(user.getUid()); session.setAttribute(cart, cart); }验证用 Chrome 登录加购两本书用 Edge 访问同一网址登录同一账号进入/cart/show确认商品已存在。6.3 必改点三订单状态机增强增加“取消订单”与“退款”按钮原订单状态只有 0→1→2→3 单向流转缺少用户主动取消和管理员退款能力。我们在OrderServlet中新增cancelOrder()和refundOrder()方法并在order/detail.jsp添加按钮改法在OrderServlet.java添加protected void cancelOrder(HttpServletRequest request, HttpServletResponse response) { String oid request.getParameter(oid); User user (User) request.getSession().getAttribute(user); if (user null) throw new RuntimeException(未登录); orderService.cancelOrder(oid, user.getUid()); // status0→-1已取消 response.sendRedirect(request.getContextPath() /order/list); }在OrderServiceImpl.java的cancelOrder()中执行 SQLUPDATE orders SET status -1 WHERE oid ? AND uid ? AND status 0;在order/detail.jsp的订单状态下方添加c:if test${order.status 0} a href${pageContext.request.contextPath}/order?methodcanceloid${order.oid}取消订单/a /c:if验证创建订单后立即点击“取消订单”刷新订单列表确认该订单状态变为“已取消”。6.4 我的后悔药机制Git 分支 SQL 备份脚本改崩了 10 秒回滚二次开发最怕改错核心逻辑比如把orderService.createOrder()的事务 rollback 写成 commit。我的做法是每次修改前先打 Git 标签 备份数据库。这不是过度工程是血泪经验。操作清单5 行命令10 秒完成# 1. 在项目根目录初始化 Git若无 git init # 2. 添加所有文件并提交首次 git add . git commit -m initial commit # 3. 创建 feature 分支如改购物车 git checkout -b feat-persistent-cart # 4. 修改代码后备份当前数据库Linux/Mac mysqldump -u root -p bookstore backup_bookstore_$(date %Y%m%d_%H%M%S).sql # 5. 若改崩10 秒回滚 git reset --hard HEAD # 代码回退 mysql -u root -p bookstore backup_bookstore_20240520_102345.sql # 数据回退从那以后我每次改OrderService或ConnectionUtil都强制走一遍这个流程。不是信不过自己是信不过“就改一行”的幻觉。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →