Class StandardRestExceptionHandler
java.lang.Object
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
io.leandev.appfuse.error.StandardRestExceptionHandler
- All Implemented Interfaces:
org.springframework.beans.factory.Aware, org.springframework.context.MessageSourceAware
public abstract class StandardRestExceptionHandler
extends org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
標準 REST API 異常處理器基類 (RFC 7807)
提供統一的異常處理實作,將所有異常轉換為 RFC 7807 ProblemDetail 格式。 應用層可直接使用或繼承擴展。
繼承 ResponseEntityExceptionHandler 以處理 Spring 框架內建異常。
RFC 7807 錯誤回應格式
{
"type": "urn:appfuse:error:not-found",
"title": "Not Found",
"status": 404,
"detail": "The requested resource does not exist",
"instance": "/api/users/123",
"violations": [...], // 僅在驗證錯誤時包含
"format": "...", // 用於國際化
"params": [...] // 訊息參數
}
使用方式
方式 1:直接使用(推薦用於簡單應用)
@ControllerAdvice
public class GlobalRestExceptionHandler extends StandardRestExceptionHandler {
}
方式 2:註冊自定義 Mapper(推薦用於需要自定義異常處理的應用)
@ControllerAdvice
public class GlobalRestExceptionHandler extends StandardRestExceptionHandler {
static {
getRegistry().register(new CustomBusinessExceptionMapper());
}
}
- See Also:
-
Field Summary
Fields inherited from class org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
logger, PAGE_NOT_FOUND_LOG_CATEGORY, pageNotFoundLogger -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedprotectedStandardRestExceptionHandler(ErrorDisclosurePolicy disclosurePolicy) -
Method Summary
Modifier and TypeMethodDescriptionprotected StringextractPath(org.springframework.web.context.request.WebRequest request) 從 WebRequest 提取請求路徑protected StringformatViolations(org.springframework.http.ProblemDetail problem) 將 ProblemDetail 的 violations 渲染成可讀字串,附加於日誌訊息之後protected static ExceptionMappingRegistry取得異常映射註冊中心 子類別可透過此方法註冊自定義 Mapperprotected org.springframework.http.ResponseEntity<Object> handleAccessDenied(org.springframework.security.access.AccessDeniedException ex, org.springframework.web.context.request.WebRequest request) 處理授權拒絕(已認證但權限不足)→ 403 Source: Spring Security 方法層授權(@PreAuthorize等),其拋出的AuthorizationDeniedException為AccessDeniedException子型別。這類拒絕在 控制器調用期間拋出、先經 MVC 例外解析,若不在此明確映射會落入兜底 handler 被誤判為 500。 此處映為 RFC 7807 的 403 Forbidden。 註:URL 層授權拒絕(authorizeHttpRequests)由 Spring Security filter 的AccessDeniedHandler處理、不經此處(亦會帶 RFC 6750WWW-Authenticate挑戰標頭)。protected org.springframework.http.ResponseEntity<Object> handleApplicationException(ApplicationException ex, org.springframework.web.context.request.WebRequest request) 處理應用程式自定義異常 Source: AppFuse - 業務邏輯層拋出的語義化異常 Includes: NotFoundException, ConflictException, DuplicateException, etc.protected org.springframework.http.ResponseEntity<Object> handleAuthenticationException(org.springframework.security.core.AuthenticationException ex, org.springframework.web.context.request.WebRequest request) 處理認證失敗並保留實際 Spring Security 例外至揭露政策邊界。protected org.springframework.http.ResponseEntity<Object> handleCacheUnavailable(CacheUnavailableException ex, org.springframework.web.context.request.WebRequest request) 必要的一次性 cache state store 不可用時回 503,不誤映射成無效憑證或 500。protected org.springframework.http.ResponseEntity<Object> handleFrameworkException(Exception ex, org.springframework.web.context.request.WebRequest request) 統一處理 Spring 和 Jakarta 框架異常 Sources:protected org.springframework.http.ResponseEntity<Object> handleHttpClientException(HttpClientException ex, org.springframework.web.context.request.WebRequest request) 處理 AppFuse HTTP 客戶端異常 Source: AppFuse HTTP Client - HTTP 客戶端呼叫異常protected org.springframework.http.ResponseEntity<Object> handleJwtException(io.jsonwebtoken.JwtException ex, org.springframework.web.context.request.WebRequest request) JWT 驗證錯誤保留原始 parser 診斷;最小政策仍可收斂為 access token 無效。protected org.springframework.http.ResponseEntity<Object> handleMethodArgumentNotValid(org.springframework.web.bind.MethodArgumentNotValidException ex, org.springframework.http.HttpHeaders headers, org.springframework.http.HttpStatusCode status, org.springframework.web.context.request.WebRequest request) 處理 @Valid 或 @Validated 驗證失敗 Source: Spring Validation - 當請求體驗證失敗時拋出protected org.springframework.http.ResponseEntity<Object> handleMissingPathVariable(org.springframework.web.bind.MissingPathVariableException ex, org.springframework.http.HttpHeaders headers, org.springframework.http.HttpStatusCode status, org.springframework.web.context.request.WebRequest request) 處理路徑變數缺失 Source: Spring Web - 當 @PathVariable 對應的路徑變數缺失時拋出protected org.springframework.http.ResponseEntity<Object> handleMissingServletRequestParameter(org.springframework.web.bind.MissingServletRequestParameterException ex, org.springframework.http.HttpHeaders headers, org.springframework.http.HttpStatusCode status, org.springframework.web.context.request.WebRequest request) 處理缺少必要的請求參數 Source: Spring Web - 當 @RequestParam(required=true) 缺失時拋出protected org.springframework.http.ResponseEntity<Object> handleOtherException(Exception ex, org.springframework.web.context.request.WebRequest request) 處理所有未捕獲的異常 (兜底處理) Source: 任何未被上述 handler 處理的異常protected org.springframework.http.ResponseEntity<Object> handleProblemDetail(org.springframework.http.ProblemDetail problem, Throwable cause, org.springframework.web.context.request.WebRequest request) 統一處理 ProblemDetail 並返回 RFC 7807 格式的 JSON 回應protected org.springframework.http.ResponseEntity<Object> handleProblemDetail(org.springframework.http.ProblemDetail detailed, org.springframework.http.ProblemDetail minimal, Throwable cause, org.springframework.web.context.request.WebRequest request) 在所有 mapper 完成後才套用揭露政策,避免上游過早丟棄診斷。protected org.springframework.http.ProblemDetail將下游 HTTP 回應錯誤映射成對外 ProblemDetail。Methods inherited from class org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
createProblemDetail, createResponseEntity, getMessageSource, handleAsyncRequestNotUsableException, handleAsyncRequestTimeoutException, handleConversionNotSupported, handleErrorResponseException, handleException, handleExceptionInternal, handleHandlerMethodValidationException, handleHttpMediaTypeNotAcceptable, handleHttpMediaTypeNotSupported, handleHttpMessageNotReadable, handleHttpMessageNotWritable, handleHttpRequestMethodNotSupported, handleMaxUploadSizeExceededException, handleMethodValidationException, handleMissingServletRequestPart, handleNoHandlerFoundException, handleNoResourceFoundException, handleServletRequestBindingException, handleTypeMismatch, setMessageSource
-
Constructor Details
-
StandardRestExceptionHandler
protected StandardRestExceptionHandler() -
StandardRestExceptionHandler
-
-
Method Details
-
getRegistry
取得異常映射註冊中心 子類別可透過此方法註冊自定義 Mapper- Returns:
- ExceptionMappingRegistry
-
handleMissingServletRequestParameter
protected org.springframework.http.ResponseEntity<Object> handleMissingServletRequestParameter(@NonNull org.springframework.web.bind.MissingServletRequestParameterException ex, @NonNull org.springframework.http.HttpHeaders headers, @NonNull org.springframework.http.HttpStatusCode status, @NonNull org.springframework.web.context.request.WebRequest request) 處理缺少必要的請求參數 Source: Spring Web - 當 @RequestParam(required=true) 缺失時拋出- Overrides:
handleMissingServletRequestParameterin classorg.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
-
handleMissingPathVariable
protected org.springframework.http.ResponseEntity<Object> handleMissingPathVariable(@NonNull org.springframework.web.bind.MissingPathVariableException ex, @NonNull org.springframework.http.HttpHeaders headers, @NonNull org.springframework.http.HttpStatusCode status, @NonNull org.springframework.web.context.request.WebRequest request) 處理路徑變數缺失 Source: Spring Web - 當 @PathVariable 對應的路徑變數缺失時拋出- Overrides:
handleMissingPathVariablein classorg.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
-
handleMethodArgumentNotValid
protected org.springframework.http.ResponseEntity<Object> handleMethodArgumentNotValid(@NonNull org.springframework.web.bind.MethodArgumentNotValidException ex, @NonNull org.springframework.http.HttpHeaders headers, @NonNull org.springframework.http.HttpStatusCode status, @NonNull org.springframework.web.context.request.WebRequest request) 處理 @Valid 或 @Validated 驗證失敗 Source: Spring Validation - 當請求體驗證失敗時拋出- Overrides:
handleMethodArgumentNotValidin classorg.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
-
handleFrameworkException
@ExceptionHandler({org.springframework.transaction.TransactionSystemException.class,jakarta.validation.ValidationException.class,org.springframework.dao.DataAccessException.class,org.springframework.http.converter.HttpMessageConversionException.class}) protected org.springframework.http.ResponseEntity<Object> handleFrameworkException(Exception ex, org.springframework.web.context.request.WebRequest request) 統一處理 Spring 和 Jakarta 框架異常 Sources:
- TransactionSystemException: Spring Transaction - 事務提交時驗證失敗
- ValidationException: Jakarta Validation - Bean Validation 驗證失敗
- DataAccessException: Spring Data - JPA/JDBC 資料庫操作異常
- HttpMessageConversionException: Spring Web - HTTP 訊息轉換失敗 (如 JSON 解析錯誤)
-
handleHttpClientException
@ExceptionHandler(HttpClientException.class) protected org.springframework.http.ResponseEntity<Object> handleHttpClientException(HttpClientException ex, org.springframework.web.context.request.WebRequest request) 處理 AppFuse HTTP 客戶端異常 Source: AppFuse HTTP Client - HTTP 客戶端呼叫異常 -
mapDownstreamHttpException
將下游 HTTP 回應錯誤映射成對外 ProblemDetail。
建立最小揭露政策使用的下游錯誤視圖。下游 401/403 不代表 API caller 未登入或 缺少本服務權限,因此收斂為 502;其他狀態碼維持既有對外狀態。最大揭露政策則 使用保留服務、原始狀態、路徑與錯誤內容的詳細視圖。特殊整合可覆寫此方法,自訂 應用層最小揭露契約。
- Parameters:
ex- 帶下游來源脈絡的 HTTP client 例外- Returns:
- 對外 ProblemDetail
-
handleApplicationException
@ExceptionHandler(ApplicationException.class) protected org.springframework.http.ResponseEntity<Object> handleApplicationException(ApplicationException ex, org.springframework.web.context.request.WebRequest request) 處理應用程式自定義異常 Source: AppFuse - 業務邏輯層拋出的語義化異常 Includes: NotFoundException, ConflictException, DuplicateException, etc. -
handleAccessDenied
@ExceptionHandler(org.springframework.security.access.AccessDeniedException.class) protected org.springframework.http.ResponseEntity<Object> handleAccessDenied(org.springframework.security.access.AccessDeniedException ex, org.springframework.web.context.request.WebRequest request) 處理授權拒絕(已認證但權限不足)→ 403 Source: Spring Security 方法層授權(@PreAuthorize等),其拋出的AuthorizationDeniedException為AccessDeniedException子型別。這類拒絕在 控制器調用期間拋出、先經 MVC 例外解析,若不在此明確映射會落入兜底 handler 被誤判為 500。 此處映為 RFC 7807 的 403 Forbidden。 註:URL 層授權拒絕(authorizeHttpRequests)由 Spring Security filter 的AccessDeniedHandler處理、不經此處(亦會帶 RFC 6750WWW-Authenticate挑戰標頭)。 -
handleAuthenticationException
@ExceptionHandler(org.springframework.security.core.AuthenticationException.class) protected org.springframework.http.ResponseEntity<Object> handleAuthenticationException(org.springframework.security.core.AuthenticationException ex, org.springframework.web.context.request.WebRequest request) 處理認證失敗並保留實際 Spring Security 例外至揭露政策邊界。 -
handleJwtException
@ExceptionHandler(io.jsonwebtoken.JwtException.class) protected org.springframework.http.ResponseEntity<Object> handleJwtException(io.jsonwebtoken.JwtException ex, org.springframework.web.context.request.WebRequest request) JWT 驗證錯誤保留原始 parser 診斷;最小政策仍可收斂為 access token 無效。 -
handleOtherException
-
handleProblemDetail
protected org.springframework.http.ResponseEntity<Object> handleProblemDetail(org.springframework.http.ProblemDetail problem, Throwable cause, org.springframework.web.context.request.WebRequest request) 統一處理 ProblemDetail 並返回 RFC 7807 格式的 JSON 回應- Parameters:
problem- ProblemDetail 物件cause- 原始異常(用於日誌記錄)request- WebRequest(用於取得請求路徑)
-
handleProblemDetail
-
formatViolations
將 ProblemDetail 的 violations 渲染成可讀字串,附加於日誌訊息之後
Bean Validation 的違規訊息是通用句(每個欄位皆為 "must not be blank"), 欄位名只存在於
Violation.getProps()。日誌若僅記錄 detail,違規欄位就完全遺失。- Parameters:
problem- ProblemDetail 物件- Returns:
- 形如
violations=[email=must not be blank];無違規時回空字串
-
extractPath
從 WebRequest 提取請求路徑
-