
简介这是一套基于SpringBootMySQLHTML开发的宠物商城管理系统面向计算机专业本科生及Java初学者专为毕业设计、课程设计与期末大作业打造。系统覆盖商品展示、订单管理、用户中心、库存维护等核心业务模块采用前后端分离思路后端SpringBootMySQL前端HTML/CSS/JS界面简洁、功能完整、部署即用有效解决学生缺乏真实项目经验与毕设选题落地难的问题。压缩包共2个文件1个ZIP源码包1个SQL数据库脚本总大小14.06MBZIP内含完整IDEA工程结构、可运行后端代码、静态前端页面及微信小程序对接基础SQL脚本支持MySQL 5.7一键建库建表确保开箱运行。已有58人学习下载资源经导师验收并获高分评价附带清晰目录结构与配置说明无需二次修改即可编译部署是Java Web开发实践与毕业设计落地的理想参考方案。1. 项目缘起与核心价值为什么选择宠物商城作为毕业设计又到了一年一度的毕业季对于计算机、软件工程相关专业的同学来说毕业设计这道坎是绕不过去的。选题选得好答辩轻松过简历还能添一笔亮色选题选得烂那就是给自己挖坑熬夜掉头发不说最后可能还得求爷爷告奶奶。我当年毕业设计做的就是类似的项目后来也带过不少学弟学妹发现“宠物商城管理系统”这个选题是经久不衰的高分“潜力股”。它不像“图书管理系统”那么老套也不像“电商平台”那么宏大空洞正好卡在一个“有挑战性但又能驾驭”的甜点区。为什么这么说首先业务场景清晰且贴近生活。宠物用品购买、宠物信息管理、订单处理这些功能逻辑清晰评委老师一听就懂不需要你花大量篇幅去解释复杂的业务背景。其次技术栈组合经典且实用。Spring Boot MySQL HTML通常指代前端技术栈如HTML/CSS/JS或Thymeleaf模板是当前企业级Web开发最主流、最基础的组合。用这个组合做项目意味着你掌握了从后端API开发、数据库设计到前端页面渲染的完整开发链路技术深度和广度都足够支撑起一篇合格的毕业论文。最后扩展性强容易出亮点。基础的增删改查CRUD做完后你可以很容易地加入购物车、订单状态流转、用户权限控制、简单的数据分析图表等模块让项目显得更丰满、更“像”一个真实的系统。所以如果你正为毕业设计发愁或者想找一个能扎实练手的全栈项目“基于SpringBootMySQLHTML的宠物商城管理系统”绝对是一个不会错的选择。接下来我就以一个过来人和实践者的角度带你从零开始拆解这个项目的核心模块、技术选型背后的逻辑以及那些能让你的项目脱颖而出、获得高分的实战细节和避坑指南。2. 技术栈深度解析为什么是Spring Boot MySQL HTML在开始敲代码之前我们得先搞清楚手里这些“工具”到底强在哪里以及为什么要这样组合。很多同学只是机械地跟着教程把框架搭起来却说不清所以然这在答辩时是大忌。2.1 Spring Boot告别繁琐配置专注业务逻辑Spring Boot的核心价值就四个字约定大于配置。传统的Spring MVC项目光是把各种XML配置文件、依赖包整明白就能劝退一大半新手。Spring Boot通过内嵌Web服务器如Tomcat、提供一系列“starter”依赖和自动配置让你几乎可以“开箱即用”。对于宠物商城这个项目我们最关心的是Web层、业务层和数据访问层。Spring Boot的spring-boot-starter-web依赖一次性引入了Spring MVC、JacksonJSON处理、内嵌Tomcat等所有必需品。spring-boot-starter-data-jpa或spring-boot-starter-mybatis则能帮你快速集成数据库操作框架。你不需要再手动配置数据库连接池、事务管理器Spring Boot已经根据你引入的依赖和application.properties中的配置帮你把这一切都安排妥当了。实操心得在pom.xml中我强烈建议使用spring-boot-starter-parent作为父项目它能统一管理所有依赖的版本避免令人头疼的版本冲突。对于宠物商城基础依赖通常包括spring-boot-starter-web,spring-boot-starter-data-jpa,mysql-connector-java, 以及模板引擎如spring-boot-starter-thymeleaf如果你用Thymeleaf或前端分离时需要的依赖。2.2 MySQL关系型数据库的稳妥之选为什么不用MongoDB或者SQLite对于毕业设计而言稳妥和通用是第一要义。MySQL作为最流行的开源关系型数据库其生态、文档和社区支持都是最完善的。宠物商城的数据模型非常规整用户、商品、订单、购物车这些实体之间存在明确的关系一对多、多对多用关系型数据库来建模是最自然、查询效率也最有保障的。在设计数据库时你需要画出清晰的ER图。例如用户表 (user)id, username, password, phone, address, role用于区分普通用户和管理员。商品表 (product)id, name, category狗粮、猫砂、玩具等, price, stock库存, description, image_url。订单表 (order)id, order_no订单号, user_id, total_amount, status待付款、待发货、已发货、已完成等, create_time。订单详情表 (order_item)id, order_id, product_id, quantity, price下单时的单价。这里为什么要把价格单独存一份因为商品价格可能会变动必须记录下单时的快照。避坑指南数据库设计时一定要设置正确的主键、外键和索引。比如在order_item的product_id和order_id上建立索引能大幅提升关联查询速度。另外密码字段务必使用加密存储如BCrypt切勿明文保存。在application.properties中配置数据库连接时记得加上serverTimezoneAsia/Shanghai避免时区问题导致的时间错误。2.3 HTML与前端技术简单直接 vs 前后分离这里的“HTML”是一个泛指。在毕业设计语境下通常有两种实现方式服务端渲染SSR使用Thymeleaf、FreeMarker等模板引擎在后端生成完整的HTML页面。这种方式简单直接所有逻辑都在后端适合快速开发、逻辑不太复杂的管理系统如后台管理模块。前后端分离后端Spring Boot只提供RESTful API返回JSON数据前端使用纯HTML/CSS/JS或者Vue.js、React等框架通过Ajax调用API。这种方式更现代前后端职责清晰适合交互复杂的用户端页面如商品浏览、购物车。对于毕业设计我推荐混合模式管理后台用Thymeleaf做服务端渲染开发效率高用户商城页面用前后端分离比如用Vue.js体现你对现代Web开发的理解。这既能展示你的技术广度又能让项目结构更清晰。3. 系统核心模块设计与实现拆解一个完整的宠物商城绝不仅仅是几个表的增删改查。我们需要从用户视角和管理员视角梳理出核心的业务流程和模块。3.1 用户端核心功能流从浏览到下单用户端的体验直接决定了这个系统是否“像”一个商城。核心流程如下首页与商品浏览首页需要展示商品分类、热门商品、轮播图等。这里涉及Product和Category实体。前端通过API请求商品列表后端需要实现分页查询Pageable和条件筛选按分类、价格区间等。// ProductController 示例 GetMapping(/api/products) public PageProductDTO getProducts(RequestParam(required false) Long categoryId, RequestParam(required false) String keyword, RequestParam(defaultValue 0) int page, RequestParam(defaultValue 10) int size) { // 调用Service层进行复杂查询返回分页结果 return productService.findProducts(categoryId, keyword, page, size); }商品详情与购物车用户点击商品进入详情页。购物车功能是关键它通常有两种实现方式Session存储简单用户未登录也能用但数据无法跨设备同步。数据库存储与用户ID绑定数据持久化体验好。建议采用这种方式需要设计Cart和CartItem表。 添加商品到购物车时必须校验库存product.getStock() quantity这是一个典型的并发问题点我们后面会讲。下单与支付流程这是最复杂的部分。生成订单从购物车结算创建Order和多个OrderItem。这里必须是事务性操作你需要在一个事务内完成a) 锁定或校验库存b) 创建订单c) 清空用户购物车。Spring的Transactional注解就是为此而生。模拟支付对于毕业设计通常不需要集成真实的支付网关如支付宝、微信支付。可以做一个“模拟支付”接口调用后直接将订单状态改为“已支付”并触发后续的“减库存”操作。状态流转订单状态待支付、已支付、已发货、已完成的设计要清晰并在数据库中用枚举或状态字段明确标识。3.2 管理后台数据与业务的中枢管理后台是给系统管理员用的功能要全操作要稳。商品管理Product Management这是后台最常用的功能。除了基本的CRUD要特别注意图片上传的实现。通常的做法是前端通过input typefile上传图片。后端ProductController用RequestParam(file) MultipartFile file接收。将文件保存到服务器特定目录如/static/uploads/或者更推荐的做法是上传到云存储如阿里云OSS、腾讯云COS然后将返回的文件URL存入数据库的image_url字段。在Thymeleaf模板或前端页面中通过img src${product.imageUrl}来显示。订单管理Order Management管理员需要查看所有订单并能修改订单状态如点击“发货”。这里涉及一个权限控制问题。你必须确保这些敏感操作只有管理员能执行。最简单的实现是用户登录后将其角色信息如ROLE_ADMIN,ROLE_USER存入Session或JWT Token。在后台管理的Controller方法上使用Spring Security的注解进行权限控制PreAuthorize(hasRole(ADMIN))。用户管理与数据分析可以查看用户列表以及一些简单的数据统计比如“今日订单数”、“热销商品Top 10”。这些功能能为你的毕业设计论文增加“系统分析”章节的素材。可以用JPA的查询语句或原生SQL来统计结果用ECharts等图表库在前端展示效果会非常好。3.3 数据库事务与并发控制躲不开的坑这是体现你项目深度的关键部分也是答辩时老师喜欢问的地方。场景商品A库存只剩1件用户甲和用户乙同时点击购买。如果没有控制系统可能会创建两个订单导致超卖库存变为-1。解决方案悲观锁在查询商品时就用SELECT ... FOR UPDATE锁定这行数据直到事务结束。其他事务必须等待。这在JPA中可以通过Lock(LockModeType.PESSIMISTIC_WRITE)注解实现。这种方式简单粗暴但并发性能差。乐观锁更推荐的方式。在商品表中增加一个版本号字段version整数类型。每次更新时SET stock stock - 1, version version 1 WHERE id ? AND version ?。如果更新影响的行数为0说明版本号对不上数据已被别人修改过此时抛出异常让上层逻辑如前端提示用户“库存已变化请重新下单”。在JPA实体类中只需要加一个Version注解即可。Entity public class Product { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; private String name; private Integer stock; Version // 乐观锁版本号字段 private Integer version; // ... getters and setters }在Service层减库存时JPA会自动利用这个version字段进行乐观锁控制。核心要点在“下单”这个核心业务方法上务必加上Transactional注解并将事务隔离级别至少设置为Transactional(isolation Isolation.READ_COMMITTED)以保证数据的一致性。同时结合乐观锁机制就能较好地处理高并发下的超卖问题。4. 项目实战从环境搭建到功能实现理论说再多不如动手做一遍。我们抛开那些华而不实的理论直接进入实战环节我会把几个最容易卡住的关键环节给你讲透。4.1 初始化项目与基础配置我习惯使用 start.spring.io 来快速生成项目骨架。选择Project: Maven Project (更通用)Language: JavaSpring Boot: 选择最新的稳定版如3.x.xProject Metadata: 填好你的Group如com.yourname和Artifact如pet-mallDependencies: 添加Spring Web,Spring Data JPA,MySQL Driver,Thymeleaf如果做服务端渲染,Lombok强烈推荐简化实体类代码。点击生成并下载用IDEA或Eclipse打开。第一件事是配置src/main/resources/application.properties# 服务器端口 server.port8080 # 数据库配置 spring.datasource.urljdbc:mysql://localhost:3306/pet_mall?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.passwordyourpassword spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver # JPA配置 spring.jpa.hibernate.ddl-autoupdate # 开发环境用update自动建表。生产环境务必改为none或validate spring.jpa.show-sqltrue # 控制台打印SQL调试神器 spring.jpa.properties.hibernate.dialectorg.hibernate.dialect.MySQL8Dialect spring.jpa.properties.hibernate.format_sqltrue # 格式化打印的SQL # 文件上传大小限制如果需要 spring.servlet.multipart.max-file-size10MB spring.servlet.multipart.max-request-size10MB关键一步别忘了先在MySQL中手动创建数据库pet_mall字符集用utf8mb4支持emoji和更多字符。ddl-autoupdate会在应用启动时根据你的实体类自动创建或更新表结构但这仅限于开发初期。当表结构基本稳定后建议改为validate让Hibernate校验实体与数据库是否一致避免误操作导致数据丢失。4.2 实体类(Entity)与数据访问层(Repository)设计以Product实体为例展示如何用JPA和Lombok优雅地建模package com.yourname.petmall.entity; import lombok.Data; import javax.persistence.*; import java.math.BigDecimal; import java.time.LocalDateTime; Entity Table(name product) // 指定表名 Data // Lombok注解自动生成getter, setter, toString等 public class Product { Id GeneratedValue(strategy GenerationType.IDENTITY) // 主键自增 private Long id; Column(nullable false, length 100) // 非空长度限制 private String name; ManyToOne // 多对一关联多个商品属于一个分类 JoinColumn(name category_id) private Category category; private BigDecimal price; // 用BigDecimal表示金额避免精度丢失 private Integer stock; // 库存 Column(columnDefinition TEXT) // 使用TEXT类型存储长文本 private String description; private String imageUrl; // 商品图片链接 Version // 乐观锁版本号 private Integer version; private LocalDateTime createTime; private LocalDateTime updateTime; PrePersist // 持久化前自动设置创建时间 protected void onCreate() { createTime LocalDateTime.now(); updateTime LocalDateTime.now(); } PreUpdate // 更新前自动设置更新时间 protected void onUpdate() { updateTime LocalDateTime.now(); } }对应的ProductRepository接口就非常简单了继承JpaRepository就能获得大量现成的CRUD方法package com.yourname.petmall.repository; import com.yourname.petmall.entity.Product; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; public interface ProductRepository extends JpaRepositoryProduct, Long { // 根据分类ID查找商品分页 PageProduct findByCategoryId(Long categoryId, Pageable pageable); // 根据名称模糊查询 ListProduct findByNameContaining(String name); // 复杂查询示例查找某个价格区间内库存大于0的商品 Query(SELECT p FROM Product p WHERE p.price BETWEEN :minPrice AND :maxPrice AND p.stock 0) PageProduct findAvailableProductsInPriceRange(Param(minPrice) BigDecimal minPrice, Param(maxPrice) BigDecimal maxPrice, Pageable pageable); }JPA的强大之处在于你只需要按照规则定义方法名如findByCategoryId它就能自动生成对应的查询SQL极大地提高了开发效率。4.3 业务逻辑层(Service)与控制器层(Controller)实现Service层负责处理核心业务逻辑是大脑。以“下单”这个最复杂的服务为例Service Transactional // 类级别声明事务所有公共方法都受事务管理 Slf4j // Lombok注解自动提供log变量 public class OrderService { Autowired private ProductRepository productRepository; Autowired private OrderRepository orderRepository; Autowired private CartService cartService; public Order createOrder(Long userId, ListCartItemDTO cartItems, String shippingAddress) { // 1. 计算总金额并再次校验库存防止购物车页面停留过久库存变化 BigDecimal totalAmount BigDecimal.ZERO; ListOrderItem orderItemList new ArrayList(); for (CartItemDTO item : cartItems) { Product product productRepository.findById(item.getProductId()) .orElseThrow(() - new RuntimeException(商品不存在: item.getProductId())); if (product.getStock() item.getQuantity()) { throw new RuntimeException(商品库存不足: product.getName()); } // 2. 扣减库存乐观锁在此生效 int updatedRows productRepository.deductStock(product.getId(), item.getQuantity()); if (updatedRows 0) { // 乐观锁失败库存已被其他订单修改 throw new RuntimeException(商品库存已发生变化请重新确认订单: product.getName()); } // 3. 构建订单项 OrderItem orderItem new OrderItem(); orderItem.setProduct(product); orderItem.setQuantity(item.getQuantity()); orderItem.setPrice(product.getPrice()); // 记录下单时的价格 orderItemList.add(orderItem); totalAmount totalAmount.add(product.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))); } // 4. 创建订单 Order order new Order(); order.setUserId(userId); order.setOrderNo(generateOrderNo()); // 生成唯一订单号如时间戳随机数 order.setTotalAmount(totalAmount); order.setStatus(OrderStatus.PENDING_PAYMENT); // 初始状态待支付 order.setShippingAddress(shippingAddress); order.setItems(orderItemList); // 设置关联的订单项 Order savedOrder orderRepository.save(order); // 5. 清空购物车 cartService.clearCart(userId); log.info(订单创建成功订单号: {}, savedOrder.getOrderNo()); return savedOrder; } private String generateOrderNo() { // 简单示例时间戳 随机数 return ORD System.currentTimeMillis() (int)((Math.random() * 9 1) * 1000); } }在ProductRepository中需要定义自定义的扣减库存方法以利用乐观锁Modifying // 声明为修改查询 Query(UPDATE Product p SET p.stock p.stock - :quantity, p.version p.version 1 WHERE p.id :id AND p.stock :quantity) int deductStock(Param(id) Long productId, Param(quantity) Integer quantity);Controller层则负责接收HTTP请求调用Service并返回响应。对于RESTful API可以这样设计RestController RequestMapping(/api/orders) public class OrderController { Autowired private OrderService orderService; PostMapping public ResponseEntity? createOrder(RequestBody OrderRequest request, HttpSession session) { // 从session中获取当前用户ID假设登录后已存入 Long userId (Long) session.getAttribute(userId); if (userId null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(用户未登录); } try { Order order orderService.createOrder(userId, request.getCartItems(), request.getShippingAddress()); return ResponseEntity.ok(new OrderResponse(order.getId(), order.getOrderNo(), 订单创建成功)); } catch (RuntimeException e) { // 捕获业务异常如库存不足 return ResponseEntity.badRequest().body(e.getMessage()); } } }4.4 前端页面与后端交互以商品列表为例如果你采用Thymeleaf服务端渲染Controller和页面会紧密耦合Controller RequestMapping(/admin/product) public class AdminProductController { Autowired private ProductService productService; GetMapping public String listProducts(RequestParam(defaultValue 0) int page, Model model) { PageProduct productPage productService.getAllProducts(page, 10); model.addAttribute(products, productPage); return admin/product-list; // 对应 templates/admin/product-list.html } }对应的product-list.htmlThymeleaf模板中你可以直接使用后端传过来的数据!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8 title商品管理/title !-- 引入Bootstrap等CSS框架 -- /head body table classtable thead tr thID/th th商品名/th th价格/th th库存/th th操作/th /tr /thead tbody tr th:eachproduct : ${products.content} td th:text${product.id}/td td th:text${product.name}/td td th:text${#numbers.formatCurrency(product.price)}/td td th:text${product.stock}/td td a th:href{/admin/product/edit/{id}(id${product.id})}编辑/a a href# th:onclick|confirmDelete(${product.id})|删除/a /td /tr /tbody /table !-- 分页组件 -- div th:if${products.totalPages 1} span th:eachi: ${#numbers.sequence(1, products.totalPages)} a th:href{/admin/product(page${i-1})} th:text${i}/a /span /div /body /html如果是前后端分离前端比如用Vue.js会通过Axios调用后端的RESTful API获取JSON数据然后动态渲染到页面上。这种方式下后端Controller返回的是Product对象的JSON数组而不是视图名称。5. 项目优化与高分亮点打造把基础功能跑通只是一个及格线。要想拿高分你必须展示出对项目更深层次的思考和优化。以下几个方向能瞬间提升你项目的“高级感”。5.1 安全性加固不止于登录密码加密前面提过用BCryptPasswordEncoder加密存储密码这是Spring Security提供的标准方案比MD5安全得多。SQL注入防护使用JPA或MyBatis的参数化查询已经天然避免了SQL注入。绝对不要用字符串拼接的方式组装SQL。XSS攻击防护如果使用Thymeleaf它默认会对输出进行HTML转义提供了基础防护。对于纯API项目可以在全局或关键接口上通过过滤器或拦截器对请求参数进行清理。Spring Boot也可以集成commons-text库的StringEscapeUtils来转义HTML。CSRF防护如果使用Thymeleaf和Spring Security默认是开启CSRF保护的。对于前后端分离项目如果使用JWT等无状态认证可以酌情关闭CSRFhttp.csrf().disable()但必须确保API没有跨站请求伪造的风险。API接口鉴权管理员的API一定要加权限注解PreAuthorize。对于用户相关的API如查询自己的订单必须在Service层或Controller层校验当前登录用户ID与请求的资源所属用户ID是否匹配防止越权访问。5.2 性能与体验优化数据库连接池Spring Boot默认使用HikariCP性能很好。你可以在application.properties中调整其参数如spring.datasource.hikari.maximum-pool-size10。静态资源缓存商品图片、CSS、JS这些静态资源应该设置HTTP缓存头减少重复请求。Spring Boot可以通过配置WebMvcConfigurer来实现。前端异步加载与分页商品列表、订单列表务必做分页不要一次性查询所有数据。前端通过滚动加载或分页器按钮异步请求数据提升页面响应速度。日志记录使用Slf4j注解在关键业务节点如创建订单、支付成功记录日志。这不仅便于调试也是线上排查问题的依据。配置logback-spring.xml文件将日志按级别输出到不同文件。5.3 为论文和答辩准备的“加分项”你的毕业设计不止是代码论文和答辩同样重要。系统里的一些设计可以直接成为你论文中的章节。数据库设计章节拿出你精心设计的ER图详细说明每个表、每个字段的作用以及表之间的关系一对一、一对多、多对多。解释为什么这样设计比如“订单详情表冗余存储商品单价是为了记录历史价格”。系统架构图画一张简单的架构图说明前端、后端Spring Boot应用、MySQL数据库之间的关系。如果用了缓存如Redis也可以画上去。核心算法或流程说明比如“订单编号生成算法”、“基于乐观锁的库存扣减流程”。用流程图或伪代码清晰地表达出来。测试章节不要只写“进行了测试”。用Postman截图展示你测试的API接口和返回结果。甚至可以为核心的Service方法如OrderService.createOrder编写单元测试JUnit并把测试代码和覆盖率报告截图放到论文里。部署说明如何将Spring Boot项目打包成JAR文件如何在服务器上运行java -jar pet-mall.jar。可以简要提一下用Nginx做反向代理或者用Docker容器化部署这能体现你的工程化能力。6. 常见问题排查与避坑实录做项目的过程中你一定会遇到各种奇奇怪怪的问题。这里我总结几个最常见的帮你提前排雷。6.1 数据库连接失败与时区问题问题项目启动时报错Communications link failure或者The server time zone value ... is unrecognized。解决检查MySQL服务是否启动。检查application.properties中的url,username,password是否正确。最关键的一步在数据库连接URL后面加上?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingutf8。高版本的MySQL驱动对时区要求严格不加这个参数大概率连不上。6.2 JPA实体类与数据库表映射问题问题启动时报Table pet_mall.xxx doesnt exist或者字段映射错误。解决检查实体类的Entity和Table(namexxx)注解是否正确。检查字段名是否与数据库列名对应。默认规则是驼峰转下划线如imageUrl映射到image_url。如果不匹配使用Column(name xxx)显式指定。检查spring.jpa.hibernate.ddl-auto配置。开发时用update但要注意它不会删除列。如果改了字段类型可能需要先手动删表或修改数据库。6.3 事务不回滚问题问题在Service方法里抛出了异常但数据库的数据还是被修改了事务没有回滚。解决确保你的Service方法是public的。Spring AOP代理默认只对public方法生效。确保异常是RuntimeException或其子类。默认情况下Spring只对运行时异常进行回滚。如果是受检异常如IOException需要在Transactional注解中指定rollbackFor Exception.class。确保异常被抛出到方法外部而不是在方法内部被try-catch吞掉了。如果非要捕获记得在catch块里手动抛出new RuntimeException(e)。6.4 前端页面无法加载静态资源或模板问题访问页面时CSS/JS/图片不显示或者Thymeleaf模板找不到。解决静态资源Spring Boot默认从/static/,/public/,/resources/,/META-INF/resources/这些目录下找静态资源。把你的CSS、JS、图片放在src/main/resources/static/目录下访问路径就是/css/style.css。Thymeleaf模板模板文件必须放在src/main/resources/templates/目录下。Controller返回的字符串admin/product-listThymeleaf会自动去templates/下找admin/product-list.html。检查pom.xml中是否引入了spring-boot-starter-thymeleaf依赖。6.5 跨域问题CORS——前后端分离时必遇问题前端运行在localhost:3000后端运行在localhost:8080前端调用后端API时浏览器报错CORS policy。解决在后端Spring Boot项目中添加一个全局CORS配置类。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) // 针对所有/api开头的接口 .allowedOrigins(http://localhost:3000) // 允许的前端地址 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true); } }把这个项目从想法到代码再到优化和排坑的完整过程走一遍你得到的不仅仅是一个能运行的毕业设计更是一套扎实的、可复用的全栈开发经验。记住代码质量、文档清晰、答辩时能讲清楚技术选型和设计思路是获得高分的关键。最后别忘了在GitHub上好好维护你的代码仓库清晰的README和提交记录本身就是一个加分项。本文还有配套的精品资源点击获取