《苍穹外卖》SpringBoot后端开发项目重点知识整理(DAY1 to DAY3)

目录

  • 一、在本地部署并启动Nginx服务
      1. 解压Nginx压缩包
      1. 启动Nginx服务
      1. 验证Nginx是否启动成功:
  • 二、导入接口文档
      1. 黑马程序员提供的YApi平台
      1. YApi Pro平台
      1. 推荐工具:Apifox
  • 三、Swagger
      1. 常用注解
      • 1.1 @Api与@ApiModel
      • 1.2 @ApiModelProperty与@ApiOperation
  • 四、DTO的使用原因
      1. 实体类 Employee
      1. DTO EmployeeDTO
      1. 使用 DTO 的场景
      • 3.1 查询员工信息
      • 3.2 更新员工信息
      • 3.3 新增员工
      1. DTO、VO和实体类的区别
  • 五、为什么使用 XML 注解而不是 MyBatis 注解
      1. 使用 XML 注解的原因
      • 1.1 动态 SQL 支持
      • 1.2 SQL 与代码分离
      • 1.3 复用性
      • 1.4 工具支持
      1. MyBatis 注解的局限性
      • 2.1 动态 SQL 支持有限
      • 2.2 可读性差
      • 2.3 维护困难
  • 六、Spring Boot 的请求映射规则
      1. 类级别路径
      1. 方法级别路径
      • 2.1 分页查询
      • 2.2 根据 ID 查询菜品
      • 2.3 修改菜品
      • 2.4 新增菜品
      • 2.5 批量删除菜品
      1. 如何区分不同的功能
      1. 示例请求
      • 4.1 新增菜品
      • 4.2 修改菜品
      • 4.3 批量删除菜品
      • 4.4 分页查询菜品
      • 4.5 根据 ID 查询菜品
  • 七、接口设计中的是否必须原则
      1. 请求参数说明
      1. Java代码片段分析
      1. XML映射文件分析
  • 八、阿里云OSS
  • 九、JWT令牌

视频链接:黑马程序员Java项目实战《苍穹外卖》,最适合新手的SpringBoot+SSM的企业级Java项目实战

网盘资料:苍穹外卖讲义&前后端源码

一、在本地部署并启动Nginx服务

在开发过程中,我们经常需要使用Nginx来部署前端项目或作为反向代理服务器。

1. 解压Nginx压缩包

首先,确保你已经从黑马程序员资料中下载了Nginx的压缩包。接下来,按照以下步骤解压:

选择解压路径

  • 将Nginx压缩包解压到一个全英文路径 中。例如:

    D:\nginx
    
  • 注意:路径中不要包含中文或特殊字符,否则可能会导致Nginx无法正常运行。


2. 启动Nginx服务

解压完成后,按照以下步骤启动Nginx:

进入Nginx目录

  • 打开解压后的Nginx文件夹,找到nginx.exe文件。路径通常为:

    C:\nginx\nginx.exe
    

启动Nginx

  • 双击nginx.exe文件,启动Nginx服务。
  • 启动后,Nginx会在后台运行,你可以在任务管理器中看到nginx.exe进程。

3. 验证Nginx是否启动成功:

  • 打开浏览器,访问以下地址(其中80是默认端口可省略不写):

    http://localhost:80
    
  • 如果看到此页面,说明Nginx已成功启动。

  • 注意:Nginx默认不会随系统自动启动,因此每次重启电脑后,都需要手动启动Nginx


二、导入接口文档

在开发过程中,接口管理平台是团队协作和项目管理的重要工具。以下是几个常用平台的对比:

1. 黑马程序员提供的YApi平台


2. YApi Pro平台

  • 地址:https://yapi.pro/
  • 问题:需要挂梯子才能访问,且极易卡顿,使用体验不佳。

3. 推荐工具:Apifox

  • 地址:https://apifox.com/
  • 优势:
    • 无需梯子即可访问。
    • 性能流畅,支持接口文档、Mock数据、自动化测试等功能。
    • 支持导入YApi数据格式的接口文档,方便无缝迁移现有项目。

