《蒼穹外賣》SpringBoot后端開發項目核心知識點與常見問題整理(DAY1 to DAY3)

目錄

  • 一、在本地部署并啟動Nginx服務
    • 1. 解壓Nginx壓縮包
    • 2. 啟動Nginx服務
    • 3. 驗證Nginx是否啟動成功:
  • 二、導入接口文檔
    • 1. 黑馬程序員提供的YApi平臺
    • 2. YApi Pro平臺
    • 3. 推薦工具:Apifox
  • 三、Swagger
    • 1. 常用注解
      • 1.1 @Api與@ApiModel
      • 1.2 @ApiModelProperty與@ApiOperation
  • 四、基于JWT和ThreadLocal動態獲取員工ID
    • 1. 在pom.xml中引入JWT依賴
    • 2. 在application.yaml中配置JWT參數
    • 3. 使用JWT獲取當前登錄員工ID
    • 4. 通過攔截器解析JWT
    • 5. 使用ThreadLocal傳遞員工ID
    • 6. 在Service中獲取員工ID
  • 五、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. 請求參數說明
      • 1.1 Java代碼分析
        • 1.1.1 必需參數
      • 1.2 XML映射文件分析
        • 1.2.1 可選參數
    • 2. 返回響應說明
      • 2.1 Java代碼分析
        • 2.1.1 必需參數
        • 2.1.2 可選參數
      • 2.2 返回響應示例
        • 2.2.1 成功響應(帶數據)
        • 2.2.2 成功響應(不帶數據)
        • 2.2.3 失敗響應
  • 九、阿里云OSS配置指南
    • 1. 注冊阿里云OSS賬號
    • 2. 獲取關鍵信息
    • 3. 更新配置文件
    • 4, 重新運行服務
  • 十、SpringBoot配置類詳解
    • 1. 生產環境與開發環境配置
      • 1.1 配置文件命名規則
      • 1.2 激活環境配置
      • 1.3 占位符替換
        • 示例
    • 2. Spring 前綴與自定義前綴配置
      • 2.1 Spring 內置配置
      • 2.2 自定義配置
    • 3. 自定義配置類的注冊與使用
      • 3.1 創建配置類
        • 3.1.1 JWT 配置類
        • 3.1.2 阿里云 OSS 配置類
      • 3.2 使用配置類
        • 3.2.1 在 Service 中使用配置類
      • 3.3 配置類的注冊
  • 十一、SpringBoot注解匯總
    • 1. Spring MVC 相關注解
    • 2. Swagger 相關注解
    • 3. Spring 核心注解
    • 4. AOP 相關注解
    • 5. Lombok 相關注解
    • 6. MyBatis 相關注解
    • 7. 配置相關注解


本文旨在為剛完成《蒼穹外賣》項目DAY1至DAY3章節學習的學員提供難點解析與核心知識點梳理。鑒于該項目由黑馬程序員于2023年推出,在實際構建過程中可能會遇到諸如網站鏈接失效、阿里OSS服務不可用等問題。本文將針對這些常見問題提供解決方案,并幫助學員更好地掌握項目關鍵內容。

視頻鏈接:黑馬程序員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

在這里插入圖片描述
在這里插入圖片描述


四、基于JWT和ThreadLocal動態獲取員工ID

在開發員工管理系統時,新增員工時需要記錄創建人和修改人的ID。如果直接使用固定值,會導致數據不準確,無法真實反映操作者。

public void save(EmployeeDTO employeeDTO) {Employee employee = new Employee();employee.setCreateUser(10L); // 固定值employee.setUpdateUser(10L); // 固定值employeeMapper.insert(employee);
}

因此我們要通過JWT和ThreadLocal動態獲取當前登錄員工的ID,并實現數據的準確記錄。在使用 JWT(JSON Web Token)進行身份驗證時,通常需要在項目中引入相關的依賴庫,并在配置文件中設置 JWT 的參數。以下是如何在 Spring Boot 項目中引入 JWT 并進行配置的簡單說明:

1. 在pom.xml中引入JWT依賴

為了使用 JWT,我們需要引入一個 JWT 庫,比如 java-jwt(由 Auth0 提供)。

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version> <!-- 使用最新版本 -->
</dependency>

2. 在application.yaml中配置JWT參數

