环境: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的规范模型是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标识)
传递问题特定扩展的能力允许传递多个问题。例如:
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'"
}
]
}
从Spring6.x开始支持Problem Detail。
REST服务的一个常见需求是在错误响应的主体中包含详细信息。Spring框架支持“Problem Details for HTTP APIs”规范,即RFC 7807。
以下是此支持的主要抽象:
Spring中要使用ProblemDetail首先需要通过如下配置开启:
spring:
mvc:
problemdetails:
enabled: true
我们可以在任何使用@ExceptionHandler或任何@RequestMapping方法返回ProblemDetail或ErrorResponse以呈现RFC 7807响应。处理方式如下:
要为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 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
该类是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中的实现原理。
文章标题:Springboot3新特性异常信息ProblemDetail详解
链接地址:http://www.36103.cn/qtweb/news35/23435.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联