三、Swagger

Swagger 是一种用于设计、构建、记录和使用 RESTful Web 服务的开源框架。它提供了一套工具,帮助开发者设计、构建、文档化和测试 API。

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


1. 常用注解

通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:

注解 说明
@Api 用在类上,例如Controller,表示对类的说明
@ApiModel 用在类上,例如entity、DTO、VO
@ApiModelProperty 用在属性上,描述属性信息
@ApiOperation 用在方法上,例如Controller的方法,说明方法的用途、作用

1.1 @Api与@ApiModel

1.2 @ApiModelProperty与@ApiOperation



四、DTO的使用原因

在项目中,Employee 是实体类(Entity),用于表示数据库中的员工记录,而 EmployeeDTO 是数据传输对象(DTO),用于在不同层之间传递数据。以下是使用 DTO 的主要原因和优势:

1. 实体类 Employee

java 复制代码
package com.sky.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;           // 员工ID
    private String username;   // 用户名
    private String name;       // 姓名
    private String password;   // 密码(敏感字段)
    private String phone;      // 手机号
    private String sex;        // 性别
    private String idNumber;   // 身份证号
    private Integer status;    // 状态
    private LocalDateTime createTime; // 创建时间(内部字段)
    private LocalDateTime updateTime; // 更新时间(内部字段)
    private Long createUser;   // 创建人(内部字段)
    private Long updateUser;   // 更新人(内部字段)
}

2. DTO EmployeeDTO

java 复制代码
package com.sky.dto;

import lombok.Data;
import java.io.Serializable;

@Data
public class EmployeeDTO implements Serializable {

    private Long id;           // 员工ID
    private String username;   // 用户名
    private String name;       // 姓名
    private String phone;      // 手机号
    private String sex;        // 性别
    private String idNumber;   // 身份证号
}

3. 使用 DTO 的场景

3.1 查询员工信息

  • 前端只需要员工的基本信息(如 idusernamenamephonesexidNumber)。
  • 后端返回 EmployeeDTO,过滤掉敏感字段(如 password)和内部字段(如 createTime)。

3.2 更新员工信息

  • 前端传递 EmployeeDTO 作为请求体,后端根据 DTO 更新员工信息。
  • 避免前端传递不必要的字段(如 passwordcreateTime)。

3.3 新增员工

  • 前端传递 EmployeeDTO 作为请求体,后端将 DTO 转换为实体类并保存到数据库。
  • 避免前端传递内部字段(如 createTimeupdateTime)。

4. DTO、VO和实体类的区别

特性 DTO VO Entity
目的 数据传输 数据展示或封装值 表示数据库中的数据结构
使用场景 跨层数据传输(如Controller-Service) 展示层或领域模型 数据库操作、业务逻辑
可变性 可变(通常有setter) 通常不可变(无setter) 可变(用于持久化和业务逻辑)
字段 与传输需求相关 与展示或业务逻辑相关 与数据库表字段严格对应
行为 通常无行为 可能包含简单行为(如格式化) 包含业务逻辑和验证规则
示例 UserDTO UserVO UserEntity

五、为什么使用 XML 注解而不是 MyBatis 注解

1. 使用 XML 注解的原因

1.1 动态 SQL 支持

  • XML 提供了强大的动态 SQL 支持,例如 <if><foreach><choose> 等标签。
  • 在复杂的查询场景中,动态 SQL 可以更灵活地构建 SQL 语句。

1.2 SQL 与代码分离

  • 将 SQL 语句写在 XML 文件中,可以使 SQL 与 Java 代码分离,便于维护和管理。
  • 对于复杂的 SQL 语句,XML 文件的可读性更高。

1.3 复用性

  • XML 文件中的 SQL 语句可以在多个 Mapper 接口中复用。
  • 例如,可以在不同的 Mapper 接口中引用同一个 SQL 片段。

