You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot REST API移除try-catch,仅用@ExceptionHandler处理异常

移除API中所有try-catch,仅用@ExceptionHandler统一处理异常

完全可以通过全局异常处理器实现无try-catch的异常处理,你之前用@ExceptionHandler没生效,大概率是没配置全局生效的注解。以下是具体实现步骤:


1. 配置全局异常处理器(核心)

必须给异常处理类添加@RestControllerAdvice(针对REST API)或@ControllerAdvice注解,这样@ExceptionHandler才能全局生效(否则仅对当前Controller有效)。

示例代码:

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理自定义业务异常
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
        ErrorResponse error = new ErrorResponse(ex.getCode(), ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationError(MethodArgumentNotValidException ex) {
        String errorMsg = ex.getBindingResult().getFieldErrors().stream()
                .map(err -> err.getField() + ": " + err.getDefaultMessage())
                .collect(Collectors.joining(", "));
        ErrorResponse error = new ErrorResponse("400", "参数错误:" + errorMsg);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    // 兜底处理所有未捕获异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
        ErrorResponse error = new ErrorResponse("500", "服务器内部错误");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 统一错误响应体
class ErrorResponse {
    private String code;
    private String message;

    public ErrorResponse(String code, String message) {
        this.code = code;
        this.message = message;
    }

    // getter、setter 省略
}

2. 移除业务代码中的try-catch

直接让异常向上抛出即可,无需在Controller/Service层捕获:

Controller层示例

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        // 无try-catch,异常直接抛给全局处理器
        User user = userService.getUserById(id);
        return ResponseEntity.ok(user);
    }

    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody UserRequest request) {
        User user = userService.createUser(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
}

Service层示例

@Service
public class UserService {

    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("404", "用户不存在"));
    }
}

// 自定义业务异常类
class BusinessException extends RuntimeException {
    private String code;

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
    }

    public String getCode() {
        return code;
    }
}

3. 排查@ExceptionHandler不生效的常见原因

  • 未添加@RestControllerAdvice/@ControllerAdvice:单独的@ExceptionHandler仅在当前Controller范围内生效,无法全局捕获。
  • 异常被中间层提前捕获:比如Filter、Interceptor中的try-catch会拦截异常,导致无法传递到全局处理器。
  • 异常类型匹配错误:确保@ExceptionHandler注解指定的异常类型与抛出的异常匹配(子类异常会优先匹配对应处理器)。

内容的提问来源于stack exchange,提问作者Aditya Mehta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:08:25