application.yaml 文件中定義 JWT 的相關配置,例如密鑰、過期時間和令牌名稱。

sky:jwt:# 設置 JWT 簽名加密時使用的秘鑰admin-secret-key: itcast# 設置 JWT 過期時間(單位:毫秒)admin-ttl: 7200000 # 2小時# 設置前端傳遞過來的令牌名稱admin-token-name: token
  • admin-secret-key:用于簽名和驗證 JWT 的密鑰。必須保密,且長度足夠復雜以確保安全性。
  • admin-ttl:JWT 的有效期(以毫秒為單位)。例如,7200000 表示 2 小時。
  • admin-token-name:前端傳遞 JWT 時使用的參數名稱。例如,前端可能會在請求頭或請求參數中傳遞 token=xxx

3. 使用JWT獲取當前登錄員工ID

員工登錄成功后,系統會生成JWT令牌并返回給前端。JWT中包含了當前登錄員工的ID信息。

/*** 員工管理*/
@RestController
@RequestMapping("/admin/employee")
@Api(tags = "員工相關接口")
@Slf4j
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@Autowiredprivate JwtProperties jwtProperties;/*** 登錄** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("員工登錄:{}", employeeLoginDTO);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);}...
}

4. 通過攔截器解析JWT

在每次請求時,前端會攜帶JWT令牌。通過攔截器解析JWT,獲取當前登錄員工的ID。

/*** jwt令牌校驗的攔截器*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校驗jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判斷當前攔截到的是Controller的方法還是其他資源if (!(handler instanceof HandlerMethod)) {//當前攔截到的不是動態方法,直接放行return true;}//1、從請求頭中獲取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校驗令牌try {log.info("jwt校驗:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("當前員工id:", empId);BaseContext.setCurrentId(empId);//3、通過,放行return true;} catch (Exception ex) {//4、不通過,響應401狀態碼response.setStatus(401);return false;}}
}

5. 使用ThreadLocal傳遞員工ID

通過ThreadLocal實現線程隔離,將當前登錄員工的ID傳遞給Service層。

public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}
}

6. 在Service中獲取員工ID

在Service層中,從ThreadLocal中獲取當前登錄員工的ID,并設置為創建人和修改人。

public void save(EmployeeDTO employeeDTO) {Employee employee = new Employee();employee.setCreateUser(BaseContext.getCurrentId()); // 動態獲取當前登錄員工IDemployee.setUpdateUser(BaseContext.getCurrentId()); // 動態獲取當前登錄員工IDemployeeMapper.insert(employee);
}

五、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 查詢員工信息

  • 前端只需要員工的基本信息(如 idusernamenamephonesexidNumber)。
  • 后端返回 EmployeeDTO,過濾掉敏感字段(如 password)和內部字段(如 createTime)。

3.2 更新員工信息

  • 前端傳遞 EmployeeDTO 作為請求體,后端根據 DTO 更新員工信息。
  • 避免前端傳遞不必要的字段(如 passwordcreateTime)。

3.3 新增員工

  • 前端傳遞 EmployeeDTO 作為請求體,后端將 DTO 轉換為實體類并保存到數據庫。
  • 避免前端傳遞內部字段(如 createTimeupdateTime)。

4. DTO、VO和實體類的區別

特性DTOVOEntity
目的數據傳輸數據展示或封裝值表示數據庫中的數據結構
使用場景跨層數據傳輸(如Controller-Service)展示層或領域模型數據庫操作、業務邏輯
可變性可變(通常有setter)通常不可變(無setter)可變(用于持久化和業務邏輯)
字段與傳輸需求相關與展示或業務邏輯相關與數據庫表字段嚴格對應
行為通常無行為可能包含簡單行為(如格式化)包含業務邏輯和驗證規則
示例UserDTOUserVOUserEntity

六、為什么使用 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 代碼。

七、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. 請求參數說明

在這里插入圖片描述

從接口文檔中可以看到,請求參數包括以下幾項:

參數名類型說明必需性示例值
categoryIdstring分類id可選101
namestring菜品名稱可選官保雞丁
pagestring頁碼必需1
pageSizestring每頁記錄數必需10
statusstring分類狀態可選1
  • 必需參數

    • pagepageSize 是分頁查詢的必需參數,用于指定查詢的頁碼和每頁的記錄數。
  • 可選參數

    • categoryIdnamestatus 是可選參數,用于過濾查詢結果。

1.1 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());
}
1.1.1 必需參數
  • dishPageQueryDTO.getPage()dishPageQueryDTO.getPageSize() 是分頁查詢的必需參數。
  • 如果這兩個參數為空或未提供,分頁功能將無法正常工作。

1.2 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>
1.2.1 可選參數
  • namecategoryIdstatus 是可選參數,通過 <if> 標簽動態生成查詢條件。
  • 如果某個參數為 null,則對應的條件不會添加到 SQL 查詢中。

通過這種設計,分頁查詢接口既滿足了基本的查詢需求,又提供了靈活的過濾選項,適用于不同的業務場景。


2. 返回響應說明

在 API 設計中,返回響應的數據結構通常需要遵循一定的規范,以確保客戶端能夠準確處理和理解服務器的響應。Result<T> 類是一個典型的統一響應格式,根據不同的設計需求,我們發現 code 一定是必需的,而 msgdata 在某些情況下是可選的,而在某些情況可能是必需的。接下來,我們將詳細探討這種設計背后的原因。

在這里插入圖片描述
在這里插入圖片描述

2.1 Java代碼分析

package com.sky.result;import lombok.Data;import java.io.Serializable;`/*** 后端統一返回結果* @param <T>*/
@Data
public class Result<T> implements Serializable {private Integer code; //編碼:1成功,0和其它數字為失敗private String msg; //錯誤信息private T data; //數據public static <T> Result<T> success() {Result<T> result = new Result<T>();result.code = 1;return result;}public static <T> Result<T> success(T object) {Result<T> result = new Result<T>();result.data = object;result.code = 1;return result;}public static <T> Result<T> error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}}
2.1.1 必需參數

code 是必需的

