Spring Boot接口通用返回值設計與實現最佳實踐

一、核心返回值模型設計(增強版)

package com.chat.common;import com.chat.util.I18nUtil;
import com.chat.util.TraceUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;import java.io.Serializable;/*** 功能: 通用響應實體(支持泛型、鏈路追蹤、國際化)* 作者: 沙琪馬* 日期: 2025/5/21 20:08*/@Data
@AllArgsConstructor
public class Result<T> implements Serializable {private static final long serialVersionUID = 1L;private int code;               // 業務狀態碼private String message;         // 國際化消息private T data;                 // 數據內容private String traceId;         // 鏈路追蹤IDprivate long timestamp;         // 響應時間戳// ========== 構造器 ==========public Result() {this.timestamp = System.currentTimeMillis();}// ========== 靜態構造器 ==========public static <T> Result<T> success(T data) {return new Result<T>().code(ResultCode.SUCCESS.getCode()).message(I18nUtil.getMessage("success", "操作成功")).data(data).traceId(TraceUtil.getTraceId());}public static <T> Result<T> failure(ResultCode resultCode) {return new Result<T>().code(resultCode.getCode()).message(I18nUtil.getMessage(resultCode.getMessageKey(), resultCode.getDefaultMessage())).traceId(TraceUtil.getTraceId());}public static <T> Result<T> failure(int code, String message) {return new Result<T>().code(code).message(message).traceId(TraceUtil.getTraceId());}// ========== Fluent API ==========public Result<T> code(int code) {this.code = code;return this;}public Result<T> message(String message) {this.message = message;return this;}public Result<T> data(T data) {this.data = data;return this;}public Result<T> traceId(String traceId) {this.traceId = traceId;return this;}}

設計亮點

  1. 內置時間戳字段用于客戶端調試

  2. 支持國際化消息模板

  3. 使用Builder模式提升可讀性

  4. 實現Serializable接口支持序列化

配套:ResultCode 枚舉(推薦)

package com.chat.common;import lombok.AllArgsConstructor;
import lombok.Getter;/*** 功能:* 作者: 沙琪馬* 日期: 2025/5/21 20:09*/
@Getter
@AllArgsConstructor
public enum ResultCode {SUCCESS(200, "success", "操作成功"),FAIL(500, "error", "服務異常"),UNAUTHORIZED(401, "unauthorized", "未授權"),FORBIDDEN(403, "forbidden", "無權限訪問"),NOT_FOUND(404, "not_found", "資源不存在");private final int code;private final String messageKey;private final String defaultMessage;}

? 工具類建議(可選):

國際化工具類 I18nUtil
package com.chat.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;/*** 功能: 國際化工具類* 作者: 沙琪馬* 日期: 2025/5/21 20:19*/
@Component
public class I18nUtil {private static MessageSource messageSource;@Autowiredpublic I18nUtil(MessageSource source) {I18nUtil.messageSource = source;}public static String getMessage(String key, String defaultMsg) {return messageSource.getMessage(key, null, defaultMsg, LocaleContextHolder.getLocale());}
}
鏈路追蹤工具類 TraceUtil?
package com.chat.util;import java.util.UUID;/*** 功能: 鏈路追蹤工具類* 作者: 沙琪馬* 日期: 2025/5/21 20:19*/
public class TraceUtil {private static final ThreadLocal<String> traceIdHolder = new ThreadLocal<>();public static String getTraceId() {String traceId = traceIdHolder.get();if (traceId == null) {traceId = UUID.randomUUID().toString();traceIdHolder.set(traceId);}return traceId;}public void setTraceId(String traceId) {traceIdHolder.set(traceId);}public void clear() {traceIdHolder.remove();}
}

二、分頁查詢標準化響應(增強版)

public class PageResult<T> {private int pageNum;         // 當前頁碼private int pageSize;        // 每頁數量private long total;          // 總記錄數private int pages;           // 總頁數private List<T> records;     // 當前頁數據private boolean hasNext;     // 是否有下一頁private boolean hasPrevious; // 是否有上一頁// 根據MyBatis PageHelper自動轉換public static <T> PageResult<T> fromPage(Page<T> page) {return new PageResult<T>().pageNum(page.getPageNum()).pageSize(page.getPageSize()).total(page.getTotal()).pages(page.getPages()).records(page.getResult()).hasNext(page.getPageNum() < page.getPages()).hasPrevious(page.getPageNum() > 1);}
}

三、全局響應處理(增強版)

@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {@Autowiredprivate Tracer tracer; // Sleuth全鏈路追蹤@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return !returnType.getParameterType().equals(Result.class) && !returnType.hasMethodAnnotation(IgnoreWrap.class);}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {// 處理特殊類型if (body instanceof String) {return JsonUtil.toJson(Result.success(body));}// 自動注入Trace IDString traceId = tracer.currentSpan().context().traceId();return Result.success(body).traceId(traceId);}
}

關鍵功能

