ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot药店管理系统实战:进销存设计、数据库与核心实现

Spring Boot药店管理系统实战:进销存设计、数据库与核心实现 简介本资源是一套面向计算机专业本科生的课程设计与毕业设计实践项目聚焦基于SpringBoot的Java Web药店管理系统开发适用于Java后端初学者巩固Web开发全流程能力。压缩包共包含多个核心文件涵盖可直接运行的完整源码、数据库初始化脚本db.sql、开题报告与论文文档LW、系统说明文档等类型涉及Java工程代码、SQL脚本、Word技术文档及纯文本操作指南整体大小为15.96MB。已有67人下载学习体现了其在教学实践场景中的实用价值。读者可获得从需求分析、SpringBootMyBatis/Security技术选型、前后端交互实现到库存管理、订单处理、用户权限控制等真实业务模块的完整参考所有代码经验证可本地一键运行配套文档清晰说明环境配置与启动步骤极大降低上手门槛是理解企业级Java Web系统架构与开发规范的优质入门范例。 这几年帮人看课设毕设项目Spring Boot Java Web 方向的药店管理系统几乎是每个学期都会遇到的高频题目。这个题一听很普通但每个人拿到的需求差别其实很大有的只要求最基础的增删改查有的要求带上完整的进销存、库存预警、效期提醒还有的把会员积分、统计报表和 Excel 导出全部算进去。我在这类项目上前前后后迭代过好几版也踩了不少坑今天就把完整的设计思路、技术选型、数据库表结构、核心业务实现以及交付时源码和 LW论文/设计文档怎么组织一次性讲清楚。如果你正在做这个题或者想深入理解一个进销存系统的完整链路这篇内容可以直接拿来当参考。1. 为什么选药店管理系统从课题价值到答辩风险都替你算了一遍1.1 药店管理系统到底在解决什么问题药店日常经营里最烦的不是卖药而是库存对不上。今天入库了一批感冒药前台卖了几盒有人在盘点时又发现几盒过期了如果靠 Excel 登记很容易漏记、错记。药品的效期、批次、供应商批次对账、会员积分全是细节。药店管理系统本质是一个进销存系统核心是管理药品从“采购”到“入库”到“销售出库”再到“库存盘点”的完整生命周期。除此之外还牵扯到供应商资料、会员档案、价格管理、临期药品提醒和经营数据统计。把这些业务搬到线上让每一次入库、销售都有据可查库存数量所有角色看到的是一致的这就是系统最基础的价值。1.2 为什么这个题在课设毕设里性价比高一个适合做课设/毕设的题目要满足三点需求清晰、技术复杂度适中、有足够的扩展空间。药店管理系统恰好三点都占。第一需求清晰。进销存是管理信息系统里的经典业务模型每个老师都能理解描述起来不需要太多额外背景。第二业务关系丰富。虽然体量不大但涉及用户、药品、供应商、采购单、销售单、库存流水、会员等实体一对多、多对多关系都有数据库设计部分可以有内容。第三扩展空间大。你可以在基础功能上叠加近效期提醒、库存预警、销售趋势分析、会员积分、导出报表甚至对接微信小程序随便挑一个都能写成亮点。这题比纯论坛系统、纯博客系统更容易体现工程化思维也是一个比较稳妥的选择。1.3 答辩老师最爱问的几个问题要先想好这个题被问到的概率最高的三个问题提前准备一下答辩基本不会冷场。第一个药品效期是怎么管理的你的答案要点是药品表里有 expiry_date 字段查询时用 SQL 把当前日期到到期日之间不足 90 天的记录筛出来列表里用颜色标记销售时还可以做二次校验。第二个库存和销售数据的一致性怎么保证答案是事务。每次扣减库存和生成销售记录放在同一个事务里任何一步失败就整体回滚同时用库存流水表记录每次变动随时可以追溯。第三个为什么用 Spring Boot 而不是传统的 SSH 或 SSM答案要点是 Spring Boot 基于 Spring Boot 生态内嵌 Tomcat不需要额外部署外部容器配置简化适合快速迭代而且已经成为 Java Web 开发的主流选择。把这三个问题答顺了答辩老师就会觉得你确实做过项目而不只是把 PPT 背了一遍。2. 需求拆解先别急着写代码把角色和流程理清楚2.1 角色划分不同人看到的界面和功能不一样药店管理系统不是一个所有人都能操作所有功能的系统。最常见的角色有三种。系统管理员负责系统基础配置包括用户管理、药品字典维护、供应商审核、数据统计和日志查看。店员的日常操作是前台售药、退药、会员登记以及查看自己的销售记录。采购员负责供应商管理、采购单创建和到货入库。如果系统做得再细一点还可以增加一个店长角色能看门店的经营报表和利润分析但不能修改基础数据。角色的意义不只是菜单显示不同更重要的是后端接口要有对应的权限控制。比如店员界面不应该出现进货价和利润统计哪怕是接口被猜到也要能拦截下来否则做权限管理就没有意义。2.2 功能模块清单先画清楚再开发在动手写代码之前我会先列一张功能模块表把每个模块的功能点和说明写清楚。这张表既可以指导开发后面写 LW 文档时也能直接复用。模块功能点说明药品管理药品增删改查、药品分类、近效期筛选药品编码唯一名称、规格、厂家、批准文号必填库存管理入库、销售出库、盘点、库存预警、流水查询所有库存变动必须写流水可追溯采购管理采购单登记、审核、到货入库一张采购单可以包含多个药品销售管理前台售药、销售单查询、退货销售时实时校验库存和效期供应商管理供应商增删改查包含联系人、电话、地址、合作状态会员管理会员发卡、积分管理、消费记录会员按手机号唯一标识系统管理用户管理、角色管理、操作日志管理员专用控制权限统计报表日/月销售统计、低库存、近效期、导出给店长和管理员看经营数据2.3 核心业务流程采购入库和前台销售是两条主线整个系统最核心的两条业务链路一条是“采购入库”另一条是“前台销售”。采购入库的流程是采购员选择供应商和药品生成采购单药品到货后核对数量提交入库系统自动增加对应药品的库存同时写一条入库类型的库存流水记录本次变动前后数量。前台销售的流程是收银员把顾客需要的药品逐一加入销售列表确认数量后收款提交系统校验库存和效期通过后扣减库存、写销售流水、生成销售主单和销售明细单。如果顾客是会员还要同步累加积分。这两条链路几乎涵盖了系统所有核心逻辑。代码实现时先把这两条流程跑通其他模块基本都是在这两条链路外围做增删改查。2.4 非功能性需求校验、权限和日志课设系统同学容易忽略非功能性需求但答辩加分往往靠这些点。后端入参要做校验比如库存数量不能为负数、销售数量不能大于库存、药品编码不能重复。普通店员不能访问成本价和利润相关接口这个必须做。药品改价、盘库存这类操作要记录操作人和操作时间方便追溯。3. 技术选型Spring Boot Java Web 的方案怎么定才稳3.1 为什么 Spring Boot 成了课设“标准答案”以前做 Java Web 课设最常写的是 SSM 整合就是在 Spring Spring MVC MyBatis 的基础上手动配一堆 XML 文件。Spring 的 applicationContext.xml、Spring MVC 的 dispatcher-servlet.xml、MyBatis 的 mybatis-config.xml哪个配置写错一点项目启动就会直接报错对新手极其不友好。Spring Boot 带来的最大改变是“约定大于配置”。它不仅把 SSM 的整合过程自动完成还内嵌了 Tomcat开发时直接启动 main 方法就能看到效果部署时一个 java -jar 命令就能跑。课设演示的时候再也不用先装 Tomcat、改 server.xml、把 war 包手动拷进 webapps体验上的提升非常明显。从技术本质上说Spring Boot 仍然是 Java Web 技术栈底层还是 Spring MVC只不过把繁琐的配置收进去了。在论文里写“基于 Spring Boot 的 Java Web 系统”完全站得住脚。3.2 ORM 选 MyBatis-Plus单表不用写 SQL复杂查询又留得住持久层框架推荐 MyBatis-Plus理由非常简单单表的增删改查可以直接继承 BaseMapper自带 selectById、insert、updateById 等方法连 SQL 都不用写。分页查询有官方分页插件逻辑删除和字段自动填充都能配置。更重要的是MyBatis-Plus 没有把自定义 SQL 的能力封死。统计报表、库存预警这类需要多表联查的复杂 SQL仍然可以写在 Mapper XML 里由自己控制。这一点对课设项目很关键因为很多高价值的模块恰好是那些手写 SQL 的地方。3.3 前端方案Thymeleaf Bootstrap 优先Vue 按需选择前端有两种主流方案。第一种是服务端渲染Spring Boot Thymeleaf Bootstrap。页面由 Controller 直接返回Thymeleaf 模板负责渲染数据Bootstrap 负责样式。优点是工程结构简单不需要 Node.js 环境启动后端就能看到一个完整的管理后台特别适合单人开发。缺点是页面交互比较传统要实现复杂的前端效果会比较吃力。第二种是前后端分离Spring Boot 提供 REST API前端用 Vue3 Element Plus 搭后台。界面确实更现代但这意味着你要同时维护两套工程还要处理跨域、Token 鉴权、构建环境等问题。如果对 Node 和 Vue 不熟答辩现场很容易被环境问题卡住。我的建议课设项目优先选 Thymeleaf Bootstrap稳定不翻车。如果你确实想让系统看起来有亮点可以做一个 Vue 管理页作为扩展但至少保证后端 API 能用 Postman 完整演示这样即使前端出问题也有补救空间。3.4 环境版本搭配别为了新版牺牲稳定性我见过很多项目用最新的 Spring Boot 3.x结果 JDK 版本不够直接启动失败最后又回退。给你一个我长期在用的稳定组合组件推荐版本备注JDK1.8 或 11学校电脑兼容性最好不要用 17Spring Boot2.7.x功能稳定资料多MyBatis-Plus3.5.x3.5 以后对 Boot2 支持良好MySQL5.7 或 8.0两者都可以8.0 注意驱动差异Maven3.6配合 IDEA 使用IDEA2022.3社区版也够用数据库驱动如果用的是 MySQL 8.0记得在连接串里加 serverTimezoneAsia/Shanghai否则很容易踩时区问题。3.5 再说一下“LW”和源码压缩包的事标题里的 LW 在课设圈里一般指“论文”或“设计文档”也就是除了源码之外还要交付的文档材料。一个完整的课程设计/毕业设计交付物通常包含源码、数据库脚本、LW 文档、演示视频压缩包命名里带上日期或者版本号。源码可运行是底线文档规范是加分项两个都不能忽视。4. 数据库设计这几张表是怎么一步步定下来的4.1 药品表药店系统的心脏药品表是整个系统最重要的表字段需要认真设计。我用的核心字段如下字段说明id主键自增drug_code药品编码唯一索引common_name通用名比如“阿莫西林胶囊”trade_name商品名比如“再林”specification规格比如“0.25g*24粒”unit单位盒/瓶/袋manufacturer生产厂家approval_number批准文号国药准字purchase_price进货价DECIMAL(10,2)sale_price零售价DECIMAL(10,2)stock_quantity当前库存数量stock_lower_limit库存下限低于这个值预警stock_upper_limit库存上限expiry_date有效期至category_id药品分类deleted逻辑删除标记进货价和零售价必须分开字段因为这两个价格的可见人群不同。进货价用于成本核算由管理员维护店员界面不展示。批准文号字段在答辩时能体现你对药品行业的理解千万别丢掉。4.2 用户、角色、供应商表用户表 userid、username、password、real_name、phone、role_id、status。密码不能存明文用 BCrypt 加密。角色表 roleid、role_name、role_key、description。管理员角色 key 是 admin店员是 clerk采购员是 purchaser。用户直接挂 role_id不需要把权限系统做太复杂但角色要存在数据库里不能写死在代码里。供应商表 supplierid、supplier_name、contact_person、phone、address、status、remark。采购入库时必须关联供应商保证采购数据能够对账。4.3 采购主单和采购明细为什么要拆两张表采购单设计成主单 明细两张表这是课设里非常值得讲的部分。采购主表 purchase_orderid、order_no、supplier_id、total_amount、status待入库/已入库/已取消、create_time、create_by。采购明细表 purchase_order_itemid、order_id、drug_id、quantity、purchase_price、subtotal。为什么不把采购信息全部塞到一张表里因为一张采购单可能包含 5 种甚至 20 种药品如果都放在一行同一张单的药品会被拆成多行数据里就会大量重复单号查询单据时还要处理重复。主单管理订单整体信息明细管理每个药品的条目一次采购单生成多条明细边界非常清晰。后续做供应商对账、进货总额统计都能直接通过 order_id 关联查询。4.4 销售主单和销售明细订单模型的常见设计销售表和采购表结构类似。销售主表 sale_orderid、order_no、member_id、total_amount、pay_type现金/微信/支付宝、status、create_time、create_by。销售明细表 sale_order_itemid、order_id、drug_id、quantity、sale_price、subtotal。这里要注意的是 member_id 允许为空因为非会员顾客也可以买药。如果做退货业务可以在主单上加 status 字段区分正常和退货退货时重新生成一条负数的库存流水表示库存回补。4.5 库存流水表整个系统的账本库存流水表 stock_record 是容易被忽略但很关键的一张表。字段包括id、drug_id、change_type1 入库、2 销售扣减、3 报损、4 盘点调整、change_quantity正数增加负数减少、before_quantity、after_quantity、biz_no关联的采购单号或销售单号、create_time、create_by。有了这张表你可以随时回答“某盒药到底什么时候进的、什么时候卖的、卖给了哪笔单子”这些问题。没有流水数据库里只剩一个当前库存数字连对账都做不了。这也是答辩时一个可靠的亮点拿出库存流水的时候老师会觉得你不是在写玩具。4.6 会员表和用户表分开会员表 memberid、card_no、name、phone、points、create_time。会员是药店面向消费者的客户档案用户表是操作系统的人两个模型必须分开。会员等级和积分可以先用一个字段存点数后续要扩展等级再加一个 level 字段就行。4.7 表设计的一些取舍外键字段逻辑关联保留但不要在大表之间强制建物理外键约束。课设阶段测试数据非常频繁物理外键容易导致删除失败、导入顺序报错。逻辑外键的意思是在代码和 SQL 中通过 JOIN 来保证关系由业务层控制完整性不依赖数据库约束。金额字段一律用 DECIMAL(10,2)不要用 DOUBLE 或 FLOAT浮点数在计算金额时会有精度损失。所有业务表都加 deleted 字段实现逻辑删除这是 MyBatis-Plus 的标配也方便论文里写“系统支持数据恢复”。5. 从零搭建项目把 Spring Boot 项目骨架搭起来5.1 创建项目和引入依赖打开 IDEANew Project 选择 Spring InitializrJava 版本选 8依赖先勾选 Spring Web、MySQL Driver、Validation、Thymeleaf。生成之后在 pom.xml 里手动加 MyBatis-Plus 和 Lombok。pom.xml 核心依赖长这样dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency5.2 application.yml 配置配置文件是最容易出错的位置尤其是数据库连接串。server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/pharmacy?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 thymeleaf: cache: false mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0这里要重点说一下 map-underscore-to-camel-case 的作用。数据库字段一般是 create_time 下划线风格Java 实体类是 createTime 驼峰风格这个配置打开之后 MyBatis 会自动完成映射不用手写 resultMap。逻辑删除配置则保证调用 deleteById 时执行的是 UPDATE deleted 1 而不是物理删除。5.3 分包结构一眼能看懂的工程我习惯用下面这个结构com.example.pharmacy ├── config ├── controller ├── entity ├── mapper ├── service ├── service.impl ├── dto ├── vo └── commoncontroller 放接口入口service 放业务逻辑mapper 放数据库访问entity 放表映射实体common 放统一返回结果和异常处理。不要把业务逻辑堆在 controller 里否则 Service 层没有内容论文里写“业务层设计”会非常虚。5.4 统一返回结果和全局异常处理前端页面或者接口调用方如果每次接收的数据结构都不一样联调就是灾难。定义一个 Result 类全系统统一返回格式public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT r new Result(); r.code 200; r.message ok; r.data data; return r; } public static T ResultT error(String message) { ResultT r new Result(); r.code 500; r.message message; return r; } }全局异常处理用 RestControllerAdvice 统一捕获业务异常和未知异常避免把异常堆栈直接返回给前端。课设里的前端页面如果直接暴露异常堆栈观感很差而且有信息泄露风险。5.5 一个完整的药品分页查询接口示例ControllerGetMapping(/drug/page) public ResultIPageDrug page(RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size, RequestParam(required false) String keyword) { return Result.success(drugService.pageQuery(page, size, keyword)); }Service 实现public IPageDrug pageQuery(int page, int size, String keyword) { PageDrug p new Page(page, size); LambdaQueryWrapperDrug wrapper Wrappers.lambdaQuery(); if (StringUtils.hasText(keyword)) { wrapper.like(Drug::getCommonName, keyword) .or().like(Drug::getTradeName, keyword); } return drugMapper.selectPage(p, wrapper); }这个接口同时支持分页和关键字模糊搜索可以覆盖药品列表页的全部需求。注意分页插件需要在配置类里注册 MybatisPlusInterceptor加上 PaginationInnerInterceptor否则 selectPage 只能查出所有数据分页不生效。6. 库存与销售课设里最值得写进论文的核心实现6.1 入库操作为什么必须放在同一个事务里采购入库涉及三步保存采购主单、更新药品库存、写库存流水。任何一个环节失败都会造成库存数据不一致。举个例子如果保存采购单成功但更新库存时报错数据库里就会有一个“已入库”状态的采购单实际药品数量却没有增加。再比如库存已经更新了但流水没写成将来对账时完全说不清这个库存是怎么来的。解决办法是在 Service 方法上加 Transactional(rollbackFor Exception.class)让三个操作要么全部成功要么全部回滚。事务是数据库保证一致性的基础也是答辩时必讲的技术点。核心逻辑可以写成这样Transactional(rollbackFor Exception.class) public void purchaseStock(PurchaseOrder order, ListPurchaseOrderItem items) { purchaseOrderMapper.insert(order); for (PurchaseOrderItem item : items) { Drug drug drugMapper.selectById(item.getDrugId()); Integer before drug.getStockQuantity(); drug.setStockQuantity(before item.getQuantity()); drugMapper.updateById(drug); stockRecordMapper.insert(new StockRecord( item.getDrugId(), 1, item.getQuantity(), before, drug.getStockQuantity(), order.getOrderNo() )); } }6.2 销售扣库存并发情况下怎么避免超卖销售最容易出的问题是并发扣库存。如果两个收银员同时卖出同一盒药库存就剩 1 盒系统读到两个“库存为 1”各自都执行减 1最后库存变成 -1实际却卖出了 2 盒。解决思路是让扣库存的操作变成原子性的并且只有条件满足时才执行。比较常用的方式是乐观锁在 drug 表加一个 version 字段扣库存时使用带条件的 updateUPDATE drug SET stock_quantity stock_quantity - #{quantity}, version version 1 WHERE id #{drugId} AND stock_quantity #{quantity} AND version #{version}如果 update 返回的影响行数为 0说明库存不足或者版本号已变化业务层立刻抛出“库存不足或操作冲突”提示收银员刷新重试。这种方式在课设项目里已经足够可靠而且代码量很小。6.3 库存流水before 和 after 的妙用库存流水的 before_quantity 和 after_quantity 字段初看是冗余的因为通过当前库存反推也能算出来。实际用起来会发现这对字段在数据核对时非常有用。比如某天盘点发现库存少了 3 盒如果有流水可以按时间把每笔变动列出来快速定位是哪笔操作出了问题。如果没有流水就只能凭记忆找原因。把 before 和 after 带上之后流水本身就是一条完整的审计链。写入顺序要注意先更新 drug 表的库存再插入 stock_record流水里的 after_quantity 必须等于更新后的最新库存。这两个操作必须在同一个事务里否则会出现“流水写了但库存没更新”的情况。6.4 近效期提醒用 SQL 把快过期药品筛出来药品效期是药店业务里的刚需。查询 90 天内即将到期的药品SELECT * FROM drug WHERE expiry_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 90 DAY) AND deleted 0 ORDER BY expiry_date ASC这条 SQL 可以直接用在药品列表页的“近效期”Tab 中。更完整一点的做法是在销售时增加效期校验如果药品距离到期日不足 30 天前端弹窗提示收银员确认后二次放行。6.5 库存预警低于下限自动提醒库存预警的 SQL 非常简单SELECT * FROM drug WHERE stock_quantity stock_lower_limit AND deleted 0但要在首页把它做成一个统计数据卡片比如“缺货药品 6 种”“近效期药品 3 种”“今日销售额 12800 元”这样管理员打开系统第一眼就能看到异常情况。这三个数字看起来简单实际上要做三张统计 SQL分别查销售总额、低库存数量和近效期数量。写完这三个接口首页的展示效果立刻不一样。6.6 统计报表和导出 Excel日报表统计按自然日分组SELECT DATE(create_time) AS day, SUM(total_amount) AS amount FROM sale_order WHERE status 1 GROUP BY DATE(create_time) ORDER BY day DESC报表展示用折线图或者柱状图可以用一个轻量级的图表库 ECharts通过 Thymeleaf 模板把数据拼到 JS 变量里渲染。导出功能推荐引入 EasyExcel 依赖写一个导出接口把报表数据转为 Excel 文件响应给前端下载。这个功能不复杂但演示效果非常好是课设项目里一个性价比很高的亮点。7. 排错实录课设跑不起来的常见原因我已经帮你踩过一遍7.1 数据库连接失败被时区问题卡住最常见的报错是“Communications link failure”或者时区相关的异常。原因是连接串里没有配置 serverTimezoneMySQL 8.0 的驱动要求明确指定时区。解决办法就是加上 serverTimezoneAsia/Shanghai。还有一种情况是密码错误报“Access denied for user rootlocalhost”要把 application.yml 里密码改成你自己本机的数据库密码不要直接照抄网上配置。7.2 控制台中文乱码中文乱码一般是字符集不统一造成的。确认三处设置数据库连接串里带上 characterEncodingutf8数据库表结构默认字符集是 utf8mb4IDE 的 File Encoding 全部改成 UTF-8。如果是页面乱码还要确认前端模板文件头部有meta charsetUTF-8。7.3 前端提交日期参数报 400前台页面用表单提交一个日期字符串比如“2024-05-20 14:30”后端用 Date 类型接收时Spring MVC 默认不认识这个格式会直接返回 400。解决办法是在实体类的日期字段上加上 DateTimeFormat(pattern yyyy-MM-dd HH:mm:ss)。如果是通过 JSON 传输要改用 JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)。这两个注解容易搞混我每次都会检查一下。7.4 MyBatis-Plus 自动填充不生效如果实体类里有 createTime 和 updateTime并且加了 TableField(fill FieldFill.INSERT)但插入数据后这两个字段是 null原因是你没有配置 MetaObjectHandler。自动填充需要一个处理器在插入时自动 set 创建时间和修改时间。Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } }配置了之后createTime 和 updateTime 就会自动维护不需要每个 Service 方法手动 set。7.5 静态资源 404页面样式全丢了Spring Boot 的默认静态资源路径是 classpath:/static/模板页面放在 classpath:/templates/ 下。Thymeleaf 页面里引用 CSS 时要用 th:href{/css/style.css}或者写成 /css/style.css 绝对路径不要用相对路径否则从不同 URL 进入页面时路径会乱掉。7.6 启动报端口占用启动时如果提示“Port 8080本文还有配套的精品资源点击获取
返回列表