  • 作用code 用于表示請求的處理結果狀態,通常是一個數字。
    • 例如: 1 表示成功,0 或其他數字表示失敗。
  • 為什么必需
    • 明確狀態:客戶端需要知道請求是否成功。code 提供了一個明確的狀態標識,客戶端可以根據它決定后續操作。
    • 標準化:統一的 code 值可以讓客戶端以一致的方式處理所有 API 的響應。
    • 錯誤處理:當請求失敗時,code 可以幫助客戶端快速定位問題類型(如權限不足、資源不存在等)。
2.1.2 可選參數

msg 是可選的

  • 作用msg 用于提供額外的錯誤信息或成功提示。
    • 例如:成功時:msg 可以為空或包含提示信息(如“操作成功”),失敗時:msg 可以包含具體的錯誤描述(如“用戶未找到”)。
  • 為什么可選
    • 成功時可能不需要:在請求成功的情況下,客戶端可能只需要 data,而不需要額外的提示信息。
    • 減少冗余:如果 msg 是必需的,即使沒有實際意義的信息(如成功時的默認提示),也需要返回,這會增加響應的冗余。
    • 靈活性:在某些場景下,錯誤信息可能由其他方式提供(如日志或專門的錯誤處理機制),因此 msg 可以省略。

data 是可選的

  • 作用data 用于承載實際的響應數據。
    • 例如:查詢接口返回的列表或對象,創建接口返回的新創建的資源。
  • 為什么可選
    • 某些操作不需要返回數據:例如,刪除操作或簡單的狀態更新操作可能不需要返回任何數據。
    • 減少冗余:如果 data 是必需的,即使沒有數據也需要返回一個空對象或 null,這會增加響應的冗余。
    • 靈活性:某些接口可能只需要返回狀態信息(如 codemsg),而不需要額外的數據。

2.2 返回響應示例

2.2.1 成功響應(帶數據)
{"code": 1,"msg": "操作成功","data": {"id": 123,"name": "John Doe"}
}
2.2.2 成功響應(不帶數據)
{"code": 1
}
2.2.3 失敗響應
{"code": 0,"msg": "用戶未找到"
}

這種設計符合 API 設計的最佳實踐,能夠滿足大多數場景的需求,同時保持簡潔和一致性。


九、阿里云OSS配置指南

在使用對象存儲服務時,可能會遇到Bucket失效的情況,從而導致服務無法正常運行。為了解決這個問題,我們需要重新配置一個新的Bucket,并更新相關配置文件。參考教程:Java利用阿里云OSS/本地存儲實現文件上傳功能

1. 注冊阿里云OSS賬號

首先,訪問阿里云-對象存儲OSS官網注冊賬號。新用戶可免費試用20GB存儲空間,有效期為3個月。

在這里插入圖片描述

2. 獲取關鍵信息

注冊完成后,開通對象存儲服務OSS,創建第一個Bucket,并獲取以下四個關鍵信息:

