成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Springboot3新特性異常信息ProblemDetail詳解

開發 前端
要為Spring WebFlux異常和任何ErrorResponseException啟用RFC 7807響應,需要擴展 ResponseEntityExceptionHandler,并在Spring配置中把它聲明為@ControllerAdvice。處理程序有一個@ExceptionHandler方法,可以處理所有ErrorResponse異常,其中包括所有內置的web異常。您可以添加更多的異常

環境:Springboot3.0.5

概述

RFC 7807定義了為HTTP響應中錯誤的可讀詳細信息,以避免需要為HTTP API定義新的錯誤響應格式。HTTP [RFC7230]狀態碼有時不足以傳達關于錯誤的足夠信息。

RFC 7807 定義了簡單的JSON[RFC7159]和XML[W3C.REC-XML-20081126]文檔格式以滿足此目的。它們被設計為可由HTTP API重用,HTTP API可以識別特定于其需求的不同“問題類型”。

因此,API客戶端既可以知道高級錯誤類(使用狀態碼),也可以知道問題的細粒度細節。

例如,考慮一個響應,該響應表明客戶的賬戶沒有足夠的權限。403禁止狀態代碼可能被認為是最適合使用的,因為它將向HTTP通用軟件(如客戶端庫、緩存和代理)通知響應的一般語義。然而,這并沒有為API客戶端提供足夠的信息,說明為什么禁止請求、適用的帳戶余額或如何糾正問題。如果這些細節以可讀的格式包含在響應體中,則客戶端可以適當地處理它;例如觸發將更多的信用轉移到賬戶中。

RFC 7807規范通過使用URI[RFC3986]識別特定類型的問題(例如,“信用不足”)來實現這一點;HTTP API可以通過指定受其控制的新URI或重用現有URI來實現這一點。

此外,Problem Detail信息可以包含其他信息,例如標識問題具體發生的URI(有效地為“Joe上周四沒有足夠的信用”這一概念提供了標識符),這對于支持或取證目的可能很有用。

Problem Detail的數據模型是一個JSON[RFC7159]對象;當格式化為JSON文檔時,它使用“application/problem+json”媒體類型。

請注意,Problem Detail 不是在HTTP中傳達問題細節的唯一方式;例如,如果響應仍然是資源的表示,那么通常最好以該應用程序的格式來描述相關細節。同樣,在許多情況下,有一個適當的HTTP狀態代碼,不需要傳遞額外的細節。

Problem Detail消息格式

Problem Detail的規范模型是JSON對象。當序列化為JSON文檔時,該格式用“application/problem+json”媒體類型標識。

例如,一個帶有JSONProblem Detail的HTTP響應:

HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Content-Language: en
{
    "type": "https://pack.com/probs/out-of-credit",
    "title": "你沒有足夠的信用。",
    "detail": "你現在的余額是30,但是要花50。",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345", "/account/67890"]
}

這里,結余不足問題(由其類型URI標識)

  • type:標識問題類型的URI引用
  • title:中指明了403的原因
  • instance:給出了具體問題發生的參考
  • detail:中給出了發生的具體細節,并添加了兩個擴展
  • balance:表示帳戶的余額
  • accounts:提供了可以充值帳戶的鏈接

傳遞問題特定擴展的能力允許傳遞多個問題。例如:

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en
 {
   "type": "https://example.net/validation-error",
   "title": "Your request parameters didn't validate.",
   "invalid-params": [ {
      "name": "age",
      "reason": "must be a positive integer"
    },
    {
      "name": "color",
      "reason": "must be 'green', 'red' or 'blue'"
    }
  ]
}

Spring支持

從Spring6.x開始支持Problem Detail。

REST服務的一個常見需求是在錯誤響應的主體中包含詳細信息。Spring框架支持“Problem Details for HTTP APIs”規范,即RFC 7807。

以下是此支持的主要抽象:

  • ProblemDetail — ?RFC 7807問題細節的表示;一個簡單的容器,用于規范中定義的標準字段和非標準字段。
  • ErrorResponse — 以RFC 7807的格式暴露HTTP錯誤響應細節,包括HTTP狀態、響應頭和響應體;這允許異常封裝并暴露它們如何映射到HTTP響應的細節。所有Spring MVC異常都實現了這一點。
  • ErrorResponseException?—?基本的ErrorResponse實現,其他人可以作為一個方便的基類使用。
  • ResponseEntityExceptionHandler?—?@ControllerAdvice的方便基類,它處理所有Spring MVC異常,以及任何ErrorResponseException,并渲染一個帶有主體的錯誤響應。

