【苍穹外卖】Day01:从零认识企业级项目开发

目录

一、软件开发整体介绍

[1.1 软件开发流程](#1.1 软件开发流程)

[1.2 角色分工](#1.2 角色分工)

[1.3 软件环境](#1.3 软件环境)

二、苍穹外卖项目介绍

[2.1 项目简介](#2.1 项目简介)

[2.2 产品原型](#2.2 产品原型)

[2.3 技术选型](#2.3 技术选型)

三、开发环境搭建

[3.1 前端环境搭建](#3.1 前端环境搭建)

[3.2 后端环境搭建](#3.2 后端环境搭建)

[3.2.1 项目结构](#3.2.1 项目结构)

[3.2.2 Git 版本控制](#3.2.2 Git 版本控制)

[3.2.3 数据库环境搭建](#3.2.3 数据库环境搭建)

[3.2.4 前后端联调](#3.2.4 前后端联调)

[3.2.5 Nginx 反向代理与负载均衡](#3.2.5 Nginx 反向代理与负载均衡)

[3.2.6 完善登录功能(MD5加密)](#3.2.6 完善登录功能(MD5加密))

四、导入接口文档

[五、Swagger 接口文档工具](#五、Swagger 接口文档工具)

[5.1 介绍](#5.1 介绍)

[5.2 使用步骤](#5.2 使用步骤)

[5.3 常用注解](#5.3 常用注解)

六、总结


本文是《苍穹外卖》项目实战的第一天课程记录,适合刚接触企业级开发的初学者。我们将从软件开发流程讲起,带你了解一个真实项目是如何从需求到上线的,并完成开发环境的搭建。


一、软件开发整体介绍

作为一名软件开发工程师,你需要了解软件开发的完整流程、团队角色分工以及常见的软件环境。

1.1 软件开发流程

一个软件项目从无到有,通常经历以下 5 个阶段:

阶段 主要工作 产出物
需求分析 产品经理调研需求,编写需求规格说明书、产品原型 需求文档、产品原型(HTML页面)
设计 UI设计、数据库设计、接口设计 界面效果图、数据库表结构、接口文档
编码 开发工程师编写代码,进行单元测试 项目代码、单元测试报告
测试 测试工程师功能测试、性能测试 测试报告
上线运维 运维工程师部署环境,项目上线 线上可运行的系统

产品原型:用网页形式展示页面布局、数据展示和交互效果,是开发的重要参考。

1.2 角色分工

一个标准的项目团队通常包含以下角色:

角色 职责
项目经理 整体把控进度、任务分配
产品经理 需求调研、输出需求文档和原型
UI设计师 设计界面效果图
架构师 技术选型、架构设计
开发工程师 功能代码实现(我们的角色)
测试工程师 编写测试用例、输出测试报告
运维工程师 环境搭建、项目上线

实际项目中,人员可能身兼数职,比如项目经理兼任架构师。

1.3 软件环境

开发过程中会接触三种环境:

  • 开发环境(development):开发人员本地使用,外部无法访问。

  • 测试环境(testing):独立服务器,供测试人员使用。

  • 生产环境(production):正式对外提供服务的线上环境。

项目开发完成后,依次经过开发 → 测试 → 生产环境的部署流程。


二、苍穹外卖项目介绍

2.1 项目简介

"苍穹外卖"是一款专为餐饮企业定制的软件产品,包含:

  • 管理端:供餐厅内部员工使用,管理分类、菜品、套餐、订单、员工等。

  • 用户端:供消费者使用的小程序,支持浏览菜品、加购物车、下单、支付等。

2.2 产品原型

产品原型用于展示业务功能,并非最终页面效果。课程资料中提供了管理端和用户端两份原型文件。

管理端主要功能

  • 登录/退出

  • 员工管理

  • 分类管理

  • 菜品管理

  • 套餐管理

  • 订单管理

  • 数据统计

用户端主要功能

  • 微信登录

  • 点餐(分类/菜品浏览)

  • 购物车

  • 订单支付

  • 个人信息、历史订单

2.3 技术选型

项目采用前后端分离架构,技术栈如下:


三、开发环境搭建

3.1 前端环境搭建

前端工程基于 Nginx 部署。从资料中找到 Nginx,解压到非中文目录 ,双击 nginx.exe 启动,访问 http://localhost:80 即可看到管理端页面。

3.2 后端环境搭建

3.2.1 项目结构

后端基于 Maven 分模块构建,父工程 sky-take-out 下包含:

模块 作用
sky-common 公共类:工具类、常量、异常等
sky-pojo 实体类:Entity、DTO、VO
sky-server 核心服务:Controller、Service、Mapper、配置等

sky-common 包结构

  • constant:常量

  • context:上下文

  • enumeration:枚举

  • exception:自定义异常

  • json:JSON处理

  • properties:配置属性

  • result:统一返回结果

  • utils:工具类

sky-pojo 包结构

  • Entity:与数据库表对应

  • DTO:数据传输对象

  • VO:视图对象(返回给前端)

  • POJO:普通Java对象

sky-server 包结构

  • config:配置类

  • controller:控制器

  • interceptor:拦截器

  • mapper:数据访问层

  • service:业务层

  • SkyApplication:启动类

3.2.2 Git 版本控制
  1. 在 IDEA 中创建 Git 本地仓库。

  2. 在 Gitee 创建远程仓库。

  3. 提交代码到本地仓库(忽略 .ideatarget 等文件)。

  4. 添加远程仓库地址并推送。

3.2.3 数据库环境搭建

从资料中找到 sky.sql,直接在 MySQL 客户端中执行,会创建 11 张表:

表名 中文名
employee 员工表
category 分类表
dish 菜品表
dish_flavor 菜品口味表
setmeal 套餐表
setmeal_dish 套餐菜品关系表
user 用户表
address_book 地址表
shopping_cart 购物车表
orders 订单表
order_detail 订单明细表
3.2.4 前后端联调

后端初始工程已实现登录功能。启动后端服务,前端访问登录页面,输入用户名密码即可测试。

登录流程

  1. Controller 接收 EmployeeLoginDTO,调用 Service。在sky-server模块中,com.sky.controller.admin.EmployeeController

    java 复制代码
    /**
         * 登录
         *
         * @param employeeLoginDTO
         * @return
         */
        @PostMapping("/login")
        public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
            log.info("员工登录:{}", employeeLoginDTO);
    		//调用service方法查询数据库
            Employee employee = employeeService.login(employeeLoginDTO);
    
            //登录成功后,生成jwt令牌
            Map<String, Object> claims = new HashMap<>();
            claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
            String token = JwtUtil.createJWT(
                    jwtProperties.getAdminSecretKey(),
                    jwtProperties.getAdminTtl(),
                    claims);
    
            EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
                    .id(employee.getId())
                    .userName(employee.getUsername())
                    .name(employee.getName())
                    .token(token)
                    .build();
    
            return Result.success(employeeLoginVO);
        }
  2. Service 根据用户名查询员工,校验密码、账号状态。在sky-server模块中,com.sky.service.impl.EmployeeServiceImpl

    java 复制代码
    /**
         * 员工登录
         *
         * @param employeeLoginDTO
         * @return
         */
        public Employee login(EmployeeLoginDTO employeeLoginDTO) {
            String username = employeeLoginDTO.getUsername();
            String password = employeeLoginDTO.getPassword();
    
            //1、根据用户名查询数据库中的数据
            Employee employee = employeeMapper.getByUsername(username);
    
            //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
            if (employee == null) {
                //账号不存在
                throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
            }
    
            //密码比对
            if (!password.equals(employee.getPassword())) {
                //密码错误
                throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
            }
    
            if (employee.getStatus() == StatusConstant.DISABLE) {
                //账号被锁定
                throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
            }
    
            //3、返回实体对象
            return employee;
        }
  3. 登录成功生成 JWT 令牌,返回 EmployeeLoginVO。在sky-server模块中,com.sky.mapper.EmployeeMapper

    java 复制代码
    @Mapper
    public interface EmployeeMapper {
    
        /**
         * 根据用户名查询员工
         * @param username
         * @return
         */
        @Select("select * from employee where username = #{username}")
        Employee getByUsername(String username);
    
    }

Mapper 层 使用 @Select 注解查询数据库。

3.2.5 Nginx 反向代理与负载均衡

问题 :前端请求 http://localhost/api/employee/login,后端接口 http://localhost:8080/admin/employee/login,地址不一致,如何请求到后端?

答案:Nginx 反向代理。

反向代理的好处

  • 提高访问速度(缓存)

  • 负载均衡

  • 保证后端服务安全(不暴露真实地址)

配置方式

javascript 复制代码
server{
    listen 80;
    server_name localhost;
    
    location /api/{
        proxy_pass http://localhost:8080/admin/; #反向代理
    }
}

**proxy_pass:**该指令是用来设置代理服务器的地址,可以是主机名称,IP地址加端口号等形式。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../..这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://localhost:8080/admin/上来

负载均衡配置

javascript 复制代码
upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}
server{
    listen 80;
    server_name localhost;
    
    location /api/{
        proxy_pass http://webservers/admin;#负载均衡
    }
}

**upstream:**如果代理服务器是一组服务器的话,我们可以使用upstream指令配置后端服务器组。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../..这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://webservers/admin,根据webservers名称找到一组服务器,根据设置的负载均衡策略(默认是轮询)转发到具体的服务器。

**注:**upstream后面的名称可自定义,但要上下保持一致

常见负载均衡策略:

名称 说明
轮询 默认方式
weight 权重方式,默认为1,权重越高,被分配的客户端请求就越多
ip_hash 依据ip分配方式,这样每个访客可以固定访问一个后端服务
least_conn 依据最少连接方式,把请求优先分配给连接数少的后端服务
url_hash 依据url分配方式,这样相同的url会被分配到同一个后端服务
fair 依据响应时间方式,响应时间短的服务将会被优先分配
3.2.6 完善登录功能(MD5加密)

问题:数据库中密码明文存储,不安全。

解决:使用 MD5 加密。

  1. 修改数据库中密码为 MD5 密文。

  2. 修改 Java 代码,将前端密码进行 MD5 加密后再比对:

java 复制代码
/**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {

        //1、根据用户名查询数据库中的数据
       
        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        //.......
        //密码比对
        // TODO 后期需要进行md5加密,然后再进行比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        //........

        //3、返回实体对象
        return employee;
    }

四、导入接口文档

前后端分离开发模式下,接口定义至关重要。我们使用 Apifox中的YApi 平台管理接口文档。

操作步骤

  1. 访问 YApi 平台,创建项目。

  2. 从资料中找到接口 JSON 文件(管理端、用户端)。

  3. 导入到 YApi 中。


五、Swagger 接口文档工具

5.1 介绍

Swagger (API Documentation & Design Tools for Teams | Swagger) 是一个用于生成、描述、调用 RESTful 接口的框架,能在线自动生成接口文档,方便前后端协作和测试。目前常用 knife4j 作为增强解决方案。

5.2 使用步骤

导入 Maven 坐标

java 复制代码
<dependency>
   <groupId>com.github.xiaoymin</groupId>
   <artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>

添加配置类(WebMvcConfiguration):

java 复制代码
/**
     * 通过knife4j生成接口文档
     * @return
*/
    @Bean
    public Docket docket() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("苍穹外卖项目接口文档")
                .version("2.0")
                .description("苍穹外卖项目接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

设置静态资源映射

WebMvcConfiguration.java

java 复制代码
/**
     * 设置静态资源映射
     * @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}

访问测试 :接口文档访问路径为 http://ip:port/doc.html ---> http://localhost:8080/doc.html

**思考:**通过 Swagger 就可以生成接口文档,那么我们就不需要 Yapi 了?

1、Yapi 是设计阶段使用的工具,管理和维护接口

2、Swagger 在开发阶段使用的框架,帮助后端开发人员做后端的接口测

5.3 常用注解

注解 说明
@Api 用在类上,说明类的用途
@ApiModel 用在类上,说明数据模型
@ApiModelProperty 用在属性上,描述属性
@ApiOperation 用在方法上,说明方法用途

示例:

在sky-pojo模块中

EmployeeLoginDTO.java

java 复制代码
@Data
@ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable {

    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("密码")
    private String password;

}

在sky-server模块中

EmployeeController.java

java 复制代码
/**
 * 员工管理
 */
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "员工相关接口")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) 	{
        //..............

        
    }

    /**
     * 退出
     *
     * @return
     */
    @PostMapping("/logout")
    @ApiOperation("员工退出")
    public Result<String> logout() {
        return Result.success();
    }

}

启动服务:访问http://localhost:8080/doc.html


六、总结

今天我们完成了:

  • 了解软件开发全流程、角色分工、三种环境

  • 认识苍穹外卖项目:管理端 + 用户端

  • 搭建前端(Nginx)和后端(Maven多模块)环境

  • 配置 Git、数据库,完成前后端联调

  • 理解 Nginx 反向代理和负载均衡

  • 使用 MD5 加密完善登录功能

  • 导入接口文档,集成 Swagger(knife4j)生成在线接口文档

相关推荐
智购科技自动贩卖机1 小时前
自动售货机嵌入式系统时钟同步与时间管理实战:从RTC校准到断网时间保持的工程实践
大数据·linux·数据库·人工智能·yolo
Y3815326621 小时前
SEO 周报自动化:从采集数据到一页报告
数据库·搜索引擎
雨辰AI1 小时前
多租户数据库资源配额管控|避免租户资源抢占雪崩(金仓 / 达梦 / 高斯 /openGauss 全库原生适配)
java·大数据·数据库·后端
ThornArmor1 小时前
《向内深潜,向外飞掠》
c语言·开发语言·c++·vim·visual studio
AI深栈1 小时前
第 12 章 · AI智能体的结构化输出与流式响应
java·人工智能
传奇开心果编程1 小时前
【仓颉语言基础语法学与练】第1课:从零开始
开发语言·学习·华为
君顾11 小时前
本地AI错题纠正小程序:端侧推理与错题闭环实战
java·开发语言·错题
吠品1 小时前
Python 写入 Excel 的两种主流方案实际用法总结
c语言·开发语言·算法
Wang's Blog1 小时前
Java 服务器: Linux-yum在线安装与lrzsz文件传输
java·服务器