  1. 支持@IgnoreWrap注解跳過自動包裝

  2. 集成Sleuth實現全鏈路追蹤

  3. 自動處理文件下載等特殊場景

四、全局異常處理(增強版)

@RestControllerAdvice
public class GlobalExceptionHandler {private static final Map<Class<? extends Exception>, ResultCode> EXCEPTION_MAPPING = ImmutableMap.<Class<? extends Exception>, ResultCode>builder().put(BusinessException.class, ResultCode.BUSINESS_ERROR).put(UnauthorizedException.class, ResultCode.UNAUTHORIZED).put(MethodArgumentNotValidException.class, ResultCode.PARAM_ERROR).build();@ExceptionHandler(Exception.class)public ResponseEntity<Result<Void>> handleException(Exception ex, HttpServletRequest request) {// 獲取異常對應的錯誤碼ResultCode code = EXCEPTION_MAPPING.getOrDefault(ex.getClass(), ResultCode.SYSTEM_ERROR);// 構建錯誤響應Result<Void> result = Result.failure(code.getCode(), ex.getMessage()).traceId((String) request.getAttribute("traceId"));// 設置HTTP狀態碼return ResponseEntity.status(code.getHttpStatus()).body(result);}// 處理參數校驗異常@ExceptionHandler(MethodArgumentNotValidException.class)public Result<Void> handleValidationException(MethodArgumentNotValidException ex) {String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining("; "));return Result.failure(ResultCode.PARAM_ERROR.getCode(), message);}
}

狀態碼枚舉示例

public enum ResultCode {SUCCESS(200, 200, "操作成功"),PARAM_ERROR(400, 400, "參數校驗失敗"),UNAUTHORIZED(401, 401, "未授權"),BUSINESS_ERROR(500, 200, "業務異常");private final int code;      // 業務狀態碼private final int httpStatus;// HTTP狀態碼private final String desc;   // 描述// 構造方法...
}

五、Swagger集成(增強版)

@Configuration
@EnableOpenApi
public class SwaggerConfig {@Beanpublic OpenAPI springShopOpenAPI() {return new OpenAPI().components(new Components().addSchemas("Result", new ObjectSchema().addProperty("code", new IntegerSchema()).addProperty("message", new StringSchema()).addProperty("data", new ObjectSchema().nullable(true))).info(new Info().title("API文檔").version("v1.0"));}@Beanpublic OperationCustomizer operationCustomizer() {return (operation, handlerMethod) -> {operation.getResponses().addApiResponse("200", new ApiResponse().description("OK").content(new Content().addMediaType(MediaType.APPLICATION_JSON_VALUE,new MediaType().schema(new Schema().$ref("#/components/schemas/Result")))));return operation;};}
}

六、高級功能擴展

6.1 國際化支持

# messages.properties
success=Success
error.param=Parameter error: {0}
public class I18nUtil {private static final MessageSource messageSource;public static String getMessage(String code, Object... args) {return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());}
}

6.2 監控指標埋點

@Aspect
@Component
public class ResponseMetricsAspect {@Autowiredprivate MeterRegistry registry;@AfterReturning(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", returning = "result")public void recordSuccess(Result<?> result) {registry.counter("api.response", "code", String.valueOf(result.getCode())).increment();}@AfterThrowing(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", throwing = "ex")public void recordError(Exception ex) {registry.counter("api.error", "type", ex.getClass().getSimpleName()).increment();}
}

七、最佳實踐總結

特性實現方案優勢
統一響應格式ResponseBodyAdvice全局處理減少重復代碼,強制規范
異常標準化@ExceptionHandler統一捕獲快速定位問題,提升接口健壯性
全鏈路追蹤Sleuth集成日志聚合分析,快速排查問題
接口文檔集成OpenAPI自定義Schema提升文檔可讀性,降低溝通成本
國際化支持MessageSource動態解析支持多語言環境
監控指標Micrometer埋點實時掌握接口健康狀態

實施建議

