SpringBoot 全局异常处理终极指南
@RestController
@RequestMapping("/user")
publicclassUserController {
@GetMapping("/{id}")
public ApiResponse<String> getUser(@PathVariableint id) {
if (id == 0) {
thrownewBusinessException(404, "用户不存在");
}
return ApiResponse.success("用户ID: " + id);
}
}
@GetMapping("/{id}")
public User getUser(@PathVariableint id) {
try {
return userService.findById(id);
} catch (Exception e) {
e.printStackTrace();
returnnull;
}
}
-
• try-catch逻辑冗余,重复代码太多。 -
• 一旦抛出异常,返回值不明确,前端无法准确感知错误信息。
@ControllerAdvice + @ExceptionHandler。ApiResponse,用于统一接口返回格式:publicclassApiResponse<T> {
privateint code;
private String message;
private T data;
publicApiResponse(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
publicstatic <T> ApiResponse<T> success(T data) {
returnnewApiResponse<>(200, "success", data);
}
publicstatic <T> ApiResponse<T> error(int code, String message) {
returnnewApiResponse<>(code, message, null);
}
// getter & setter
}
除了系统异常(NullPointerException、SQLException 等),我们还需要定义 业务异常,用于明确业务逻辑错误:publicclassBusinessExceptionextendsRuntimeException {
privateint code;
publicBusinessException(int code, String message) {
super(message);
this.code = code;
}
publicintgetCode() {
return code;
}
}
例如:用户不存在、余额不足、参数非法等,都可以通过 BusinessException 来抛出。接下来,通过 @RestControllerAdvice来统一捕获异常:@RestControllerAdvice
publicclassGlobalExceptionHandler {
// 处理业务异常
@ExceptionHandler(BusinessException.class)
public ApiResponse<?> handleBusinessException(BusinessException ex) {
return ApiResponse.error(ex.getCode(), ex.getMessage());
}
// 处理参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResponse<?> handleValidException(MethodArgumentNotValidException ex) {
Stringmsg= ex.getBindingResult().getFieldError().getDefaultMessage();
return ApiResponse.error(400, msg);
}
// 兜底异常处理
@ExceptionHandler(Exception.class)
public ApiResponse<?> handleException(Exception ex) {
ex.printStackTrace(); // 可接入日志系统
return ApiResponse.error(500, "服务器内部错误");
}
}
{
"code":200,
"message":"success",
"data":"用户ID: 1"
}
{
"code":404,
"message":"用户不存在",
"data":null
}
{
"code":500,
"message":"服务器内部错误",
"data":null
}
try-catch。Logback、ELK)或异常监控平台(如 Sentry)。@ExceptionHandler(Exception.class)
public ApiResponse<?> handleException(Exception ex, HttpServletRequest request) {
// 记录日志信息
ErrorLoglog=newErrorLog();
log.setUri(request.getRequestURI());
log.setMethod(request.getMethod());
log.setMessage(ex.getMessage());
log.setStackTrace(Arrays.toString(ex.getStackTrace()));
log.setCreateTime(LocalDateTime.now());
errorLogRepository.save(log); // JPA 或 MyBatis 保存
return ApiResponse.error(500, "服务器内部错误");
}
其中 ErrorLog 可以定义为:@Entity
publicclassErrorLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String uri;
private String method;
private String message;
private String stackTrace;
private LocalDateTime createTime;
// getter & setter
}
logback-spring.xml 中使用 logstash-logback-encoder 输出 JSON:<configuration>
<appendername="LOGSTASH"class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app-log.json</file>
<encoderclass="net.logstash.logback.encoder.LoggingEventEncoder"/>
</appender>
<rootlevel="INFO">
<appender-refref="LOGSTASH"/>
</root>
</configuration>
logstash.conf):input {
file {
path =>"/usr/local/app/logs/app-log.json"
codec => json
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "springboot-error-%{+YYYY.MM.dd}"
}
}
Kibana Dashboard,可以实现:Prometheus Alertmanager)。https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
使用 RestTemplate 发送 POST 请求:@Component
publicclassFeishuBotNotifier {
privatestaticfinalStringWEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx";
privatefinalRestTemplaterestTemplate=newRestTemplate();
publicvoidsendAlert(String title, String content) {
Map<String, Object> body = newHashMap<>();
body.put("msg_type", "text");
Map<String, String> text = newHashMap<>();
text.put("text", String.format("【异常告警】\n标题: %s\n详情: %s", title, content));
body.put("content", text);
restTemplate.postForEntity(WEBHOOK_URL, body, String.class);
}
}
@RestControllerAdvice
@RequiredArgsConstructor
publicclassGlobalExceptionHandler {
privatefinal FeishuBotNotifier feishuBotNotifier;
@ExceptionHandler(Exception.class)
public ApiResponse<?> handleException(Exception ex, HttpServletRequest request) {
// 构造告警信息
Stringtitle="SpringBoot 服务异常";
Stringcontent= String.format("URI: %s\nMethod: %s\n错误: %s",
request.getRequestURI(), request.getMethod(), ex.getMessage());
// 发送飞书告警
feishuBotNotifier.sendAlert(title, content);
ex.printStackTrace();
return ApiResponse.error(500, "服务器内部错误");
}
}
【异常告警】
标题: SpringBoot 服务异常
详情:
URI: /user/0
Method: GET
错误: 用户不存在
-
• 全局异常处理:统一返回格式,简化开发。 -
• 业务异常区分:明确业务错误与系统错误。 -
• 日志落库:异常可持久化追溯。 -
• ELK 接入:日志可视化分析,支持查询与报表。 -
• 飞书机器人告警:重大异常实时通知,提高运维响应速度。
接口开发 → 异常收敛 → 日志分析 → 实时告警 的完整链路,既保证了系统的可维护性,也提升了线上运维的响应效率。
摘抄自网络,便于检索查找。

浙公网安备 33010602011771号