  1. Endpoint:OSS服務的訪問地址。
  2. Access Key ID:用于身份驗證的訪問密鑰ID。
  3. Access Key Secret:用于身份驗證的訪問密鑰。
  4. Bucket Name:新創建的Bucket名稱。

在這里插入圖片描述

3. 更新配置文件

將上述獲取的信息填寫到對應的YAML配置文件sky-server/src/main/resources/application-dev.yml目錄下

sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: sky_take_outusername: your_usernamepassword: your_passwordalioss:endpoint: your_endpointaccess-key-id: your_accessKeyIdaccess-key-secret: your_keySecretbucket-name: your_bucketName#    endpoint: oss-cn-hangzhou.aliyuncs.com
#    access-key-id: LTAI5tPeFLzsPPT8gG3LPW64
#    access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7
#    bucket-name: sky-take-out

4, 重新運行服務

保存配置文件后,重新運行服務并打開前端頁面,發現圖片能夠正常上傳了!

在這里插入圖片描述
并且我們可以在自己的對象存儲OSS文件管理中監控到從前端頁面上傳的圖片文件

在這里插入圖片描述


十、SpringBoot配置類詳解

在 Spring Boot 項目中,配置文件是管理應用程序行為的關鍵部分。通過合理使用配置類,我們可以輕松實現多環境配置、自定義配置以及配置的動態注入。

1. 生產環境與開發環境配置

Spring Boot 支持多環境配置,通常我們會為不同環境(如開發、測試、生產)創建不同的配置文件。通過 spring.profiles.active 屬性,可以動態切換環境。

1.1 配置文件命名規則

  • 默認配置文件application.yaml(或 application.properties)。
  • 環境特定配置文件application-{profile}.yaml,其中 {profile} 是環境標識,如 devprod

1.2 激活環境配置

application.yaml 中,通過 spring.profiles.active 指定激活的環境:

spring:profiles:active: dev  # 激活開發環境
  • dev 的含義:表示加載 application-dev.yaml 文件。
  • prod 的含義:表示加載 application-prod.yaml 文件。

1.3 占位符替換

在配置文件中,可以使用 ${} 占位符引用其他配置項的值。Spring Boot 會在啟動時自動替換這些占位符。

示例
  • application.yaml

    spring:datasource:url: jdbc:mysql://${sky.datasource.host}:${sky.datasource.port}/${sky.datasource.database}
    
  • application-dev.yaml

    sky:datasource:host: localhostport: 3306database: devdb
    
  • 最終替換結果

    spring:datasource:url: jdbc:mysql://localhost:3306/devdb
    

2. Spring 前綴與自定義前綴配置

Spring Boot 的配置文件支持兩種類型的配置:Spring 內置配置自定義配置

2.1 Spring 內置配置

Spring Boot 使用 spring 作為內置配置的命名空間,用于配置框架本身的行為,例如:

  • 數據源配置spring.datasource
  • Redis 配置spring.redis
  • Profile 激活spring.profiles.active
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: rootredis:host: localhostport: 6379

2.2 自定義配置

自定義配置通常用于業務相關的配置項。我們可以使用自定義前綴(如 sky)來組織這些配置。

sky:jwt:admin-secret-key: itcastadmin-ttl: 7200000alioss:endpoint: oss-cn-shenzhen.aliyuncs.comaccess-key-id: LTAI5tRK6gZ9f6CyHCaWh7e8

3. 自定義配置類的注冊與使用

Spring Boot 提供了 @ConfigurationProperties 注解,用于將配置文件中的值綁定到 Java 對象中。

3.1 創建配置類

通過 @ConfigurationProperties 注解,指定配置的前綴,并定義與配置項對應的字段。

3.1.1 JWT 配置類
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {private String adminSecretKey;private long adminTtl;private String adminTokenName;
}
3.1.2 阿里云 OSS 配置類
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
}

3.2 使用配置類