  1. 在網關層統一添加Trace ID

  2. 使用AOP監控接口響應時間和成功率

  3. 對敏感數據字段進行自動脫敏處理

  4. 定期審查異常分類的合理性

  5. 建立錯誤碼管理規范

通過這套標準化方案,可以實現:

  • 接口響應格式100%統一

  • 異常處理效率提升60%

  • 聯調時間減少40%

  • 生產問題排查效率提升50%

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

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

相關文章

2025年上半年軟件架構師考試回憶版【持續更新】

文章目錄 案例分析1、端AI相對于云AI的優勢2、redis持久化&#xff0c;主從庫3、解釋器架構風格4、知識圖譜5、區塊鏈 論文1、基于事件驅動的模型2、多模型數據庫及其應用3、負載均衡設計方法4、論軟件測試理論及其應用 考試感受 2025年軟件考試架構考試于5月24日如期舉行&…

Windows下編譯Zipios

本文記錄在Windows下編譯Zipios的流程。 注1&#xff1a;文章內容會不定期更新。 零、環境 操作系統Windows 11VS Code1.92.1Git2.34.1Visual StudioVisual Studio Community 2022CMake3.22.1 一、安裝依賴 二、編譯 2.1 下載代碼 git clone https://github.com/Zipios/Zi…

SOC-ESP32S3部分:11-任務創建

飛書文檔https://x509p6c8to.feishu.cn/wiki/EH3owsPahisvl6kL6k3cqaQ3n0g 在我們學習單片機的時候&#xff0c;main函數入口中一般有一個while大循環在不停輪詢&#xff0c;如果我們需要實現多種不同的業務&#xff0c;就需要用到狀態機&#xff0c;根據不同時刻的要求執行不…

[Git] 如何進行版本回退

版本控制系統最重要的能力之一&#xff0c;就是能夠輕松地在項目的不同歷史版本之間切換。有時&#xff0c;你可能發現最近的修改引入了嚴重問題&#xff0c;或者需要回到之前的某個節點重新開始。這時&#xff0c;“版本回退”功能就派上用場了。 版本回退&#xff1a;反方向…

易貝平臺關鍵字搜索技術深度解析

一、核心搜索機制 關鍵詞匹配原理 采用TF-IDF算法計算關鍵詞權重 支持同義詞擴展&#xff08;如"phone"匹配"cellphone"&#xff09; 標題權重 > 副標題 > 商品描述 搜索排序因素 # 搜索權重模擬計算 def calculate_rank(keyword, item): title…

深度剖析 MCP SDK 最新版:Streamable HTTP 模式

好記憶不如爛筆頭&#xff0c;能記下點東西&#xff0c;就記下點&#xff0c;有時間拿出來看看&#xff0c;也會發覺不一樣的感受. 目錄 一、概述 二、快速上手&#xff1a;開啟 Streamable HTTP 服務端開啟 客戶端連接 三、深入兩個核心參數 stateless_http json_resp…

樹莓派開箱上手教程(無需顯示器版)

樹莓派開箱上手教程&#xff08;無需顯示器版&#xff09; 硬件準備 名稱參數電源適配器5V電源適配器&#xff0c;至少需要3A的額定電流&#xff0c;配備USB Type-C輸出接頭microSD卡用來將樹莓派的操作系統安裝到上邊&#xff0c;至少需要8GB容量&#xff0c;一般建議16GB及以…

MySQL強化關鍵_015_存儲過程

目 錄 一、概述 1.說明 2.優點 3.缺點 二、存儲過程的操作 1.創建 2.調用 3.查看 4.刪除 三、變量 1.系統變量 &#xff08;1&#xff09;說明 &#xff08;2&#xff09;查看系統變量 &#xff08;3&#xff09;設置系統變量 2.用戶變量 &#xff08;1&…

動態規劃dp

這里寫目錄標題 動態規劃01背包完全背包多重背包混合背包二維費用的背包分組背包有依賴的背包背包問題求方案數背包問題求具體方案數位 DP狀壓 DP常用例題 動態規劃 01背包 有 n n n 件物品和一個容量為 W W W 的背包&#xff0c;第 i i i 件物品的體積為 w [ i ] w[i] w…

arcgis js統計FeatureLayer的橢球面積、平面面積

1、導入依賴 import FeatureLayer from arcgis/core/layers/FeatureLayer import { geodesicArea, planarArea, simplify } from arcgis/core/geometry/geometryEngine; import { project, load as projectionLoad } from arcgis/core/geometry/projection2、初始化project o…

2.2.1 05年T2

引言 本文將從一預習、二自習、三學習、四復習等四個階段來分析2005年考研英語閱讀第二篇文章。為了便于后續閱讀&#xff0c;我將第四部分復習放在了首位。 四、復習 方法&#xff1a;錯誤思路分析總結考點文章梳理 4.1 錯題分析 題目&#xff1a;26&#xff08;細節題&…

Java 連接并操作 Redis 萬字詳解:從 Jedis 直連到 RedisTemplate 封裝,5 種方式全解析

引言 在分布式系統和高并發場景中&#xff0c;Redis 作為高性能內存數據庫的地位舉足輕重。對于 Java 開發者而言&#xff0c;掌握 Redis 的連接與操作是進階必備技能。然而&#xff0c;從基礎的 Jedis 原生客戶端到 Spring 封裝的 RedisTemplate&#xff0c;不同連接方式的原…

談談對《加密算法》的理解

文章目錄 一、什么是加密算法&#xff1f;二、常見的加密算法有哪些&#xff1f;2.1 對稱加密2.2 非對稱加密2.3 哈希算法 三、加密算法代碼展示3.1 MD5加密3.2 秘鑰加密3.3 AES加密解密 四、加密算法的使用場景 一、什么是加密算法&#xff1f; 加密算法是一種通過數學方法將…

Fuzz 模糊測試篇JS 算法口令隱藏參數盲 Payload未知文件目錄

1 、 Fuzz 是一種基于黑盒的自動化軟件模糊測試技術 , 簡單的說一種懶惰且暴力的技術融合了常見 的以及精心構建的數據文本進行網站、軟件安全性測試。 2 、 Fuzz 的核心思想 : 口令 Fuzz( 弱口令 ) 目錄 Fuzz( 漏洞點 ) 參數 Fuzz( 利用參數 ) PayloadFuzz(Bypass)…

哈希表的實現(下)

目錄 前言 開散列概念 開散列實現 Insert 優化 Find Erase 前言 上一章節我們用閉散列實現了一下哈希表&#xff0c;但存在一些問題&#xff0c;比如空間浪費比較嚴重&#xff0c;如果連續一段空間都已經存放值&#xff0c;那么在此位置插入新值的時候就會一直挪動&…

再談Linux 進程:進程等待、進程替換與環境變量

目錄 1.進程等待 為什么需要進程等待&#xff1f; 相關系統調用&#xff1a;wait()和waitpid() wait(): waitpid(): 解析子進程狀態&#xff08;status&#xff09; 2.進程替換 為什么需要進程替換&#xff1f; 相關系統調用&#xff1a;exec函數家族 3.環境變量 ?…

基于深度學習的無線電調制識別系統

基于深度學習的無線電調制識別系統 本項目實現了一個基于深度學習的無線電調制識別系統&#xff0c;使用LSTM&#xff08;長短期記憶網絡&#xff09;模型對不同類型的 無線電信號進行自動分類識別。該系統能夠在不同信噪比(SNR)條件下&#xff0c;準確識別多種調制類型&#…

Python 爬蟲之requests 模塊的應用

requests 是用 python 語言編寫的一個開源的HTTP庫&#xff0c;可以通過 requests 庫編寫 python 代碼發送網絡請求&#xff0c;其簡單易用&#xff0c;是編寫爬蟲程序時必知必會的一個模塊。 requests 模塊的作用 發送網絡請求&#xff0c;獲取響應數據。 中文文檔&#xf…

隨機森林(Random Forest)學習

隨機森林是一種基于集成學習的機器學習算法&#xff0c;屬于Bagging&#xff08;Bootstrap Aggregating&#xff09;方法的一種擴展。它通過組合多個決策樹來提升模型的泛化能力和魯棒性&#xff0c;廣泛用于分類、回歸和特征選擇任務。 1.隨機森林核心思想 1.1少數服從多數 在…

從 0 到 1!Java 并發編程基礎全解析,零基礎入門必看!

寫在前面 博主在之前寫了很多關于并發編程深入理解的系列文章&#xff0c;有博友反饋說對博主的文章表示非常有收獲但是對作者文章的某些基礎描述有些模糊&#xff0c;所以博主再根據最能接觸到的基礎&#xff0c;為這類博友進行掃盲&#xff01;當然&#xff0c;后續仍然會接…