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=trueErrorResponseException
您可以在服务代码中抛出 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 反馈 — 无需本地设置。
此课程中的所有课时
- Bean 验证:@NotNull、@Size、@Pattern
- 自定义约束注解
- 使用 @ControllerAdvice 进行全局异常处理
- RFC 7807 问题详情与一致的错误响应