全局异常处理需用@ControllerAdvice+@ExceptionHandler,通过HttpServletRequest获取request.getRequestURI()路径,用Instant.now().toString()生成ISO格式时间戳,封装进ErrorResponse统一响应体返回。

在 Spring Boot 项目中,全局异常处理通常通过 @ControllerAdvice + @ExceptionHandler 实现。要让响应体中包含请求路径(URI)和时间戳,关键是在异常处理器方法中获取当前请求上下文,并将其注入到返回的响应对象里。
使用 HttpServletRequest 获取请求路径
Spring MVC 会自动将当前请求的 HttpServletRequest 注入到 @ExceptionHandler 方法参数中,你可以直接用它拿到原始请求路径:
-
request.getRequestURL():返回完整 URL(含协议、域名、端口、路径、查询参数) -
request.getRequestURI():只返回路径部分(如/api/users/123),更常用 -
request.getQueryString():可选,拼接后得到带参数的路径
时间戳建议用 Instant.now() 而非 new Date()
推荐使用 Java 8 的 Instant 类生成时间戳,语义清晰且线程安全:
-
Instant.now()返回 UTC 时刻,适合日志和 API 响应 - 如果前端需要格式化时间,可转为 ISO 格式字符串:
Instant.now().toString()(如"2024-05-20T08:32:15.123Z") - 避免用
new Date().getTime(),虽然也能用,但不如Instant明确表达“时间点”含义
定义统一错误响应结构
创建一个标准响应类,把路径、时间戳、错误码、消息等都纳入其中:
立即学习“Java免费学习笔记(深入)”;
public class ErrorResponse {
private String timestamp; // 如 "2024-05-20T08:32:15.123Z"
private String path; // 如 "/api/orders"
private int status;
private String error;
private String message;
// 构造函数、getter、setter 省略
}
在异常处理器中实例化它,并填充请求信息:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public ResponseEntity<ErrorResponse> handleRuntimeException(
RuntimeException e, HttpServletRequest request) {
ErrorResponse response = new ErrorResponse();
response.setTimestamp(Instant.now().toString());
response.setPath(request.getRequestURI());
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.setError("Internal Server Error");
response.setMessage(e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
补充说明:确保请求上下文可用
上述方式依赖 Spring MVC 的请求绑定机制,在 WebMVC 环境下默认可用。但需注意:
- 该方法不适用于纯异步线程(如
@Async或手动启的线程),因为HttpServletRequest是线程绑定的 - 若用 WebFlux(响应式栈),需改用
ServerWebExchange获取路径:exchange.getRequest().getURI().getPath() - 时间戳字段建议用
String类型返回,避免序列化时因时区或格式引发歧义


