1.4 工具支持

  • MyBatis 提供了丰富的工具支持 XML 文件的编写和调试。
  • 例如,MyBatis Generator 可以自动生成 XML 映射文件。

2. MyBatis 注解的局限性

2.1 动态 SQL 支持有限

  • MyBatis 注解对动态 SQL 的支持较弱,复杂的 SQL 语句难以用注解实现。
  • 例如,@Select 注解无法直接实现 <foreach> 这样的动态 SQL。
xml 复制代码
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
  select setmeal_id from setmeal_dish where dish_id in
  <foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
      #{dishId}
  </foreach>
</select>

2.2 可读性差

  • 复杂的 SQL 语句写在注解中会导致代码冗长,可读性差。
  • 例如,一个包含多个条件的查询语句会显得非常混乱。

2.3 维护困难

  • SQL 语句与 Java 代码混合在一起,维护起来不如 XML 文件方便。
  • 修改 SQL 语句时需要重新编译 Java 代码。

你提到的代码中有两个 @PutMapping 注解没有指定路径,这意味着它们默认映射到类级别的路径 /admin/dish。以下是对这个问题的详细解释:


六、Spring Boot 的请求映射规则

在 Spring Boot 中,请求的映射是通过 类级别的 @RequestMapping方法级别的 @PutMapping@GetMapping 等注解 共同决定的。

  • 类级别的 @RequestMapping
    • 定义了该类中所有方法的公共路径前缀。
    • 例如,@RequestMapping("/admin/dish") 表示该类中的所有方法都映射到 /admin/dish 路径下。
    • 管理端 发出的请求,统一使用/admin作为前缀。
    • 用户端 发出的请求,统一使用/user作为前缀。
  • 方法级别的 @PutMapping@GetMapping
    • 定义了具体的 HTTP 方法和路径。
    • 如果方法级别的注解没有指定路径,则默认使用类级别的路径。

1. 类级别路径

java 复制代码
@RestController
@RequestMapping("/admin/dish")
public class DishController {
    // 方法定义...
}
  • 所有方法的公共路径前缀是 /admin/dish

2. 方法级别路径

2.1 分页查询

java 复制代码
@GetMapping("/page")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {
    // 方法实现...
}
  • 完整路径是 /admin/dish/page

2.2 根据 ID 查询菜品

java 复制代码
@GetMapping("/{id}")
public Result<DishVO> getById(@PathVariable Long id) {
    // 方法实现...
}
  • 完整路径是 /admin/dish/{id}

2.3 修改菜品

java 复制代码
@PutMapping
public Result update(@RequestBody DishDTO dishDTO) {
    // 方法实现...
}
  • 由于 @PutMapping 没有指定路径,默认使用类级别的路径 /admin/dish

2.4 新增菜品

java 复制代码
@PostMapping
public Result save(@RequestBody DishDTO dishDTO) {
    // 方法实现...
}
  • 由于 @PostMapping 没有指定路径,默认使用类级别的路径 /admin/dish

2.5 批量删除菜品

java 复制代码
@DeleteMapping
public Result delete(@RequestParam List<Long> ids) {
    // 方法实现...
}
  • 由于 @DeleteMapping 没有指定路径,默认使用类级别的路径 /admin/dish

3. 如何区分不同的功能

Spring Boot 通过 HTTP 方法 来区分不同的功能。例如:

HTTP 方法 路径 功能
POST /admin/dish 新增菜品
PUT /admin/dish 修改菜品
DELETE /admin/dish 批量删除菜品
GET /admin/dish/page 分页查询菜品
GET /admin/dish/{id} 根据 ID 查询菜品

4. 示例请求

4.1 新增菜品

  • HTTP 方法POST

  • URL/admin/dish

  • 请求体

    json 复制代码
    {
      "name": "宫保鸡丁",
      "price": 38.0,
      "flavors": [
        {
          "name": "微辣",
          "value": "少辣"
        }
      ]
    }