在其他組件(如 Service、Controller)中,可以通過 @Autowired 注入配置類,直接使用配置值。

3.2.1 在 Service 中使用配置類
package com.sky.service;import com.sky.properties.AliOssProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OssService {@Autowiredprivate AliOssProperties aliOssProperties;public void printOssConfig() {System.out.println("Endpoint: " + aliOssProperties.getEndpoint());System.out.println("AccessKeyId: " + aliOssProperties.getAccessKeyId());}
}

3.3 配置類的注冊

  • @Component:將配置類注冊為 Spring 的 Bean。
  • @ConfigurationProperties:指定配置的前綴,并綁定配置項。

十一、SpringBoot注解匯總

1. Spring MVC 相關注解

  1. @RestController
    標記一個類為 RESTful 控制器,返回值直接作為響應體(通常是 JSON 格式),它結合了 @Controller@ResponseBody 的功能,適用于開發 RESTful API。

  2. @RequestMapping
    映射 HTTP 請求到控制器方法,可以指定請求路徑、請求方法(如 GET、POST)等。

  3. @PostMapping
    專門處理 HTTP POST 請求,是 @RequestMapping(method = RequestMethod.POST) 的簡寫。

  4. @GetMapping
    專門處理 HTTP GET 請求,是 @RequestMapping(method = RequestMethod.GET) 的簡寫。

  5. @DeleteMapping
    專門處理 HTTP DELETE 請求,是 @RequestMapping(method = RequestMethod.DELETE) 的簡寫。

  6. @PutMapping
    專門處理 HTTP PUT 請求,是 @RequestMapping(method = RequestMethod.PUT) 的簡寫。

  7. @RequestBody
    將 HTTP 請求體(通常是 JSON 格式)綁定到方法參數,適用于接收客戶端傳遞的復雜數據。

  8. @ResponseBody
    將方法的返回值直接作為 HTTP 響應體(通常是 JSON 格式),而不是跳轉到視圖頁面。

  9. @PathVariable
    將 URL 路徑中的變量綁定到方法參數,適用于 RESTful 風格的 URL。

2. Swagger 相關注解

  1. @Api
    標記一個類為 Swagger 資源,用于生成 API 文檔。

  2. @ApiModel
    描述 Swagger 模型類,通常用于實體類,生成文檔中的模型信息。

  3. @ApiModelProperty
    描述 Swagger 模型類的屬性,用于生成文檔中屬性的詳細信息。

  4. @ApiOperation
    描述 API 接口的操作,用于生成文檔中接口的詳細信息。

3. Spring 核心注解

  1. @Autowired
    自動注入 Spring Bean,用于依賴注入。

  2. @Bean
    聲明一個方法返回的對象為 Spring Bean,通常用于配置類中。

  3. @Configuration
    標記一個類為配置類,用于定義 Bean 或其他配置。

  4. @Service
    標記一個類為服務層組件,通常用于業務邏輯層。

  5. @Component
    標記一個類為 Spring 組件,泛指任何 Spring 管理的 Bean。

  6. @SpringBootApplication
    標記主啟動類,包含 @Configuration@EnableAutoConfiguration@ComponentScan,用于啟動 Spring Boot 應用。

  7. @EnableTransactionManagement
    啟用 Spring 的事務管理,通常用于配置類中。

4. AOP 相關注解

  1. @Aspect
    標記一個類為切面,用于定義橫切關注點(如日志、事務)。

  2. @Before
    在目標方法執行前執行切面邏輯。

  3. @Pointcut
    定義切點表達式,用于指定哪些方法需要被切面處理。

5. Lombok 相關注解

  1. @Slf4j
    自動生成日志對象 log,簡化日志記錄代碼。

  2. @Data
    自動生成 gettersettertoStringequalshashCode 等方法。

  3. @Builder
    為類生成 Builder 模式支持,簡化對象的創建。

  4. @NoArgsConstructor
    生成無參構造方法。

  5. @AllArgsConstructor
    生成全參構造方法。

6. MyBatis 相關注解

  1. @Mapper
    標記一個接口為 MyBatis 的 Mapper 接口,用于定義數據庫操作。

  2. @Delete
    映射 SQL 刪除操作。

  3. @Select
    映射 SQL 查詢操作。

  4. @Insert
    映射 SQL 插入操作。

  5. @AutoFill
    自定義注解,用于自動填充字段(如創建時間、更新時間)。

