目錄
- 一、在本地部署并啟動Nginx服務
- 1. 解壓Nginx壓縮包
- 2. 啟動Nginx服務
- 3. 驗證Nginx是否啟動成功:
- 二、導入接口文檔
- 1. 黑馬程序員提供的YApi平臺
- 2. YApi Pro平臺
- 3. 推薦工具:Apifox
- 三、Swagger
- 1. 常用注解
- 1.1 @Api與@ApiModel
- 1.2 @ApiModelProperty與@ApiOperation
- 四、DTO的使用原因
- 1. 實體類 Employee
- 2. DTO EmployeeDTO
- 3. 使用 DTO 的場景
- 3.1 查詢員工信息
- 3.2 更新員工信息
- 3.3 新增員工
- 4. DTO、VO和實體類的區別
- 五、為什么使用 XML 注解而不是 MyBatis 注解
- 1. 使用 XML 注解的原因
- 1.1 動態 SQL 支持
- 1.2 SQL 與代碼分離
- 1.3 復用性
- 1.4 工具支持
- 2. MyBatis 注解的局限性
- 2.1 動態 SQL 支持有限
- 2.2 可讀性差
- 2.3 維護困難
- 六、Spring Boot 的請求映射規則
- 1. 類級別路徑
- 2. 方法級別路徑
- 2.1 分頁查詢
- 2.2 根據 ID 查詢菜品
- 2.3 修改菜品
- 2.4 新增菜品
- 2.5 批量刪除菜品
- 3. 如何區分不同的功能
- 4. 示例請求
- 4.1 新增菜品
- 4.2 修改菜品
- 4.3 批量刪除菜品
- 4.4 分頁查詢菜品
- 4.5 根據 ID 查詢菜品
- 七、接口設計中的是否必須原則
- 1. 請求參數說明
- 2. Java代碼片段分析
- 3. 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平臺
- 地址:http://yapi.smart-xwork.cn/
- 狀態:已棄用
- 功能:適合用于接口管理和文檔生成。
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
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; // 員工IDprivate 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
package com.sky.dto;import lombok.Data;
import java.io.Serializable;@Data
public class EmployeeDTO implements Serializable {private Long id; // 員工IDprivate String username; // 用戶名private String name; // 姓名private String phone; // 手機號private String sex; // 性別private String idNumber; // 身份證號
}
3. 使用 DTO 的場景
3.1 查詢員工信息
- 前端只需要員工的基本信息(如
id
、username
、name
、phone
、sex
、idNumber
)。 - 后端返回
EmployeeDTO
,過濾掉敏感字段(如password
)和內部字段(如createTime
)。
3.2 更新員工信息
- 前端傳遞
EmployeeDTO
作為請求體,后端根據 DTO 更新員工信息。 - 避免前端傳遞不必要的字段(如
password
、createTime
)。
3.3 新增員工
- 前端傳遞
EmployeeDTO
作為請求體,后端將 DTO 轉換為實體類并保存到數據庫。 - 避免前端傳遞內部字段(如
createTime
、updateTime
)。
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。
<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. 類級別路徑
@RestController
@RequestMapping("/admin/dish")
public class DishController {// 方法定義...
}
- 所有方法的公共路徑前綴是
/admin/dish
。
2. 方法級別路徑
2.1 分頁查詢
@GetMapping("/page")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {// 方法實現...
}
- 完整路徑是
/admin/dish/page
。
2.2 根據 ID 查詢菜品
@GetMapping("/{id}")
public Result<DishVO> getById(@PathVariable Long id) {// 方法實現...
}
- 完整路徑是
/admin/dish/{id}
。
2.3 修改菜品
@PutMapping
public Result update(@RequestBody DishDTO dishDTO) {// 方法實現...
}
- 由于
@PutMapping
沒有指定路徑,默認使用類級別的路徑/admin/dish
。
2.4 新增菜品
@PostMapping
public Result save(@RequestBody DishDTO dishDTO) {// 方法實現...
}
- 由于
@PostMapping
沒有指定路徑,默認使用類級別的路徑/admin/dish
。
2.5 批量刪除菜品
@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
- 請求體:
{"name": "宮保雞丁","price": 38.0,"flavors": [{"name": "微辣","value": "少辣"}] }
4.2 修改菜品
- HTTP 方法:
PUT
- URL:
/admin/dish
- 請求體:
{"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 |
-
必需參數:
page
和pageSize
是分頁查詢的必需參數,用于指定查詢的頁碼和每頁的記錄數。
-
可選參數:
categoryId
、name
和status
是可選參數,用于過濾查詢結果。
2. Java代碼片段分析
在此 Java 代碼中,DishPageQueryDTO
是一個數據傳輸對象(DTO),用于封裝分頁查詢的參數。以下是代碼的詳細分析:
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 語句根據傳入的參數生成查詢條件。以下是代碼的詳細分析:
<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>
- 可選參數:
name
、categoryId
和status
是可選參數,通過<if>
標簽動態生成查詢條件。- 如果某個參數為
null
,則對應的條件不會添加到 SQL 查詢中。
通過這種設計,分頁查詢接口既滿足了基本的查詢需求,又提供了靈活的過濾選項,適用于不同的業務場景。