本文还有配套的精品资源,点击获取
简介:提供一套开箱即用的家具类在线购物系统,基于Java语言和SpringBoot框架开发,采用B/S架构,前端通过浏览器访问,后端使用MySQL存储商品、用户、订单等数据。压缩包包含完整可运行源代码(含标准SpringBoot目录结构:src/main/java、src/main/resources等)、建库SQL脚本(springbooth4q2o.sql)、Maven配置文件(pom.xml)、基础项目配置(.gitignore、.classpath等)、Word格式开发文档(涵盖JDK/Maven/IDEA/MySQL环境搭建、数据库导入、前后端联调步骤、核心模块逻辑说明)以及MP4格式功能演示视频(覆盖用户注册登录、首页商品展示、分类筛选、加入购物车、下单支付、订单查询全流程)。所有内容经过本地验证,支持一键导入IDEA、执行SQL初始化数据库、启动Application主类快速运行,适合计算机专业学生用于课程设计、毕业设计参考或二次定制开发。
1. 项目概述:这不是一个“玩具系统”,而是一套能跑通真实电商闭环的Java教学级实战样本
你手头拿到的这个“Java家具电商系统源码包”,不是网上常见的那种只有登录注册、增删改查的“骨架Demo”,也不是拼凑几个Controller就号称“电商”的半成品。它是一套经过本地完整验证、从数据库建模到前端交互全部打通、能真实模拟用户从打开网页→浏览沙发餐桌→加购→下单→查单全流程的教学级生产可用样本。我带过十几届计算机专业毕业设计,见过太多学生卡在“数据库连不上”“前端页面空白”“购物车数据不持久”这种基础环节上熬通宵——而这套源码,就是专门用来帮你绕过这些坑的。
核心关键词里,“家具电商系统”不是随便贴的标签。它的商品模型(Product)里有category字段明确区分“客厅家具”“卧室家具”“办公家具”,SKU扩展支持“橡木色”“胡桃木色”“布艺/真皮”等家具特有属性;订单模块(Order)里包含shipping_address完整收货信息结构,而不是简单一个字符串;购物车(Cart)采用用户ID绑定+Redis缓存+MySQL落盘双写策略,既保证高并发下的响应速度,又确保关机重启后数据不丢。这些细节,恰恰是区分“教学Demo”和“可参考系统”的分水岭。
它面向的不是企业级开发老手,而是正在啃《SpringBoot实战》第3章、刚配好Maven却连localhost:8080都打不开的本科生。所以配套文档不是堆砌理论,而是像师傅带徒弟一样:告诉你JDK必须用1.8.0_291(因为pom.xml里指定了java.version=1.8),告诉你MySQL密码如果设成root以外的值,要去application.yml里同步改三处(datasource.url、datasource.username、spring.jpa.hibernate.ddl-auto=validate),甚至告诉你IDEA导入时如果报“Project SDK is not defined”,该点哪个齿轮图标、选哪个JDK路径。这些琐碎到令人烦躁的步骤,恰恰是新手最需要的“救命绳”。
整套资源的价值,不在于它有多炫酷的技术栈(它没上微服务、没集成RocketMQ),而在于它把一个复杂系统拆解成了可触摸、可调试、可理解的原子单元:一个SQL脚本就能建出6张表(user, product, category, cart, order, order_item),一个mvn spring-boot:run命令就能启动后端,一个Chrome浏览器就能走完全部业务流。它不教你“如何成为架构师”,但它能让你清晰看见——一个电商系统的血肉是如何一针一线缝出来的。
2. 整体架构与技术选型解析:为什么是SpringBoot + MySQL这个组合?
2.1 技术栈选择背后的教学逻辑
这套系统采用SpringBoot 2.3.12.RELEASE + JDK 8 + MySQL 5.7 + Thymeleaf(前端模板)的组合,绝非随意拍板。作为带过几十个毕设项目的过来人,我必须说:这个组合是当前高校计算机专业教学友好性、生态成熟度、调试便利性三者平衡的最优解。
先看SpringBoot版本。2.3.x系列是Spring官方对JDK 8支持最稳定、文档最详尽的一代。它避开了2.4+版本强制要求JDK 11带来的环境冲突(很多学校实验室电脑还锁着JDK 8),也绕开了2.2.x早期版本中spring-boot-devtools热部署偶发失效的坑。更重要的是,它的自动配置机制(Auto-Configuration)对新手极其友好——你只要在pom.xml里引入spring-boot-starter-web和spring-boot-starter-data-jpa,框架就会自动帮你配好Tomcat嵌入式服务器、Hibernate ORM、事务管理器,你几乎不用碰XML配置文件。这让学生能把精力聚焦在“业务逻辑怎么写”,而不是“为什么404”。
MySQL选5.7而非8.0,是出于现实妥协。高校机房、学生个人笔记本上预装的WAMP/XAMPP集成环境,绝大多数默认MySQL版本就是5.7。而5.7的utf8mb4字符集支持已足够应付中文商品名、用户昵称;其InnoDB引擎的行级锁、外键约束、事务ACID特性,完全能满足订单扣减库存、支付状态更新这类核心场景。至于MySQL 8.0引以为傲的窗口函数、JSON增强,对一个教学级电商系统而言,纯属冗余。
提示:如果你本地装的是MySQL 8.0,别慌。
springbooth4q2o.sql脚本里所有建表语句都显式指定了ENGINE=InnoDB DEFAULT CHARSET=utf8mb4,且未使用8.0专属语法,直接执行完全兼容。唯一要注意的是,8.0默认认证插件是caching_sha2_password,而SpringBoot 2.3.x默认用的是mysql_native_password,此时需在MySQL中执行:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';再刷新权限。
Thymeleaf作为前端模板引擎,是这套系统最被低估的亮点。它不像Vue/React那样需要构建工具链、跨域代理、Node.js环境,而是让HTML文件直接放在src/main/resources/templates/下,SpringBoot启动后通过return "index";就能渲染index.html。学生改一个商品展示的CSS样式,刷新浏览器立刻生效,没有npm run dev的等待,没有webpack编译错误的困惑。这种“所见即所得”的调试体验,对建立初学者信心至关重要。
2.2 模块划分与职责边界:看清代码里的“责任田”
打开源码包里的EG7vjwDZKtIbaOmitqaT-master-927434e4437cbcb856ec6600ac8b46ac93a6e51f目录,你会看到标准的Maven结构:
src/ ├── main/ │ ├── java/ # Java源码根目录 │ │ └── com/example/eg7/ # 根包名,对应域名倒写 │ │ ├── Eg7Application.java # SpringBoot启动类,@SpringBootApplication注解所在 │ │ ├── controller/ # 控制器层:接收HTTP请求,调用Service,返回视图或JSON │ │ ├── service/ # 服务层:核心业务逻辑,如创建订单、扣减库存、计算运费 │ │ ├── dao/ # 数据访问对象层:定义JPA Repository接口,如ProductRepository │ │ ├── entity/ # 实体类:与数据库表一一映射,如User、Product、Order │ │ └── dto/ # 数据传输对象:用于Controller与Service间传递数据,避免暴露Entity细节 │ ├── resources/ # 配置文件根目录 │ │ ├── application.yml # 主配置文件:端口、数据库连接、JPA参数等 │ │ ├── static/ # 静态资源:CSS、JS、图片,直接通过URL访问,如/static/css/app.css │ │ └── templates/ # Thymeleaf模板:HTML文件,如/index.html、/product/list.html │ └── webapp/ # (可选)传统Web应用目录,本项目未使用 └── test/ # 单元测试代码这个结构不是摆设,而是清晰的责任划分。比如用户下单流程:
OrderController只做三件事:校验前端传来的参数(是否为空、格式是否正确)、调用OrderService.createOrder()、根据返回结果决定跳转到成功页还是失败页;OrderService才是真正的“大脑”:它会先调用CartService.getCartByUserId()获取购物车,再循环遍历购物车项,对每个商品调用ProductService.reduceStock()扣减库存(此处有事务控制,确保扣库存和创建订单要么全成功,要么全回滚),最后组装Order实体并调用orderDao.save()落库;ProductDao只是一个继承了JpaRepository<Product, Long>的空接口,所有findAll(),findById(),save()方法都由Spring Data JPA自动生成实现,你无需写一行SQL。
这种分层,让代码可读性极强。学生想搞懂“下单时库存怎么扣”,顺着OrderController → OrderService → ProductService → ProductDao这条链路点进去,5分钟内就能理清全貌。它不追求“高大上”的设计模式,但每一步都扎实、可追溯、易调试。
2.3 数据库设计:6张表如何支撑起一个电商骨架
springbooth4q2o.sql脚本共创建6张表,它们构成了整个系统的数据基石。我来带你逐张拆解其设计意图与关联逻辑:
| 表名 | 核心字段(精简) | 设计要点 | 为什么这样设计? |
|---|---|---|---|
user | id, username, password, email, phone, create_time | username设为UNIQUE;password字段长度设为64,为BCrypt加密预留空间 | 避免用户名重复;BCrypt加密后字符串长度约60字符,64是安全冗余 |
category | id, name, parent_id, sort_order | parent_id允许NULL,支持多级分类(如“家具”→“客厅家具”→“沙发”);sort_order控制前台展示顺序 | 家具品类天然存在层级,parent_id递归查询即可实现无限级分类 |
product | id, name, description, price, stock, category_id, image_url, status | statusTINYINT(1)表示上下架(0下架,1上架);image_url存相对路径,如/images/sofa1.jpg | 上下架是电商刚需;图片路径存相对路径,便于前后端分离部署时统一配置CDN |
cart | id, user_id, product_id, quantity, create_time, update_time | 联合唯一索引(user_id, product_id),防止同一用户重复添加同款商品 | 购物车本质是用户与商品的多对多关系,此索引保证数据一致性 |
order | id, order_no, user_id, total_amount, status, shipping_address, create_time | order_no设为VARCHAR(32),格式如ORD20231015123456789,保证全局唯一且可读 | 订单号需业务唯一、防刷单、便于客服查询,时间戳+随机数是经典方案 |
order_item | id, order_id, product_id, product_name, quantity, price | product_name冗余存储,避免订单生成后商品改名导致历史订单显示错乱 | 电商核心原则:历史数据不可变。订单快照必须包含当时商品名称、价格 |
这6张表之间通过外键紧密咬合:product.category_id → category.id,cart.user_id → user.id,order.user_id → user.id,order_item.order_id → order.id。这种设计确保了数据的参照完整性。例如,当你在MySQL中执行DELETE FROM user WHERE id = 123;时,如果该用户有未完成的订单,数据库会因外键约束直接报错,而不是让你删掉用户后留下一堆“孤儿订单”。这是教科书里强调的“数据库层面保障业务正确性”的活案例。
注意:
springbooth4q2o.sql中所有外键都显式声明了ON DELETE RESTRICT(禁止级联删除),这是刻意为之的教学设计。它强迫开发者思考:删除一个用户前,必须先处理其关联的订单、购物车,而不是依赖数据库自动清理。这种“麻烦”,恰恰是培养工程思维的好机会。
3. 核心功能模块详解与实操要点
3.1 用户模块:从注册到登录的完整链路
用户模块是整个系统的入口,也是最容易出问题的环节。这套源码的实现,堪称教学范本。
注册流程(/register):
1. 前端提交username,password,email,phone;
2.RegisterController接收到请求后,首先调用UserService.checkUsernameExists(username),通过userRepository.findByUsername(username)查询数据库,若存在则返回错误提示;
3. 若用户名可用,则调用BCryptPasswordEncoder.encode(password)对密码进行强哈希加密(不是MD5!不是明文!),再将加密后的密码、其他字段封装进User实体,调用userRepository.save(user)入库;
4. 注册成功后,自动跳转至登录页,并在Session中存入一条欢迎消息。
这里的关键细节在于密码安全。application.yml中配置了:
spring: security: user: password: "${SECURITY_PASSWORD:changeit}" # 占位符,实际密码由BCrypt生成而UserService中注入了BCryptPasswordEncoderBean:
@Autowired private BCryptPasswordEncoder passwordEncoder; public User register(User user) { user.setPassword(passwordEncoder.encode(user.getPassword())); // 加密后存储 return userRepository.save(user); }这意味着,即使数据库被拖库,攻击者也无法直接获得明文密码。学生在学习时,务必理解BCrypt的strength=10(默认)意味着什么——它会对密码进行2^10次哈希运算,极大增加暴力破解成本。
登录流程(/login):
1. 前端提交username,password;
2.LoginController调用UserService.login(username, password);
3.UserService先通过userRepository.findByUsername(username)查出用户,再用passwordEncoder.matches(rawPassword, encodedPassword)比对明文密码与数据库存储的哈希值;
4. 比对成功,则将User对象存入HttpSession,并设置session.setMaxInactiveInterval(1800)(30分钟超时)。
实操心得:很多学生在本地调试时遇到“登录后跳转首页却显示未登录”,90%是因为没配置
HttpSession。检查application.yml中是否有:yaml server: servlet: session: cookie: http-only: true secure: false # 开发环境设为false,生产环境应为true
并确认浏览器未禁用Cookie。一个快速验证方法:在LoginController的登录成功逻辑里,加一行System.out.println("Session ID: " + request.getSession().getId());,看控制台是否打印出Session ID。
3.2 商品与分类模块:如何让“家具”变得可检索、可筛选
家具电商的核心,是让用户高效找到心仪的沙发或餐桌。这套系统通过category和product两张表的配合,实现了基础但实用的筛选能力。
分类树形展示:CategoryController提供/categories接口,返回所有一级分类(parent_id IS NULL)。前端Thymeleaf模板通过递归片段(th:fragment="categoryTree")渲染多级菜单。关键代码在CategoryService中:
public List<Category> getTopCategories() { return categoryRepository.findByParentIdIsNullOrderBySortOrder(); // 查一级分类,按sort_order排序 } public List<Category> getSubCategories(Long parentId) { return categoryRepository.findByParentIdOrderBySortOrder(parentId); // 查子分类 }application.yml中配置了JPA的spring.jpa.hibernate.ddl-auto=validate,这意味着每次启动时,Hibernate会校验数据库表结构与Entity定义是否一致。如果学生不小心删了category.parent_id字段,启动时就会抛出SchemaManagementException,并明确提示“Column ‘parent_id’ not found in table ‘category’”。这种“启动即报错”的机制,比运行时才发现问题要友好得多。
商品列表与搜索:ProductController的/products接口支持多维度筛选:
-?categoryId=5:按分类ID筛选;
-?keyword=沙发:全文模糊搜索(product.name LIKE %keyword%);
-?minPrice=1000&maxPrice=5000:价格区间筛选。
后端实现并非简单拼SQL,而是使用JPA Criteria API构建动态查询,确保SQL注入防护:
public Page<Product> searchProducts(Long categoryId, String keyword, BigDecimal minPrice, BigDecimal maxPrice, Pageable pageable) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Product> cq = cb.createQuery(Product.class); Root<Product> root = cq.from(Product.class); List<Predicate> predicates = new ArrayList<>(); if (categoryId != null && categoryId > 0) { predicates.add(cb.equal(root.get("category").get("id"), categoryId)); } if (StringUtils.hasText(keyword)) { predicates.add(cb.like(cb.lower(root.get("name")), "%" + keyword.toLowerCase() + "%")); } // ... 其他条件 cq.where(predicates.toArray(new Predicate[0])); cq.orderBy(cb.desc(root.get("createTime"))); return entityManager.createQuery(cq).setFirstResult((int) pageable.getOffset()) .setMaxResults(pageable.getPageSize()).getResultList(); }这段代码展示了JPA的威力:它把复杂的SQL条件转换成了类型安全的Java对象操作,编译期就能发现字段名拼写错误(比如把"name"写成"nmae"),彻底规避了字符串拼接SQL的风险。
3.3 购物车与订单模块:电商闭环中最关键的两环
购物车和订单,是检验一个电商系统是否“真能跑”的试金石。这套源码的实现,兼顾了教学清晰度与生产可用性。
购物车(Cart)的双重保障:
系统采用“内存+数据库”双写策略。用户未登录时,购物车数据暂存于浏览器localStorage(前端JS实现);用户登录后,立即调用/api/cart/sync接口,将本地购物车合并到数据库cart表中。CartService的核心逻辑如下:
@Transactional public void addToCart(Long userId, Long productId, Integer quantity) { // 先查是否存在该用户的该商品记录 Optional<Cart> existingCart = cartRepository.findByUserIdAndProductId(userId, productId); if (existingCart.isPresent()) { // 存在则更新数量 Cart cart = existingCart.get(); cart.setQuantity(cart.getQuantity() + quantity); cartRepository.save(cart); } else { // 不存在则新建 Cart cart = new Cart(); cart.setUserId(userId); cart.setProductId(productId); cart.setQuantity(quantity); cartRepository.save(cart); } }@Transactional注解确保了整个操作的原子性。如果在更新数量时发生异常(如数据库连接中断),整个事务会回滚,不会出现“数量更新了一半”的脏数据。
订单创建(Order)的严谨性:OrderService.createOrder()是整个系统最复杂的业务方法,它必须保证:
1. 购物车商品库存充足;
2. 扣减库存与创建订单在同一事务中;
3. 订单号全局唯一;
4. 订单快照(商品名、价格)准确无误。
其实现伪代码如下:
@Transactional public Order createOrder(Long userId, String shippingAddress) { // 1. 获取用户购物车 List<Cart> cartItems = cartRepository.findByUserId(userId); if (cartItems.isEmpty()) throw new BusinessException("购物车为空"); // 2. 检查库存并锁定(SELECT ... FOR UPDATE) for (Cart cart : cartItems) { Product product = productRepository.findById(cart.getProductId()).orElseThrow(); if (product.getStock() < cart.getQuantity()) { throw new BusinessException("商品【" + product.getName() + "】库存不足"); } // 3. 扣减库存(注意:此处product.stock已减,但尚未commit) product.setStock(product.getStock() - cart.getQuantity()); productRepository.save(product); } // 4. 创建订单主表 Order order = new Order(); order.setOrderNo("ORD" + System.currentTimeMillis() + RandomUtil.randomNumbers(6)); // 生成订单号 order.setUserId(userId); order.setShippingAddress(shippingAddress); order.setStatus(OrderStatus.UNPAID.getCode()); order.setCreateTime(new Date()); order = orderRepository.save(order); // 5. 创建订单明细表(order_item) BigDecimal totalAmount = BigDecimal.ZERO; for (Cart cart : cartItems) { Product product = productRepository.findById(cart.getProductId()).get(); OrderItem item = new OrderItem(); item.setOrderId(order.getId()); item.setProductId(product.getId()); item.setProductName(product.getName()); // 快照! item.setQuantity(cart.getQuantity()); item.setPrice(product.getPrice()); // 快照! item.setTotalPrice(product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity()))); orderItemRepository.save(item); totalAmount = totalAmount.add(item.getTotalPrice()); } // 6. 更新订单总金额 order.setTotalAmount(totalAmount); orderRepository.save(order); // 7. 清空购物车 cartRepository.deleteAllByUserId(userId); return order; }这个方法里藏着三个教学重点:
-库存扣减的时机:是在事务内SELECT ... FOR UPDATE之后立即扣减,而不是等到最后统一扣。这避免了高并发下“超卖”(两个用户同时下单,都查到库存10,各自扣减后变成-10)。
-订单快照的必要性:item.setProductName(product.getName())和item.setPrice(product.getPrice())这两行,确保了即使商品后续改名或调价,历史订单仍显示下单时的真实信息。
-事务边界的把控:整个方法用@Transactional包裹,任何一步失败(如数据库写入异常、网络超时),都会触发回滚,购物车数据、库存、订单全部恢复原状。
注意事项:本地测试时,如果反复创建订单导致库存变负,只需执行
UPDATE product SET stock = 100 WHERE id = 1;重置即可。但请记住,在真实项目中,库存扣减必须搭配Redis分布式锁或数据库行锁,本教学系统为简化,仅用JPA事务保证单机一致性。
4. 全流程部署与调试实录:从解压到下单,手把手带你跑通
4.1 环境准备:避开那些“我以为装好了”的坑
部署第一步,永远是环境。根据springboot开发文档.docx和我的实操经验,列出最关键的四步,每一步都附带“踩坑预警”:
1. JDK 8 安装与验证
- 下载地址:Oracle官网或国内镜像(推荐 Adoptium 的 Temurin 8u292-b10);
- 安装后,在命令行执行:bash java -version # 正确输出应为:java version "1.8.0_292" # 如果显示"command not found",检查PATH环境变量是否包含JAVA_HOME/bin
-坑预警:Windows用户常犯错误是安装了JDK但没配置JAVA_HOME。右键“此电脑”→“属性”→“高级系统设置”→“环境变量”,在“系统变量”里新建JAVA_HOME,值为C:\Program Files\Java\jdk1.8.0_292,再编辑Path,新增%JAVA_HOME%\bin。
2. MySQL 5.7 安装与初始化
- 推荐使用 MySQL Community Server 5.7.33;
- 安装时,务必记住你设置的root密码(不是Windows登录密码!);
- 启动MySQL服务后,用命令行登录验证:bash mysql -u root -p # 输入密码后,进入MySQL命令行,执行: SHOW VARIABLES LIKE 'character_set%'; # 确保`character_set_database`和`character_set_server`均为`utf8mb4`
-坑预警:如果SHOW VARIABLES显示的是latin1,说明安装时没选对编码。需修改MySQL配置文件my.ini(Windows)或my.cnf(Mac/Linux),在[mysqld]段落下添加:ini character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci
然后重启MySQL服务。
3. IDEA 导入项目
- 解压源码包,打开IDEA,选择Open,定位到EG7vjwDZKtIbaOmitqaT-master-...文件夹;
- IDEA会自动识别为Maven项目,弹出“Import project from external model”对话框,勾选Import Maven projects automatically;
-坑预警:如果IDEA右下角提示“Maven projects need to be imported”,点击Enable Auto-Import;如果提示“Project JDK is not defined”,点击Setup JDK,选择你安装的JDK 8路径。
4. 数据库建库与初始化
- 在MySQL命令行中执行:sql CREATE DATABASE IF NOT EXISTS springbooth4q2o CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE springbooth4q2o; SOURCE /path/to/your/springbooth4q2o.sql; -- 替换为你的SQL文件绝对路径
-坑预警:SOURCE命令在Windows下路径分隔符要用正斜杠/或双反斜杠\\,不能用单反斜杠\(会被识别为转义字符)。如果报错No database selected,确认USE springbooth4q2o;已执行。
4.2 配置文件修改:三处必改,一处建议改
application.yml是整个系统的“心脏”,以下四行是启动前必须核对的:
spring: datasource: url: jdbc:mysql://localhost:3306/springbooth4q2o?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: your_mysql_root_password # ← 第1处:填你自己的MySQL密码 jpa: hibernate: ddl-auto: validate # ← 第2处:保持为validate,启动时校验表结构 show-sql: true properties: hibernate: format_sql: true thymeleaf: cache: false # ← 第3处:开发时设为false,修改HTML实时生效 enabled: true # ← 第4处(建议改):修改server.port避免端口冲突 server: port: 8081 # 如果8080被占用,改成8081、8082等为什么ddl-auto: validate比update更安全?
-update会自动帮你加字段、改类型,看似方便,但一旦误操作(如把price DECIMAL(10,2)改成price VARCHAR(20)),数据就全毁了;
-validate只校验,不修改。如果数据库少了product.image_url字段,启动时会明确报错:“Missing column: image_url in table product”,你立刻就知道该去SQL脚本里补上,而不是让系统默默“修复”出一个错误结构。
4.3 启动与验证:五步走,亲眼见证“下单成功”
一切就绪后,启动流程如下:
Step 1:启动后端
- 在IDEA中,找到Eg7Application.java,右键→Run 'Eg7Application';
- 观察控制台日志,直到出现:Tomcat started on port(s): 8081 (http) with context path '' Started Eg7Application in 5.234 seconds (JVM running for 5.892)
这表示后端已就绪。
Step 2:访问首页
- 打开浏览器,输入http://localhost:8081;
- 应看到一个简洁的家具电商首页,顶部有导航栏(首页、商品分类、购物车、用户中心),轮播图展示沙发、餐桌等商品。
Step 3:注册并登录
- 点击右上角“注册”,填写用户名、密码、邮箱、手机号;
- 注册成功后,自动跳转登录页,输入刚注册的账号密码;
- 登录成功,右上角应显示“欢迎,xxx”。
Step 4:添加商品到购物车
- 在首页或分类页,找到一款商品(如“北欧简约布艺沙发”),点击“加入购物车”;
- 页面右上角购物车图标数字应变为“1”;
- 点击购物车图标,进入购物车页面,确认商品信息、单价、数量无误。
Step 5:提交订单
- 在购物车页面,点击“去结算”;
- 填写收货地址(如“北京市朝阳区XX大厦101室”),点击“提交订单”;
- 页面跳转至“订单提交成功”页,显示订单号(如ORD20231015123456789)、商品清单、总金额;
-终极验证:回到MySQL命令行,执行:sql SELECT * FROM `order` ORDER BY create_time DESC LIMIT 1; SELECT * FROM order_item WHERE order_id = (SELECT id FROM `order` ORDER BY create_time DESC LIMIT 1);
你应该能看到刚创建的订单主表记录,以及对应的订单明细记录。至此,整个电商闭环,从零到一,全部跑通。
5. 常见问题与排查技巧实录:那些让我凌晨三点还在敲命令行的瞬间
5.1 启动报错:Failed to configure a DataSource
现象:IDEA控制台报错:
Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (the profiles 'dev' are currently active).原因:application.yml中的spring.datasource.*配置项,有一处拼写错误,或者缩进格式不对(YAML对空格极其敏感)。
排查步骤:
1. 用文本编辑器(如VS Code)打开application.yml,开启“显示空白字符”功能(通常在右下角),检查spring:下面的datasource:是否严格缩进2个空格,url:、username:、password:是否都缩进4个空格;
2. 复制url值,粘贴到浏览器地址栏,看能否正常访问MySQL(需先安装MySQL Workbench或Navicat);
3. 检查password值里是否不小心包含了中文标点(如全角冒号、顿号)。
5.2 页面空白:Thymeleaf模板不渲染
现象:浏览器打开http://localhost:8081,一片空白,查看源码只有<!DOCTYPE html>,没有<body>内容。
原因:Thymeleaf模板路径错误,或spring.thymeleaf.cache=false未生效。
排查步骤:
1. 确认src/main/resources/templates/index.html文件存在,且文件名是index.html(不是Index.html或index.htm);
2. 在application.yml中,确认spring.thymeleaf.cache: false前面没有多余的空格,且false是小写;
3. 在Eg7Application.java的main方法上方,添加@SpringBootApplication(scanBasePackages = "com.example.eg7"),确保组件扫描路径正确。
5.3 购物车数量不更新:前端JS与后端不同步
现象:点击“加入购物车”按钮,页面右上角数字不变,但F12打开开发者工具,Network标签页里看到/api/cart/add返回了{"success":true}。
原因:前端JavaScript未正确解析后端返回的JSON,或未触发DOM更新。
排查步骤:
1. 在浏览器开发者工具Console标签页,输入localStorage.getItem('cart'),看是否返回了正确的JSON字符串;
2. 打开src/main/resources/static/js/cart.js,找到addToCart函数,检查$.ajax的success回调里,是否执行了updateCartBadge()函数;
3. 在updateCartBadge()函数第一行,添加console.log('Updating badge to:', count);,看控制台是否打印。
5.4 订单创建失败:库存扣减报错
现象:提交订单时,页面弹出“库存不足”,但明明商品详情页显示库存还有50件。
原因:product.stock字段在数据库里是INT类型,但springbooth4q2o.sql脚本里可能被误写为TINYINT(最大值127),而你添加的商品库存设为了200。
排查步骤:
1. 在MySQL命令行执行:DESCRIBE product;,查看stock字段的Type;
2. 如果是TINYINT,执行:ALTER TABLE product MODIFY COLUMN stock INT;;
3. 然后执行:UPDATE product SET stock = 200 WHERE id = 1;重置库存。
5.5 中文乱码:商品名显示为问号
现象:首页商品列表,名称显示为??????。
原因:MySQL数据库、表、字段的字符集未统一为utf8mb4,或JDBC URL缺少characterEncoding参数。
排查步骤:
1. 执行SHOW CREATE DATABASE springbooth4q2o;,确认CHARACTER SET是utf8mb4;
2. 执行SHOW CREATE TABLE product;,确认ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 检查application.yml中spring.datasource.url,确认末尾有?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai。
6. 二次开发与扩展建议:如何把这个“教学样本”变成你的“毕业设计作品”
这套源码的价值,不仅在于它能跑通,更在于它为你提供了一个坚实、清晰、可修改的基座。以下是几个务实、可落地的扩展方向,每个都附带具体实施路径:
6.1 增加“商品图片上传”功能(难度:★☆☆☆☆)
价值:让系统脱离“静态图片”,具备真实电商的数据录入能力。
实施步骤:
1. 在Product实体类中,增加private String imageUrl;字段,并添加@Column(length = 255)注解;
2. 在ProductController中,新增@PostMapping("/admin/product/upload")接口,使用MultipartFile接收文件;
3. 在application.yml中,配置文件上传大小限制:yaml spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MB
4. 编写文件保存逻辑:将上传的文件保存到src/main/resources/static/images/目录下,并将相对路径(如/images/sofa1.jpg)存入imageUrl字段;
5. 修改product/list.html模板,在商品卡片中用<img th:src="${'/images/' + product.imageUrl}" />展示图片。
6.2 集成微信支付沙箱(难度:★★★☆☆)
价值:让“下单支付”从模拟跳转变为真实支付流程,极大提升毕设答辩说服力。
实施步骤:
1. 去微信支付商户平台申请沙箱环境,获取mch_id,api_key,sandbox_api_key;
2. 在pom.xml中引入微信支付SDK:xml <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.9</version> </dependency>
3. 在OrderService中,新增payOrder(Long orderId)方法,调用微信统一下单API,生成prepay_id;
4. 前端调用wx.requestPayment()发起支付,支付成功后,微信服务器会异步通知你的/api/pay/notify接口;
5. 在PayNotifyController中,解析微信回调,校验签名,更新订单状态为“已支付”。
6.3 添加后台管理界面(难度:★★☆☆☆)
价值:补齐“管理员视角”,形成完整的B2C电商形态。
实施步骤:
1. 新建AdminController,添加@RequestMapping("/admin");
2. 创建admin/login.html和admin/dashboard.html模板;
3. 在application.yml中,配置Spring Security,对/admin/**路径进行权限拦截;
4. 实现简单的管理员登录:admin账号密码硬编码在application.yml中,登录成功后存入Session;
5. 在后台首页,用Thymeleaf表格展示user,product,order的统计数字和最近几条记录。
最后分享一个小技巧:在毕设答辩PPT里,不要只放“系统架构图”和“类图”。拿出你本地运行时的截图——首页、商品详情页、购物车、订单成功页,再配上一张MySQL里
SELECT * FROM order的查询结果截图。当评委老师看到真实的订单号、真实的商品名、真实的交易时间,他们会立刻明白:这不是一个PPT里的概念,而是一个你亲手敲出来、跑起来、能用的系统。这份“真实感”,远胜于一百行华丽的代码。
本文还有配套的精品资源,点击获取
简介:提供一套开箱即用的家具类在线购物系统,基于Java语言和SpringBoot框架开发,采用B/S架构,前端通过浏览器访问,后端使用MySQL存储商品、用户、订单等数据。压缩包包含完整可运行源代码(含标准SpringBoot目录结构:src/main/java、src/main/resources等)、建库SQL脚本(springbooth4q2o.sql)、Maven配置文件(pom.xml)、基础项目配置(.gitignore、.classpath等)、Word格式开发文档(涵盖JDK/Maven/IDEA/MySQL环境搭建、数据库导入、前后端联调步骤、核心模块逻辑说明)以及MP4格式功能演示视频(覆盖用户注册登录、首页商品展示、分类筛选、加入购物车、下单支付、订单查询全流程)。所有内容经过本地验证,支持一键导入IDEA、执行SQL初始化数据库、启动Application主类快速运行,适合计算机专业学生用于课程设计、毕业设计参考或二次定制开发。
本文还有配套的精品资源,点击获取