Java 项目实战: 外卖平台-软件开发流程与项目整体介绍

软件开发流程、角色分工与项目整体介绍

外卖平台-项目背景

随着餐饮行业竞争的加剧,传统餐饮系统间畅通程度较差,收银产品、会员产品、供应链产品等各个模块相互割裂,形成了各个信息孤岛,导致信息不对称、商家工作耗能大、增加商家人力物力和沟通成本,在三高一低的压力下,商家的竞争力不断被弱化。

用户点餐外卖全流程

浏览 → 加购 → 下单 → 支付
#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;测试环境是装了 JDKTomcatMySQL 的独立服务器;生产环境由运维严格管控,部署流程与权限都与前两者不同。

外卖平台项目整体介绍

项目定位与端划分

本项目是为餐饮企业(餐厅、饭店)定制的软件产品,整体分为两端:
#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 项目构建与单元测试

关于 NginxTomcat 的本质区别: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 完成映射
  • dtoData 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 开启声明式事务,多表写入(如新增菜品同时写口味表)必须依赖它

@Slf4jLombok 提供,编译期自动生成 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 主键生成策略

官方文档

总结

本篇作为外卖平台项目的开篇,围绕「做什么、谁来做、用什么做」三条主线,把项目的整体轮廓完整地勾勒了出来:

  • 软件开发流程:需求分析 → 设计 → 编码 → 测试 → 上线运维,是一条相对固定的流水线,后续每一天的开发任务都能在这条链条上找到自己的位置。
  • 团队角色分工 :项目经理、产品经理、UI 设计师、架构师、开发、测试、运维各司其职;小型团队中职责会向开发工程师集中。
  • 三种软件环境:开发、测试、生产三套环境相互隔离,是开发与运维沟通时必须先对齐的概念。
  • 项目定位 :为餐饮企业定制的软件产品,分为系统管理后台移动端应用两端,按三期迭代逐步交付。
  • 技术选型 :用户层 H5/Vue.js/ElementUI/微信小程序,网关层 Nginx,应用层 Spring Boot 全家桶,数据层 MySQL/MyBatis-Plus/Redis,工具 Git/Maven/Junit
  • 工程骨架Maven 坐标、application.yml 配置、启动类与静态资源映射已就绪,entity/dto/mapper/service/controller/filter 分层清晰,为后续功能开发打好了地基。

从下一篇开始,我们将进入具体功能的编码实现,逐步把原型中的每一个页面、每一段业务逻辑落地成可运行的代码。

相关推荐
她说..1 小时前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
步行cgn1 小时前
BeanFactory 与 FactoryBean 的区别:面试深度解析
java·后端·spring
X7766X1 小时前
暴雨重构国产大模型底层加速体系
服务器
IT 行者1 小时前
JDK 27 正式发布:内存、安全、并发三路齐发
java
伍一514 小时前
hiprint-spring-boot打印组件介绍
java·hiprint
Wang's Blog9 小时前
Java 接入Redis: 服务启动停止与后台运行配置
java·服务器·redis
此时不提桶,更待何时10 小时前
01-04-B-垃圾回收面试与生产事故实战
java·jvm·面试
鹿角片ljp11 小时前
KV Cache 解析
java·算法