Spring中要使用ProblemDetail首先需要通過如下配置開啟:

spring:
  mvc:
    problemdetails:
      enabled: true

我們可以在任何使用@ExceptionHandler或任何@RequestMapping方法返回ProblemDetailErrorResponse以呈現RFC 7807響應。處理方式如下:

  • ProblemDetail的status屬性決定了HTTP的狀態。
  • 如果還沒有設置,則從當前URL路徑設置ProblemDetail的實例屬性。
  • 對于內容協商,Jackson HttpMessageConverter在渲染ProblemDetail時更喜歡“application/problem+json”而不是“application/json”,如果沒有找到兼容的媒體類型,也會使用它。

要為Spring WebFlux異常和任何ErrorResponseException啟用RFC 7807響應,需要擴展 ResponseEntityExceptionHandler,并在Spring配置中把它聲明為@ControllerAdvice。處理程序有一個@ExceptionHandler方法,可以處理所有ErrorResponse異常,其中包括所有內置的web異常。您可以添加更多的異常處理方法,并使用protected方法將任何異常映射到ProblemDetail。

非標準字段

可以通過以下兩種方式之一使用非標準字段擴展RFC7807響應。

一、ProblemDetail類中有個Map集合的'properties'屬性。在使用Jackson庫時,Spring框架注冊了ProblemDetailJacksonMixin,以確保這個“properties”映射被展開,并在響應中作為頂級JSON屬性呈現,同樣,反序列化期間的任何未知屬性都會插入到這個Map中。

你還可以擴展ProblemDetail以添加專用的非標準屬性。ProblemDetail中的復制構造函數允許從現有的ProblemDetail中輕松創建子類。這可以集中完成,例如從@ControllerAdvice,如ResponseEntityExceptionHandler,它將異常的ProblemDetail重新創建到一個具有額外非標準字段的子類中。

ProblemDetail類

public class ProblemDetail {
  private static final URI BLANK_TYPE = URI.create("about:blank");
  private URI type = BLANK_TYPE;
  @Nullable
  private String title;
  private int status;
  @Nullable
  private String detail;
  @Nullable
  private URI instance;
  @Nullable
  private Map<String, Object> properties;
}

測試接口:

@RestController
@RequestMapping("/demo")
public class DemoController {


  @GetMapping("")
  public Object index(Integer age) {
    System.out.println(1 / 0) ;
    return "success" ;
  }
  
}

示例1:

基礎使用

@RestControllerAdvice
public class GlobalExceptionHandler {
  
  // 當發生異常后直接返回ProblemDetail對象
  @ExceptionHandler({Exception.class})
  public ProblemDetail handle(Exception e) {
    ProblemDetail detail = ProblemDetail.forStatusAndDetail(HttpStatusCode.valueOf(500), e.getMessage());
    return detail ;
  }
}

運行結果:

圖片

示例2:

添加擴展屬性

@RestControllerAdvice
public class GlobalExceptionHandler {
  
  // 這里使用的是ErrorResponse
  @ExceptionHandler({ArithmeticException.class})
  public ErrorResponse handle(Exception e) {
    ErrorResponse errorResponse = new ErrorResponseException(HttpStatusCode.valueOf(500), e) ;
    errorResponse.getBody().setProperty("operator_time", new Date()) ;
    return errorResponse ;
  }
  
}

運行結果:

圖片

示例3:

繼承自ResponseEntityExceptionHandler該類中定義了@ExceptionHandler注解的方法,能夠處理大多數常見的異常。

@ControllerAdvice
final class ProblemDetailsExceptionHandler extends ResponseEntityExceptionHandler {
}

ResponseEntityExceptionHandler

