0Pricing
Java Academy · 课时

RFC 7807 问题详情与一致的错误响应

使用 Spring 6 的 ProblemDetail,返回符合 RFC 7807 的结构化错误负载

RFC 7807 问题详情与一致的错误响应 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

什么是 RFC 7807?

RFC 7807《HTTP API 的问题详情》定义了错误响应的标准 JSON 格式。它避免为每个 API 使用自定义错误格式,并为客户端提供可预测、易于解析的结构。

RFC 7807 字段

标准字段包括:type(用于标识问题的 URI)、title(人类可读的摘要)、status(HTTP 状态码)、detail(具体说明)和 instance(特定问题发生实例的 URI)。

{
  "type": "https://api.example.com/errors/not-found",
  "title": "Resource Not Found",
  "status": 404,
  "detail": "User with id 42 does not exist.",
  "instance": "/api/users/42"
}

Spring 6 的 ProblemDetail

Spring 6 / Spring Boot 3 内置了对 ProblemDetail 的支持。您可以从异常处理器返回 ProblemDetail,也可以使用 ErrorResponseException。

import org.springframework.http.ProblemDetail;

@ExceptionHandler(ResourceNotFoundException.class)
public ProblemDetail handleNotFound(ResourceNotFoundException ex, HttpServletRequest req) {
    ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
    pd.setType(URI.create("https://api.example.com/errors/not-found"));
    pd.setTitle("Resource Not Found");
    pd.setInstance(URI.create(req.getRequestURI()));
    return pd;
}

添加自定义扩展

ProblemDetail 通过 setProperty(key, value) 支持扩展属性,可用于添加错误代码或字段错误等领域特定的详细信息。

ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
pd.setTitle("Validation Failed");
pd.setProperty("errors", fieldErrors); // custom extension
pd.setProperty("timestamp", Instant.now());

为 Spring MVC 启用 RFC 7807

在 application.properties 中设置 spring.mvc.problemdetails.enabled=true,即可为所有内置 Spring 异常启用 ProblemDetail。之后,Spring 会自动将标准异常(404、405 等)包装为 RFC 7807 格式。

# application.properties:
spring.mvc.problemdetails.enabled=true

ErrorResponseException

您可以在服务代码中抛出 ErrorResponseException,无需编写处理器方法即可生成 RFC 7807 响应——Spring MVC 会捕获该异常并对其进行格式化。

throw new ErrorResponseException(HttpStatus.CONFLICT,
    ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT,
        "Email already exists: " + email), null);

自定义 ProblemDetail 子类

创建 ProblemDetail 的领域专用子类,以添加具有明确类型的扩展字段,同时让处理器代码保持简洁。

public class ValidationProblemDetail extends ProblemDetail {
    private final Map<String, String> fieldErrors;
    public ValidationProblemDetail(Map<String, String> errors) {
        super(HttpStatus.BAD_REQUEST.value());
        this.fieldErrors = errors;
        setTitle("Validation Failed");
        setProperty("fieldErrors", errors);
    }
}

内容类型:application/problem+json

RFC 7807 响应应使用 application/problem+json 内容类型,以便客户端将问题响应与普通 JSON 负载区分开来。

return ResponseEntity.status(HttpStatus.NOT_FOUND)
    .contentType(MediaType.APPLICATION_PROBLEM_JSON)
    .body(pd);

统一错误结构检查清单

一个良好的错误 API 应包含:(1) 可供机器读取的类型 URI;(2) 人类可读的标题;(3) 准确的 HTTP 状态码;(4) 具体的详细消息;(5) 请求实例 URI;(6) 可选的扩展字段(时间戳、traceId、字段错误)。

用于可观测性的跟踪 ID

将请求的跟踪 ID(来自 Micrometer Tracing 或 MDC)作为扩展属性添加,这样工程师就可以将错误日志与具体的失败请求关联起来。

pd.setProperty("traceId", MDC.get("traceId"));
pd.setProperty("timestamp", Instant.now());

测试问题详情

在 @WebMvcTest 测试中,断言响应内容类型为 application/problem+json,并确认 status、title 和 detail 等 JSON 字段与预期值一致。

mockMvc.perform(get("/api/users/999"))
    .andExpect(status().isNotFound())
    .andExpect(content().contentType("application/problem+json"))
    .andExpect(jsonPath("$.status").value(404))
    .andExpect(jsonPath("$.title").value("Resource Not Found"));

快速检查

哪个 Spring Boot 属性可以为内置的 Spring MVC 异常启用 RFC 7807?

回顾

RFC 7807 通过 type、title、status、detail 和 instance 字段规范化了 JSON 错误响应。Spring 6 提供了 ProblemDetail 和 ErrorResponseException。通过 spring.mvc.problemdetails.enabled=true 启用它。添加 traceId 和时间戳作为扩展字段,以支持可观测性。

常见问题解答

「RFC 7807 问题详情与一致的错误响应」课时是免费的吗?

是的 — 「RFC 7807 问题详情与一致的错误响应」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「RFC 7807 问题详情与一致的错误响应」这节课中我会学到什么?

使用 Spring 6 的 ProblemDetail,返回符合 RFC 7807 的结构化错误负载 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「RFC 7807 问题详情与一致的错误响应」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Bean 验证:@NotNull、@Size、@Pattern
  2. 自定义约束注解
  3. 使用 @ControllerAdvice 进行全局异常处理
  4. RFC 7807 问题详情与一致的错误响应
← 返回 Java Academy