4.2 修改菜品

  • HTTP 方法PUT

  • URL/admin/dish

  • 请求体

    json 复制代码
    {
      "id": 1,
      "name": "宫保鸡丁",
      "price": 40.0,
      "flavors": [
        {
          "name": "微辣",
          "value": "少辣"
        }
      ]
    }

4.3 批量删除菜品

  • HTTP 方法DELETE
  • URL/admin/dish?ids=1,2,3
  • 请求参数ids=1,2,3

4.4 分页查询菜品

  • HTTP 方法GET
  • URL/admin/dish/page?page=1&pageSize=10
  • 请求参数page=1&pageSize=10

4.5 根据 ID 查询菜品

  • HTTP 方法GET
  • URL/admin/dish/1
  • 路径参数id=1

七、接口设计中的是否必须原则

参数的必需与非必需性是通过不同的方式来体现的,以下是具体案例


1. 请求参数说明

从接口文档中可以看到,请求参数包括以下几项:

参数名 类型 说明 必需性 示例值
categoryId string 分类id 可选 101
name string 菜品名称 可选 官保鸡丁
page string 页码 必需 1
pageSize string 每页记录数 必需 10
status string 分类状态 可选 1
  • 必需参数

    • pagepageSize 是分页查询的必需参数,用于指定查询的页码和每页的记录数。
  • 可选参数

    • categoryIdnamestatus 是可选参数,用于过滤查询结果。

2. Java代码片段分析

在此 Java 代码中,DishPageQueryDTO 是一个数据传输对象(DTO),用于封装分页查询的参数。以下是代码的详细分析:

java 复制代码
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
    // 1. 使用 PageHelper 进行分页
    PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
    
    // 2. 调用 Mapper 进行查询
    Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
    
    // 3. 返回分页结果
    return new PageResult(page.getTotal(), page.getResult());
}
  • 必需参数
    • dishPageQueryDTO.getPage()dishPageQueryDTO.getPageSize() 是分页查询的必需参数。
    • 如果这两个参数为空或未提供,分页功能将无法正常工作。

3. XML映射文件分析

在 SQL 代码中,动态 SQL 语句根据传入的参数生成查询条件。以下是代码的详细分析:

xml 复制代码
<select id="pageQuery" resultType="com.sky.vo.DishVO">
    select d.* , c.name as categoryName 
    from dish d 
    left outer join category c on d.category_id = c.id
    <where>
        <if test="name != null">
            and d.name like concat('%',#{name},'%')
        </if>
        <if test="categoryId != null">
            and d.category_id = #{categoryId}
        </if>
        <if test="status != null">
            and d.status = #{status}
        </if>
    </where>
    order by d.create_time desc
</select>
  • 可选参数
    • namecategoryIdstatus 是可选参数,通过 <if> 标签动态生成查询条件。
    • 如果某个参数为 null,则对应的条件不会添加到 SQL 查询中。

通过这种设计,分页查询接口既满足了基本的查询需求,又提供了灵活的过滤选项,适用于不同的业务场景。

八、阿里云OSS

九、JWT令牌

相关推荐
芒猿君10 分钟前
AQS——同步器框架之源
后端
SaebaRyo19 分钟前
手把手教你在网站中启用https和http2
后端·nginx·https
Forget the Dream21 分钟前
设计模式之迭代器模式
java·c++·设计模式·迭代器模式
MiniFlyZt29 分钟前
消息队列MQ(RabbitMQ)
spring boot·分布式·微服务·rabbitmq
大丈夫在世当日食一鲲29 分钟前
Java中用到的设计模式
java·开发语言·设计模式
A-Kamen33 分钟前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
练川35 分钟前
Stream特性(踩坑):惰性执行、不修改原始数据源
java·stream
豆豆酱39 分钟前
Transformer结构详解
后端
upsilon40 分钟前
golang切片slice
后端·go
狂奔小菜鸡40 分钟前
Java运行时数据区
java·jvm·后端