7. 配置相關注解

  1. @ConfigurationProperties
    將配置文件中的值綁定到 Java 對象中,通常用于加載自定義配置,其中 prefix:指定配置項的前綴,從配置文件中加載特定部分的配置。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/72032.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72032.shtml
英文地址,請注明出處:http://en.pswp.cn/web/72032.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大模型安全新范式:DeepSeek一體機內容安全衛士發布

2月以來&#xff0c;DeepSeek一體機幾乎成為了政企市場AI消費的最強熱點。 通過一體機的方式能夠縮短大模型部署周期&#xff0c;深度結合業務場景&#xff0c;降低中小企業對于大模型的使用門檻。據不完全統計&#xff0c;已約有超過60家企業基于DeepSeek推出一體機產品。 但…

OpenHarmony-SELinux配置

前言&#xff1a; OpenHarmony 上某個進程向samgr注冊SA服務&#xff0c;其他進程在與該進程進行IPC通信之前&#xff0c;需要獲取該SA服務&#xff0c;SA提供方需要為該SA配置SELinux標簽&#xff0c;否則該SA會被SELinux配置為u:object_r:default_service:s0標簽&#xff0c…

SQL開發中改善查詢性能的N種寫法

文章目錄 1. 使用 SELECT *2. 在 WHERE 子句中使用函數或計算3. 使用隱式類型轉換4. 不使用索引的列進行連接&#xff08;JOIN&#xff09;或過濾5. 使用 OR 代替 IN6. 在子查詢中使用 SELECT *7. 忽略索引統計信息8. 嵌套子查詢過多9. 過度使用 DISTINCT10. 使用不當的 JOIN 類…

第十八:go 并發 goroutine

channel 可以讓多個goroutine 之間實現通信 Add方法調用時機&#xff1a;必須在goroutine 啟動之前調用Add方法來增加計數器的值。 如果在goroutine已經啟動之后再調用Add&#xff0c;可能會導致Wait方法提前返回&#xff0c;因為計數器沒有正確反映正在運行的goroutine的數量…

數字IC后端項目典型問題(2025.03.10數字后端項目問題記錄)

小編發現今天廣大學員發過來的問題都比較好&#xff0c;立即一頓輸出分享給大家&#xff08;每天都有好多種類的數字后端問題&#xff09;。后續可能會經常通過這種方式來做分享。其實很多問題都是實際后端項目中經常遇到的典型問題。希望通過這種方式的分享能夠幫助到更多需要…

課程《Deep Learning Specialization》

在coursera上&#xff0c;Deep Learning Specialization 課程內容如下圖所示&#xff1a; Week2 assignment, Logistic Regression.

LLM推理和優化(1):基本概念介紹

一、LLM推理的核心過程&#xff1a;自回歸生成 LLM&#xff08;如DeepSeek、ChatGPT、LLaMA系列等&#xff09;的推理本質是自回歸生成&#xff1a;從初始輸入&#xff08;如[CLS]或用戶prompt&#xff09;開始&#xff0c;逐token預測下一個詞&#xff0c;直到生成結束符&…

【從零開始學習計算機科學】編譯原理(一)編譯過程概述

【從零開始學習計算機科學】編譯原理(一)編譯過程概述 緒論編譯過程概述詞法分析語法分析代碼優化代碼生成其他功能編譯器的前端和后端緒論 什么叫編譯程序?為什么我們需要編譯程序?編譯程序就是一個程序,將便于人編寫、閱讀、維護的高級計算機語言所寫作的源代碼程序,翻…

3-001:MySQL 中的回表是什么?

1. 什么是回表&#xff1f; 回表&#xff08;Back to Table&#xff09; 指的是 在使用非聚簇索引&#xff08;輔助索引&#xff09;查詢時&#xff0c;MySQL 需要 先通過索引找到主鍵 ID&#xff0c;然后再回到主鍵索引&#xff08;聚簇索引&#xff09;查詢完整數據&#xf…

【AIGC】計算機視覺-YOLO系列家族

YOLO系列家族 &#xff08;1&#xff09;YOLO發展史&#xff08;2&#xff09; YOLOX&#xff08;3&#xff09; YOLOv6&#xff08;4&#xff09; YOLOv7&#xff08;5&#xff09; YOLOv8&#xff08;6&#xff09; YOLOv9&#xff08;7&#xff09;YOLOv10&#xff08;8&…

