软件开发流程、角色分工与项目整体介绍
外卖平台-项目背景
随着餐饮行业竞争的加剧,传统餐饮系统间畅通程度较差,收银产品、会员产品、供应链产品等各个模块相互割裂,形成了各个信息孤岛,导致信息不对称、商家工作耗能大、增加商家人力物力和沟通成本,在三高一低的压力下,商家的竞争力不断被弱化。
用户点餐外卖全流程
浏览 → 加购 → 下单 → 支付
#mermaid-svg-8SvwPHqJeSlgl3im{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8SvwPHqJeSlgl3im .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8SvwPHqJeSlgl3im .error-icon{fill:#552222;}#mermaid-svg-8SvwPHqJeSlgl3im .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8SvwPHqJeSlgl3im .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8SvwPHqJeSlgl3im .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8SvwPHqJeSlgl3im .marker.cross{stroke:#333333;}#mermaid-svg-8SvwPHqJeSlgl3im svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8SvwPHqJeSlgl3im p{margin:0;}#mermaid-svg-8SvwPHqJeSlgl3im .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8SvwPHqJeSlgl3im .cluster-label text{fill:#333;}#mermaid-svg-8SvwPHqJeSlgl3im .cluster-label span{color:#333;}#mermaid-svg-8SvwPHqJeSlgl3im .cluster-label span p{background-color:transparent;}#mermaid-svg-8SvwPHqJeSlgl3im .label text,#mermaid-svg-8SvwPHqJeSlgl3im span{fill:#333;color:#333;}#mermaid-svg-8SvwPHqJeSlgl3im .node rect,#mermaid-svg-8SvwPHqJeSlgl3im .node circle,#mermaid-svg-8SvwPHqJeSlgl3im .node ellipse,#mermaid-svg-8SvwPHqJeSlgl3im .node polygon,#mermaid-svg-8SvwPHqJeSlgl3im .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8SvwPHqJeSlgl3im .rough-node .label text,#mermaid-svg-8SvwPHqJeSlgl3im .node .label text,#mermaid-svg-8SvwPHqJeSlgl3im .image-shape .label,#mermaid-svg-8SvwPHqJeSlgl3im .icon-shape .label{text-anchor:middle;}#mermaid-svg-8SvwPHqJeSlgl3im .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8SvwPHqJeSlgl3im .rough-node .label,#mermaid-svg-8SvwPHqJeSlgl3im .node .label,#mermaid-svg-8SvwPHqJeSlgl3im .image-shape .label,#mermaid-svg-8SvwPHqJeSlgl3im .icon-shape .label{text-align:center;}#mermaid-svg-8SvwPHqJeSlgl3im .node.clickable{cursor:pointer;}#mermaid-svg-8SvwPHqJeSlgl3im .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8SvwPHqJeSlgl3im .arrowheadPath{fill:#333333;}#mermaid-svg-8SvwPHqJeSlgl3im .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8SvwPHqJeSlgl3im .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8SvwPHqJeSlgl3im .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8SvwPHqJeSlgl3im .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8SvwPHqJeSlgl3im .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8SvwPHqJeSlgl3im .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8SvwPHqJeSlgl3im .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8SvwPHqJeSlgl3im .cluster text{fill:#333;}#mermaid-svg-8SvwPHqJeSlgl3im .cluster span{color:#333;}#mermaid-svg-8SvwPHqJeSlgl3im div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8SvwPHqJeSlgl3im .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8SvwPHqJeSlgl3im rect.text{fill:none;stroke-width:0;}#mermaid-svg-8SvwPHqJeSlgl3im .icon-shape,#mermaid-svg-8SvwPHqJeSlgl3im .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8SvwPHqJeSlgl3im .icon-shape p,#mermaid-svg-8SvwPHqJeSlgl3im .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8SvwPHqJeSlgl3im .icon-shape .label rect,#mermaid-svg-8SvwPHqJeSlgl3im .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8SvwPHqJeSlgl3im .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8SvwPHqJeSlgl3im .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8SvwPHqJeSlgl3im :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外卖
商家页面
重新定位
新增收货地址
商品详情
提交订单
支付订单
支付完成
选择收货地址
新增收货地址
我的
账号信息
收货地址
历史订单
编辑收货地址
新增收货地址
历史订单详情
再来一单
纲要
本篇是外卖平台项目的开篇,负责把「这个项目要做什么、由谁做、用什么技术做」讲清楚。
- 软件开发流程:需求分析 → 设计 → 编码 → 测试 → 上线运维
- 角色分工 :
项目经理/产品经理/UI设计师/架构师/开发工程师/测试工程师/运维工程师 - 三种软件环境 :
开发环境(development)/测试环境(testing)/生产环境(production) - 项目定位 :为餐饮企业(餐厅、饭店)定制的软件产品,分为系统管理后台 与移动端应用两端
- 产品原型 :
HTML页面形式的功能框架,用于可视化展示需求,不约束最终视觉样式 - 技术选型 :用户层
H5/Vue.js/ElementUI/微信小程序;网关层Nginx;应用层Spring Boot/Spring MVC/Spring Session/Swagger/Lombok;数据层MySQL/MyBatis/MyBatis-Plus/Redis;工具Git/Maven/Junit - 功能架构:管理端(分类、菜品、套餐、口味、员工、订单管理);移动端(登录、地址管理、历史订单、规格、购物车、菜品浏览)
- 角色划分 :
后台系统管理员/后台系统普通员工/C端用户
软件开发的标准流程
任何一款企业级软件,从 0 到上线都不是拍脑袋写代码的,而是有一条相对固定的流水线。理解这条流水线,才能理解后续每一天的开发任务在整个链条上处于什么位置。
#mermaid-svg-iJdKPC96Q6cbjmWH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iJdKPC96Q6cbjmWH .error-icon{fill:#552222;}#mermaid-svg-iJdKPC96Q6cbjmWH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iJdKPC96Q6cbjmWH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iJdKPC96Q6cbjmWH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iJdKPC96Q6cbjmWH .marker.cross{stroke:#333333;}#mermaid-svg-iJdKPC96Q6cbjmWH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iJdKPC96Q6cbjmWH p{margin:0;}#mermaid-svg-iJdKPC96Q6cbjmWH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster-label text{fill:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster-label span{color:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster-label span p{background-color:transparent;}#mermaid-svg-iJdKPC96Q6cbjmWH .label text,#mermaid-svg-iJdKPC96Q6cbjmWH span{fill:#333;color:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH .node rect,#mermaid-svg-iJdKPC96Q6cbjmWH .node circle,#mermaid-svg-iJdKPC96Q6cbjmWH .node ellipse,#mermaid-svg-iJdKPC96Q6cbjmWH .node polygon,#mermaid-svg-iJdKPC96Q6cbjmWH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iJdKPC96Q6cbjmWH .rough-node .label text,#mermaid-svg-iJdKPC96Q6cbjmWH .node .label text,#mermaid-svg-iJdKPC96Q6cbjmWH .image-shape .label,#mermaid-svg-iJdKPC96Q6cbjmWH .icon-shape .label{text-anchor:middle;}#mermaid-svg-iJdKPC96Q6cbjmWH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iJdKPC96Q6cbjmWH .rough-node .label,#mermaid-svg-iJdKPC96Q6cbjmWH .node .label,#mermaid-svg-iJdKPC96Q6cbjmWH .image-shape .label,#mermaid-svg-iJdKPC96Q6cbjmWH .icon-shape .label{text-align:center;}#mermaid-svg-iJdKPC96Q6cbjmWH .node.clickable{cursor:pointer;}#mermaid-svg-iJdKPC96Q6cbjmWH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iJdKPC96Q6cbjmWH .arrowheadPath{fill:#333333;}#mermaid-svg-iJdKPC96Q6cbjmWH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iJdKPC96Q6cbjmWH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iJdKPC96Q6cbjmWH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iJdKPC96Q6cbjmWH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iJdKPC96Q6cbjmWH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iJdKPC96Q6cbjmWH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster text{fill:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH .cluster span{color:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iJdKPC96Q6cbjmWH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iJdKPC96Q6cbjmWH rect.text{fill:none;stroke-width:0;}#mermaid-svg-iJdKPC96Q6cbjmWH .icon-shape,#mermaid-svg-iJdKPC96Q6cbjmWH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iJdKPC96Q6cbjmWH .icon-shape p,#mermaid-svg-iJdKPC96Q6cbjmWH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iJdKPC96Q6cbjmWH .icon-shape .label rect,#mermaid-svg-iJdKPC96Q6cbjmWH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iJdKPC96Q6cbjmWH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iJdKPC96Q6cbjmWH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iJdKPC96Q6cbjmWH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线上问题或新需求
需求分析
产品原型 + 需求规格说明书
设计
产品文档/UI/概要/详细/数据库
编码
功能实现 + 单元测试
测试
测试用例 + 测试报告
上线运维
环境搭建 + 部署
需求分析阶段
这个阶段的产出物有两类:
- 产品原型 :以网页(
HTML)形式展现项目的页面结构 ------ 有哪些页面、每个页面是列表页还是表单页、点击按钮后发生什么。原型由产品经理在需求分析阶段制作。 - 需求规格说明书 :
Word文档形式,用文字描述项目具备哪些功能。
有一个经常被误解的点必须强调:产品原型只用于展示功能,不是最终的页面效果 。配色、按钮样式、字号等视觉表现由 UI设计师 另行输出,原型不对其做约束。
设计阶段
设计不是一件单一工作,而是若干个并行子项:
| 设计子项 | 产出 |
|---|---|
| 产品文档设计 | 补充说明原型未覆盖的业务规则 |
UI 界面设计 |
页面最终视觉效果 |
| 概要设计 | 系统模块划分、接口约定 |
| 详细设计 | 类结构、方法签名、流程细节 |
| 数据库设计 | 库表数量、表结构、字段定义 |
编码阶段
由开发工程师完成,核心是功能代码实现 + 单元测试。单元测试不是可选项 ------ 它是保证提交给测试的代码「有效可用」的第一道关口。
测试与上线
测试工程师编写测试用例、执行测试并输出测试报告;测试通过后由运维工程师完成软件环境安装、配置与项目部署。
团队角色分工
一个项目团队通常包含以下角色,各自职责边界清晰:
| 角色 | 核心职责 | 介入阶段 |
|---|---|---|
| 项目经理 | 任务分配、进度把控、资源调度 | 全程 |
| 产品经理 | 需求调研、需求文档、产品原型 | 前期为主 |
UI 设计师 |
输出界面效果图 | 设计阶段 |
| 架构师 | 技术架构设计、技术选型 | 设计阶段 |
| 开发工程师 | 代码实现 | 编码阶段 |
| 测试工程师 | 测试用例编写与执行 | 测试阶段 |
| 运维工程师 | 环境搭建、项目上线 | 后期为主 |
需要注意现实与规范的差异:规模较大的公司分工明确,项目经理不参与编码;小型团队里架构师、测试人员往往缺位,这些职责会落到开发工程师身上,同时项目经理也可能直接写代码。
三种软件环境
这是开发与运维之间最容易产生沟通歧义的概念,必须分清:
#mermaid-svg-Doo4F9gylvzj3nPa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Doo4F9gylvzj3nPa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Doo4F9gylvzj3nPa .error-icon{fill:#552222;}#mermaid-svg-Doo4F9gylvzj3nPa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Doo4F9gylvzj3nPa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Doo4F9gylvzj3nPa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Doo4F9gylvzj3nPa .marker.cross{stroke:#333333;}#mermaid-svg-Doo4F9gylvzj3nPa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Doo4F9gylvzj3nPa p{margin:0;}#mermaid-svg-Doo4F9gylvzj3nPa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Doo4F9gylvzj3nPa .cluster-label text{fill:#333;}#mermaid-svg-Doo4F9gylvzj3nPa .cluster-label span{color:#333;}#mermaid-svg-Doo4F9gylvzj3nPa .cluster-label span p{background-color:transparent;}#mermaid-svg-Doo4F9gylvzj3nPa .label text,#mermaid-svg-Doo4F9gylvzj3nPa span{fill:#333;color:#333;}#mermaid-svg-Doo4F9gylvzj3nPa .node rect,#mermaid-svg-Doo4F9gylvzj3nPa .node circle,#mermaid-svg-Doo4F9gylvzj3nPa .node ellipse,#mermaid-svg-Doo4F9gylvzj3nPa .node polygon,#mermaid-svg-Doo4F9gylvzj3nPa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Doo4F9gylvzj3nPa .rough-node .label text,#mermaid-svg-Doo4F9gylvzj3nPa .node .label text,#mermaid-svg-Doo4F9gylvzj3nPa .image-shape .label,#mermaid-svg-Doo4F9gylvzj3nPa .icon-shape .label{text-anchor:middle;}#mermaid-svg-Doo4F9gylvzj3nPa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Doo4F9gylvzj3nPa .rough-node .label,#mermaid-svg-Doo4F9gylvzj3nPa .node .label,#mermaid-svg-Doo4F9gylvzj3nPa .image-shape .label,#mermaid-svg-Doo4F9gylvzj3nPa .icon-shape .label{text-align:center;}#mermaid-svg-Doo4F9gylvzj3nPa .node.clickable{cursor:pointer;}#mermaid-svg-Doo4F9gylvzj3nPa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Doo4F9gylvzj3nPa .arrowheadPath{fill:#333333;}#mermaid-svg-Doo4F9gylvzj3nPa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Doo4F9gylvzj3nPa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Doo4F9gylvzj3nPa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Doo4F9gylvzj3nPa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Doo4F9gylvzj3nPa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Doo4F9gylvzj3nPa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Doo4F9gylvzj3nPa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Doo4F9gylvzj3nPa .cluster text{fill:#333;}#mermaid-svg-Doo4F9gylvzj3nPa .cluster span{color:#333;}#mermaid-svg-Doo4F9gylvzj3nPa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Doo4F9gylvzj3nPa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Doo4F9gylvzj3nPa rect.text{fill:none;stroke-width:0;}#mermaid-svg-Doo4F9gylvzj3nPa .icon-shape,#mermaid-svg-Doo4F9gylvzj3nPa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Doo4F9gylvzj3nPa .icon-shape p,#mermaid-svg-Doo4F9gylvzj3nPa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Doo4F9gylvzj3nPa .icon-shape .label rect,#mermaid-svg-Doo4F9gylvzj3nPa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Doo4F9gylvzj3nPa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Doo4F9gylvzj3nPa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Doo4F9gylvzj3nPa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开发完成,提交测试
测试通过,运维部署
生产环境 production
正式线上服务器
对外提供服务
测试环境 testing
独立测试服务器
外部用户不可访问
开发环境 development
开发人员本机或开发服务器
外部用户不可访问
| 环境 | 英文 | 使用者 | 外部可见性 |
|---|---|---|---|
| 开发环境 | development |
开发人员 | 不可访问 |
| 测试环境 | testing |
测试人员 | 不可访问 |
| 生产环境 | production |
真实用户 | 对外提供服务 |
典型配置差异:开发环境可能就是本机 MySQL;测试环境是装了 JDK、Tomcat、MySQL 的独立服务器;生产环境由运维严格管控,部署流程与权限都与前两者不同。
外卖平台项目整体介绍
项目定位与端划分
本项目是为餐饮企业(餐厅、饭店)定制的软件产品,整体分为两端:
#mermaid-svg-VS3huvfdS8ig4yFn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VS3huvfdS8ig4yFn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VS3huvfdS8ig4yFn .error-icon{fill:#552222;}#mermaid-svg-VS3huvfdS8ig4yFn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VS3huvfdS8ig4yFn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VS3huvfdS8ig4yFn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VS3huvfdS8ig4yFn .marker.cross{stroke:#333333;}#mermaid-svg-VS3huvfdS8ig4yFn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VS3huvfdS8ig4yFn p{margin:0;}#mermaid-svg-VS3huvfdS8ig4yFn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VS3huvfdS8ig4yFn .cluster-label text{fill:#333;}#mermaid-svg-VS3huvfdS8ig4yFn .cluster-label span{color:#333;}#mermaid-svg-VS3huvfdS8ig4yFn .cluster-label span p{background-color:transparent;}#mermaid-svg-VS3huvfdS8ig4yFn .label text,#mermaid-svg-VS3huvfdS8ig4yFn span{fill:#333;color:#333;}#mermaid-svg-VS3huvfdS8ig4yFn .node rect,#mermaid-svg-VS3huvfdS8ig4yFn .node circle,#mermaid-svg-VS3huvfdS8ig4yFn .node ellipse,#mermaid-svg-VS3huvfdS8ig4yFn .node polygon,#mermaid-svg-VS3huvfdS8ig4yFn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VS3huvfdS8ig4yFn .rough-node .label text,#mermaid-svg-VS3huvfdS8ig4yFn .node .label text,#mermaid-svg-VS3huvfdS8ig4yFn .image-shape .label,#mermaid-svg-VS3huvfdS8ig4yFn .icon-shape .label{text-anchor:middle;}#mermaid-svg-VS3huvfdS8ig4yFn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VS3huvfdS8ig4yFn .rough-node .label,#mermaid-svg-VS3huvfdS8ig4yFn .node .label,#mermaid-svg-VS3huvfdS8ig4yFn .image-shape .label,#mermaid-svg-VS3huvfdS8ig4yFn .icon-shape .label{text-align:center;}#mermaid-svg-VS3huvfdS8ig4yFn .node.clickable{cursor:pointer;}#mermaid-svg-VS3huvfdS8ig4yFn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VS3huvfdS8ig4yFn .arrowheadPath{fill:#333333;}#mermaid-svg-VS3huvfdS8ig4yFn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VS3huvfdS8ig4yFn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VS3huvfdS8ig4yFn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VS3huvfdS8ig4yFn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VS3huvfdS8ig4yFn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VS3huvfdS8ig4yFn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VS3huvfdS8ig4yFn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VS3huvfdS8ig4yFn .cluster text{fill:#333;}#mermaid-svg-VS3huvfdS8ig4yFn .cluster span{color:#333;}#mermaid-svg-VS3huvfdS8ig4yFn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VS3huvfdS8ig4yFn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VS3huvfdS8ig4yFn rect.text{fill:none;stroke-width:0;}#mermaid-svg-VS3huvfdS8ig4yFn .icon-shape,#mermaid-svg-VS3huvfdS8ig4yFn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VS3huvfdS8ig4yFn .icon-shape p,#mermaid-svg-VS3huvfdS8ig4yFn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VS3huvfdS8ig4yFn .icon-shape .label rect,#mermaid-svg-VS3huvfdS8ig4yFn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VS3huvfdS8ig4yFn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VS3huvfdS8ig4yFn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VS3huvfdS8ig4yFn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 移动端应用
C端消费者使用
浏览菜品 / 加购 / 下单 / 地址管理
系统管理后台
餐饮企业内部员工使用
维护菜品 / 套餐 / 订单 / 分类 / 员工
MySQL reggie
三期迭代规划
| 期次 | 目标 | 移动端形态 |
|---|---|---|
| 一期 | 实现基本功能需求 | H5,手机浏览器访问 |
| 二期 | 改进移动端体验 | 微信小程序 |
| 三期 | 优化升级,提升访问性能 | 保持并优化 |
把项目拆成三期,与房地产分期开发的逻辑一致 ------ 控制风险、逐步交付。
产品原型解读
课程资料中的 产品原型 目录按端划分:
text
产品原型/
├── 瑞吉外卖后台(管理端) # backend
│ ├── login.html # 登录页
│ ├── 员工管理
│ ├── 分类管理
│ ├── 菜品管理(列表 / 新建 / 修改)
│ ├── 套餐管理(列表 / 新建)
│ └── 订单明细
└── 瑞吉外卖前台(用户端) # front
├── 地址管理 / 新增送餐地址
├── 点餐页(左分类 + 右菜品)
├── 选规格弹窗
├── 购物车
├── 个人中心
└── 历史订单
原型的交互是「点击即跳转」,不校验输入 ------ 它只说明「点了登录按钮会进入员工管理页」这样的功能链路,不做真实业务处理。
技术选型
#mermaid-svg-WpOyxTL0CEUNcgQe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WpOyxTL0CEUNcgQe .error-icon{fill:#552222;}#mermaid-svg-WpOyxTL0CEUNcgQe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WpOyxTL0CEUNcgQe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WpOyxTL0CEUNcgQe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WpOyxTL0CEUNcgQe .marker.cross{stroke:#333333;}#mermaid-svg-WpOyxTL0CEUNcgQe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WpOyxTL0CEUNcgQe p{margin:0;}#mermaid-svg-WpOyxTL0CEUNcgQe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster-label text{fill:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster-label span{color:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster-label span p{background-color:transparent;}#mermaid-svg-WpOyxTL0CEUNcgQe .label text,#mermaid-svg-WpOyxTL0CEUNcgQe span{fill:#333;color:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe .node rect,#mermaid-svg-WpOyxTL0CEUNcgQe .node circle,#mermaid-svg-WpOyxTL0CEUNcgQe .node ellipse,#mermaid-svg-WpOyxTL0CEUNcgQe .node polygon,#mermaid-svg-WpOyxTL0CEUNcgQe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WpOyxTL0CEUNcgQe .rough-node .label text,#mermaid-svg-WpOyxTL0CEUNcgQe .node .label text,#mermaid-svg-WpOyxTL0CEUNcgQe .image-shape .label,#mermaid-svg-WpOyxTL0CEUNcgQe .icon-shape .label{text-anchor:middle;}#mermaid-svg-WpOyxTL0CEUNcgQe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WpOyxTL0CEUNcgQe .rough-node .label,#mermaid-svg-WpOyxTL0CEUNcgQe .node .label,#mermaid-svg-WpOyxTL0CEUNcgQe .image-shape .label,#mermaid-svg-WpOyxTL0CEUNcgQe .icon-shape .label{text-align:center;}#mermaid-svg-WpOyxTL0CEUNcgQe .node.clickable{cursor:pointer;}#mermaid-svg-WpOyxTL0CEUNcgQe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WpOyxTL0CEUNcgQe .arrowheadPath{fill:#333333;}#mermaid-svg-WpOyxTL0CEUNcgQe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WpOyxTL0CEUNcgQe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WpOyxTL0CEUNcgQe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WpOyxTL0CEUNcgQe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WpOyxTL0CEUNcgQe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WpOyxTL0CEUNcgQe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster text{fill:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe .cluster span{color:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WpOyxTL0CEUNcgQe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WpOyxTL0CEUNcgQe rect.text{fill:none;stroke-width:0;}#mermaid-svg-WpOyxTL0CEUNcgQe .icon-shape,#mermaid-svg-WpOyxTL0CEUNcgQe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WpOyxTL0CEUNcgQe .icon-shape p,#mermaid-svg-WpOyxTL0CEUNcgQe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WpOyxTL0CEUNcgQe .icon-shape .label rect,#mermaid-svg-WpOyxTL0CEUNcgQe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WpOyxTL0CEUNcgQe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WpOyxTL0CEUNcgQe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WpOyxTL0CEUNcgQe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户层
H5 / Vue.js / ElementUI / 微信小程序
网关层
Nginx
应用层
Spring Boot / Spring MVC
Spring Session / Swagger / Lombok
数据层
MySQL / MyBatis / MyBatis-Plus / Redis
工具
Git / Maven / Junit
各层技术的作用:
| 分层 | 技术 | 在本项目中的作用 |
|---|---|---|
| 用户层 | H5 |
一期移动端页面载体 |
| 用户层 | Vue.js + ElementUI |
管理后台前端框架与组件库 |
| 用户层 | 微信小程序 |
二期移动端形态,需新学 |
| 网关层 | Nginx |
部署静态资源;集群场景下把请求分发到多个 Tomcat |
| 应用层 | Spring Boot / Spring MVC / Spring |
主体开发框架 |
| 应用层 | Lombok |
简化实体类 getter/setter,提供 @Slf4j 日志 |
| 应用层 | Spring Session |
集群环境下解决 Session 共享 |
| 应用层 | Swagger |
前后端分离改造后生成接口文档 |
| 数据层 | MySQL |
主存储 |
| 数据层 | MyBatis / MyBatis-Plus |
持久层框架,MP 提供分页插件与条件构造器 |
| 数据层 | Redis |
优化阶段引入,做缓存 |
| 工具 | Git |
多人协作下的代码版本管理 |
| 工具 | Maven / Junit |
项目构建与单元测试 |
关于 Nginx 与 Tomcat 的本质区别:Tomcat 是应用服务器 ,运行 Java Web 应用;Nginx 是高性能 HTTP 与反向代理服务器,主要承载静态资源并做请求转发与负载均衡。
功能架构
#mermaid-svg-uerDBVAWZOHqKDH1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uerDBVAWZOHqKDH1 .error-icon{fill:#552222;}#mermaid-svg-uerDBVAWZOHqKDH1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uerDBVAWZOHqKDH1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uerDBVAWZOHqKDH1 .marker.cross{stroke:#333333;}#mermaid-svg-uerDBVAWZOHqKDH1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uerDBVAWZOHqKDH1 p{margin:0;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge{stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 text{fill:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth--1{stroke-width:17;}#mermaid-svg-uerDBVAWZOHqKDH1 .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-0{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-0{stroke-width:14;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-1{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-1{stroke-width:11;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 text{fill:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-2{stroke-width:8;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-3{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-3{stroke-width:5;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-4{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-4{stroke-width:2;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-5{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-5{stroke-width:-1;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-6{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-6{stroke-width:-4;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-7{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-7{stroke-width:-7;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-8{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-8{stroke-width:-10;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-9{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-9{stroke-width:-13;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 polygon,#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 text{fill:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .node-icon-10{font-size:40px;color:black;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .edge-depth-10{stroke-width:-16;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled circle,#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:lightgray;}#mermaid-svg-uerDBVAWZOHqKDH1 .disabled text{fill:#efefef;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-root rect,#mermaid-svg-uerDBVAWZOHqKDH1 .section-root path,#mermaid-svg-uerDBVAWZOHqKDH1 .section-root circle,#mermaid-svg-uerDBVAWZOHqKDH1 .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-uerDBVAWZOHqKDH1 .section-root text{fill:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-root span{color:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .section-2 span{color:#ffffff;}#mermaid-svg-uerDBVAWZOHqKDH1 .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-uerDBVAWZOHqKDH1 .edge{fill:none;}#mermaid-svg-uerDBVAWZOHqKDH1 .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-uerDBVAWZOHqKDH1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外卖平台
系统管理后台
分类管理
菜品管理
套餐管理
菜品口味管理
员工登录与退出
员工管理
订单管理
移动端前台
手机号登录 H5
微信登录 小程序
地址管理
历史订单
菜品规格
购物车
菜品浏览
系统角色
| 角色 | 登录端 | 权限范围 |
|---|---|---|
| 后台系统管理员 | 管理后台 | 拥有所有操作权限,含删除用户、删除菜品/套餐 |
| 后台系统普通员工 | 管理后台 | 仅能管理菜品、套餐、订单等业务数据,不能删除用户 |
C 端用户 |
移动端应用 | 浏览菜品、加购、维护地址、下单;无后台账号 |
C 端即 Customer 端,指消费者一侧。三类角色对应三套完全不同的权限模型,这也决定了后续登录校验过滤器需要区分「员工登录态」与「用户登录态」两套放行规则。
项目目录结构说明
text
reggie_take_out/
├── pom.xml # Maven 坐标:Spring Boot 2.4.5 + MyBatis-Plus + Druid
└── src/
├── main/
│ ├── java/com/itheima/reggie/
│ │ ├── ReggieApplication.java # 启动类
│ │ ├── common/ # 通用结果类、异常、ObjectMapper
│ │ ├── config/ # WebMvcConfig 等配置类
│ │ ├── controller/ # 表现层
│ │ ├── service/ # 业务层接口与实现
│ │ ├── mapper/ # 持久层(MyBatis-Plus)
│ │ ├── entity/ # 与表一一对应的实体
│ │ ├── dto/ # 跨表数据传输对象
│ │ └── filter/ # 登录校验过滤器
│ └── resources/
│ ├── application.yml # 端口 / 数据源 / MyBatis-Plus 配置
│ ├── backend/ # 管理后台静态页面
│ └── front/ # 移动端静态页面
└── test/java/ # 单元测试
分层职责说明:
entity与数据库表严格一一对应,字段用驼峰命名,靠map-underscore-to-camel-case完成映射dto(Data Transfer Object)用于承载跨表 数据,例如DishDto同时包含菜品信息与口味列表filter中使用@WebFilter+@ServletComponentScan完成Servlet组件注册
完整可运行代码
Maven 坐标
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<groupId>com.itheima</groupId>
<artifactId>reggie_take_out</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 阿里云短信服务 SDK,手机验证码登录章节使用 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
</dependency>
<!-- MyBatis-Plus:分页插件、条件构造器、代码生成器均由它提供 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!-- Lombok:@Data 生成 getter/setter,@Slf4j 注入 log 变量 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Druid:阿里数据源,自带监控 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.5</version>
</plugin>
</plugins>
</build>
</project>
应用配置
src/main/resources/application.yml:
yaml
server:
port: 8080
spring:
application:
# 应用名称,可选;不配置时默认使用工程名
name: reggie_take_out
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
mybatis-plus:
configuration:
# 映射实体或属性时,去掉表名与字段名中的下划线,按驼峰命名法映射
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 主键策略:雪花算法生成 Long 型 ID
id-type: ASSIGN_ID
reggie:
# 文件上传后的落盘目录
path: D:\img\
配置要点:
serverTimezone=Asia/Shanghai必须显式指定,否则MySQL 8.x驱动会因时区解析失败而拒绝连接zeroDateTimeBehavior=convertToNull避免0000-00-00 00:00:00这类非法时间值导致转换异常allowPublicKeyRetrieval=true用于MySQL 8.x默认caching_sha2_password认证下的密码握手id-type: ASSIGN_ID表示主键由MyBatis-Plus使用雪花算法生成,因此所有实体主键必须使用Long而非Integer,否则会溢出
启动类
java
package com.itheima.reggie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Slf4j
@SpringBootApplication
@ServletComponentScan
@EnableTransactionManagement
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class, args);
log.info("项目启动成功...");
}
}
三个注解各自的作用:
| 注解 | 作用 |
|---|---|
@SpringBootApplication |
组合注解,等价于 @Configuration + @EnableAutoConfiguration + @ComponentScan |
@ServletComponentScan |
扫描 @WebFilter、@WebServlet、@WebListener,登录校验过滤器依赖它才能生效 |
@EnableTransactionManagement |
开启声明式事务,多表写入(如新增菜品同时写口味表)必须依赖它 |
@Slf4j 由 Lombok 提供,编译期自动生成 private static final Logger log 字段,因此可以直接使用 log.info(...) 输出日志,无需手工声明。
静态资源映射配置
默认 Spring Boot 只放行 classpath:/static/ 与 classpath:/templates/ 下的静态资源。本项目的前端页面放在 backend/ 与 front/ 目录,必须显式配置映射,否则访问返回 404。
java
package com.itheima.reggie.config;
import com.itheima.reggie.common.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 静态资源映射:/backend/** 与 /front/** 指向 classpath 下对应目录
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射...");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
/**
* 扩展 MVC 消息转换器,解决 Long 型 ID 与 LocalDateTime 的序列化问题
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器...");
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 索引 0 表示优先级最高,先于默认转换器被匹配
converters.add(0, messageConverter);
}
}
注意继承的是 WebMvcConfigurationSupport 而不是实现 WebMvcConfigurer。前者会完全接管 Spring MVC 的配置,导致 Spring Boot 的部分自动配置失效;后者只是在自动配置基础上追加。本项目选择继承方式,因此需要自己把资源映射与消息转换器配全。
API 速览
API / 注解 / 配置项 |
所属 | 作用 |
|---|---|---|
@SpringBootApplication |
org.springframework.boot.autoconfigure |
标识 Spring Boot 启动类 |
@ServletComponentScan |
org.springframework.boot.web.servlet |
启用 Servlet 组件扫描 |
@EnableTransactionManagement |
org.springframework.transaction.annotation |
开启声明式事务 |
@Slf4j |
lombok.extern.slf4j |
注入 log 日志变量 |
SpringApplication.run(Class, String[]) |
Spring Boot |
启动内嵌 Tomcat 并初始化容器 |
WebMvcConfigurationSupport |
Spring MVC |
MVC 配置基类,需重写钩子方法 |
ResourceHandlerRegistry.addResourceHandler |
Spring MVC |
配置 URL 路径与静态资源位置的映射 |
addResourceLocations |
Spring MVC |
指定实际资源目录,classpath:/ 前缀表示类路径 |
extendMessageConverters |
Spring MVC |
向转换器集合追加自定义 HttpMessageConverter |
server.port |
Spring Boot |
内嵌容器监听端口 |
spring.datasource.druid.* |
Druid |
数据源连接参数 |
mybatis-plus.configuration.map-underscore-to-camel-case |
MyBatis-Plus |
下划线转驼峰映射 |
mybatis-plus.global-config.db-config.id-type |
MyBatis-Plus |
主键生成策略 |
官方文档
Spring Boot参考文档:https://docs.spring.io/spring-boot/docs/2.4.5/reference/html/Spring Boot静态资源处理:https://docs.spring.io/spring-boot/docs/2.4.5/reference/html/spring-boot-features.html#boot-features-spring-mvc-static-contentMyBatis-Plus配置:https://baomidou.com/pages/56bac0/Lombok注解说明:https://projectlombok.org/features/logDruidSpring BootStarter:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
总结
本篇作为外卖平台项目的开篇,围绕「做什么、谁来做、用什么做」三条主线,把项目的整体轮廓完整地勾勒了出来:
- 软件开发流程:需求分析 → 设计 → 编码 → 测试 → 上线运维,是一条相对固定的流水线,后续每一天的开发任务都能在这条链条上找到自己的位置。
- 团队角色分工 :项目经理、产品经理、
UI设计师、架构师、开发、测试、运维各司其职;小型团队中职责会向开发工程师集中。 - 三种软件环境:开发、测试、生产三套环境相互隔离,是开发与运维沟通时必须先对齐的概念。
- 项目定位 :为餐饮企业定制的软件产品,分为系统管理后台 与移动端应用两端,按三期迭代逐步交付。
- 技术选型 :用户层
H5/Vue.js/ElementUI/微信小程序,网关层Nginx,应用层Spring Boot全家桶,数据层MySQL/MyBatis-Plus/Redis,工具Git/Maven/Junit。 - 工程骨架 :
Maven坐标、application.yml配置、启动类与静态资源映射已就绪,entity/dto/mapper/service/controller/filter分层清晰,为后续功能开发打好了地基。
从下一篇开始,我们将进入具体功能的编码实现,逐步把原型中的每一个页面、每一段业务逻辑落地成可运行的代码。