public abstract class ResponseEntityExceptionHandler implements MessageSourceAware {
  @ExceptionHandler({
    HttpRequestMethodNotSupportedException.class,
    HttpMediaTypeNotSupportedException.class,
    HttpMediaTypeNotAcceptableException.class,
    MissingPathVariableException.class,
    MissingServletRequestParameterException.class,
    MissingServletRequestPartException.class,
    ServletRequestBindingException.class,
    MethodArgumentNotValidException.class,
    NoHandlerFoundException.class,
    AsyncRequestTimeoutException.class,
    ErrorResponseException.class,
    ConversionNotSupportedException.class,
    TypeMismatchException.class,
    HttpMessageNotReadableException.class,
    HttpMessageNotWritableException.class,
    BindException.class
  })
  @Nullable
  public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
    if (ex instanceof HttpMessageNotWritableException theEx) {
      return handleHttpMessageNotWritable(theEx, headers, HttpStatus.INTERNAL_SERVER_ERROR, request);
    }
    // ...
  }
  protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
    ProblemDetail body = createProblemDetail(ex, status, "Failed to write request", null, null, request);
    return handleExceptionInternal(ex, body, headers, status, request);
  }
}

該類是Spring提供的默認實現,要使用該類是需要通過如下配置開啟:

spring.mvc.problemdetails.enabled=true

處理原理

當返回結果是ProblemDetail或者ErrorResponse時通過如下類進行解析處理:

public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor {
  public boolean supportsReturnType(MethodParameter returnType) {
    Class<?> type = returnType.getParameterType();
    return ((HttpEntity.class.isAssignableFrom(type) && !RequestEntity.class.isAssignableFrom(type)) || ErrorResponse.class.isAssignableFrom(type) || ProblemDetail.class.isAssignableFrom(type));
  }
  public void handleReturnValue(...) throws Exception {
    HttpEntity<?> httpEntity;
    if (returnValue instanceof ErrorResponse response) {
      httpEntity = new ResponseEntity<>(response.getBody(), response.getHeaders(), response.getStatusCode());
    } else if (returnValue instanceof ProblemDetail detail) {
      httpEntity = ResponseEntity.of(detail).build();
    }
    if (httpEntity.getBody() instanceof ProblemDetail detail) {
      if (detail.getInstance() == null) {
        URI path = URI.create(inputMessage.getServletRequest().getRequestURI());
        detail.setInstance(path);
      }
    }
    // ...
    writeWithMessageConverters(httpEntity.getBody(), returnType, inputMessage, outputMessage);
    outputMessage.flush();
  }
}

以上就是ProblemDetail在Spring中的實現原理。

責任編輯:武曉燕 來源: 實戰案例錦集
相關推薦

2023-08-07 14:28:07

SpringBoot工具

2010-01-05 09:26:13

.NET 4.0

2023-08-09 08:29:51

SpringWeb編程

2010-10-12 09:52:02

ASP.NET MVC

2013-07-29 15:13:35

2023-02-01 10:40:01

2025-04-16 10:03:40

開發Spring應用程序

2023-08-11 08:59:49

分庫分表數據數據庫

2022-10-26 07:14:25

Spring 6Spring業務

2024-10-08 08:26:43

2009-06-29 17:42:03

Tapestry5新特

2009-07-27 09:46:28

Silverlight

2012-01-09 16:00:56

2010-10-08 14:32:32

ASP.NET MVCNuPack

2024-07-31 14:03:00

Spring定時任務管理

2023-08-08 08:23:08

Spring日志?線程池

2024-09-11 09:15:06

2009-02-04 17:33:24

ibmdwPython

2024-04-18 08:04:47

ElectronChrome升級

2011-02-21 16:39:47

Android 2.3Android R5
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩国产在线 | 国产精品成人一区二区三区 | 欧美中文在线 | 欧美高清成人 | 四虎影院在线观看av | 欧美精品一区在线 | 免费在线h视频 | 欧美精品tv | 一区二区在线 | 国产电影一区二区在线观看 | 精品亚洲一区二区三区四区五区 | 亚洲午夜网 | 91在线看片 | 成人亚洲| 日韩av美女电影 | 在线观看av网站 | 国产片侵犯亲女视频播放 | 国产精品久久网 | 亚洲激情在线观看 | 亚洲欧美精品久久 | 怡红院免费的全部视频 | 国产精品射 | 精品一区二区三 | 91精品中文字幕一区二区三区 | 一区二区三区四区国产 | www.色五月.com | 欧美日韩国产三级 | 婷婷色综合 | 成人免费网视频 | 伊人久久成人 | 久久99蜜桃综合影院免费观看 | 久久久精品影院 | 精品一区二区三区四区 | 日韩在线成人 | 在线国产一区二区三区 | 午夜成人免费视频 | 欧美成人h版在线观看 | 国产精品伦理一区 | 国产乱肥老妇国产一区二 | 精品国产青草久久久久96 | 91久久久久 |