基于Python懂車帝汽車數據分析平臺(源碼+lw+部署文檔+講解),源碼可白嫖!

摘要 時代在飛速進步&#xff0c;每個行業都在努力發展現在先進技術&#xff0c;通過這些先進的技術來提高自己的水平和優勢&#xff0c;汽車數據分析平臺當然不能排除在外。本次我所開發的懂車帝汽車數據分析平臺是在實際應用和軟件工程的開發原理之上&#xff0c;運用Python…

Prompt 工程

一、提示原則 import openai import os import openai from dotenv import load_dotenv, find_dotenv from openai import OpenAI def get_openai_key():_ load_dotenv(find_dotenv())return os.environ[OPENAI_API_KEY]client OpenAI(api_keyget_openai_key(), # This is …

MySQL -- 數據庫基礎

1、基礎登錄操作 mysql 指定選項 選項&#xff1a; <1> -h 指定ip地址&#xff0c;即連接的主機&#xff0c;不帶時&#xff0c;默認連本機 <2> -P 指定的端口號&#xff0c;指定默認端口號&#xff08;配置文件中進行配置&#xff09; <3>-u 指定的用戶 &l…

02C#基本結構篇(D3_內部類-代碼塊-數據類型-變量-常量-字面量-運算符-流程控制語句)

目錄 一、內部類 1. 定義內部類 2. 創建內部類的實例 3. 訪問外部類的私有成員 4. 內部靜態類 5. 使用場景和優點 6. 注意事項 ------------------------------------------- 二、代碼塊 1. 控制流語句 1.1. 條件語句 1> if 語句 2> switch 語句 1.2. 循環語…

15 | 定義簡潔架構 Store 層的數據類型

提示&#xff1a; 所有體系課見專欄&#xff1a;Go 項目開發極速入門實戰課&#xff1b;歡迎加入 云原生 AI 實戰 星球&#xff0c;12 高質量體系課、20 高質量實戰項目助你在 AI 時代建立技術競爭力&#xff08;聚焦于 Go、云原生、AI Infra&#xff09;&#xff1b;本節課最終…

CSDN統計個人創作總字數

前言 不是很懂爬蟲&#xff0c;所以就叫deepseek寫了一個 用起來很簡單&#xff0c;但是有一個小問題&#xff0c;就是統計的是總字符數。代碼片會被統計進去&#xff0c;Markdown語法也會被統計進去。 不過我沒有太多需求&#xff0c;能大概統計一下滿足以下小小的好奇心和成…

React.js 基礎與進階教程

React.js 基礎與進階教程 React.js 是由 Facebook 開發的流行前端 JavaScript 庫&#xff0c;專為構建用戶界面&#xff08;UI&#xff09;設計&#xff0c;尤其適用于單頁面應用&#xff08;SPA&#xff09;。它采用組件化開發模式&#xff0c;使 UI 結構更加清晰、可維護性更…

msf(Metasploit)中Session與Channel的區別與關系解析

在 Metasploit Framework&#xff08;MSF&#xff09;中&#xff0c;Session 和 Channel 都是與目標主機的交互方式&#xff0c;但它們的作用和概念有所不同。本文將解析這兩個術語的區別。 一、Session&#xff08;會話&#xff09; Session 是指通過 Metasploit 成功利用目標…

設計模式-結構型模式-裝飾器模式

概述 裝飾器模式 : Decorator Pattern : 是一種結構型設計模式. 作用 &#xff1a; 允許你動態地給對象添加功能或職責&#xff0c;而無需修改其原始類的代碼,非常的符合 開閉原則。 實現思路 &#xff1a;通過創建一個包裝對象&#xff08;即裝飾器&#xff09;&#xff0c;來…

Qt/C++音視頻開發82-系統音量值獲取和設置/音量大小/靜音

一、前言 在音視頻開發中&#xff0c;音量的控制分兩塊&#xff0c;一個是控制播放器本身的音量&#xff0c;絕大部分場景都是需要控制這個&#xff0c;這個不會影響系統音量的設置。還有一種場景是需要控制系統的音量&#xff0c;因為播放器本身的音量是在系統音量的基礎上控…