统一异常处理

发布于:2024-10-17 ⋅ 阅读:(12) ⋅ 点赞:(0)

在Spring Boot项目中,设计统一的异常处理可以帮助你更好地管理和处理应用中的错误,并以一致的方式返回友好的错误响应。Spring Boot提供了多种方式来实现统一异常处理,常见的方式是通过@ControllerAdvice和@ExceptionHandler注解来集中管理所有控制器的异常。

  1. 基本设计思路
    通过@ControllerAdvice类全局捕获异常,并使用@ExceptionHandler针对不同类型的异常做处理,然后返回自定义的响应。
  2. 代码实现
    2.1 自定义异常类
    首先定义一些自定义的异常类,根据你的业务需求来扩展异常处理。
public class CustomNotFoundException extends RuntimeException {
    public CustomNotFoundException(String message) {
        super(message);
    }
}
public class CustomBadRequestException extends RuntimeException {
    public CustomBadRequestException(String message) {
        super(message);
    }
}

2.2 定义错误响应类
用于统一返回错误信息。

public class ErrorResponse {
    private int status;
    private String message;
    private long timestamp;


    public ErrorResponse(int status, String message) {
        this.status = status;
        this.message = message;
        this.timestamp = System.currentTimeMillis();
    }

    // Getters and setters
    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
}

2.3 统一异常处理类
使用@ControllerAdvice注解定义全局异常处理类,并用@ExceptionHandler处理不同的异常类型。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理自定义的资源未找到异常
    @ExceptionHandler(CustomNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFoundException(CustomNotFoundException ex, WebRequest request) {
        ErrorResponse error = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    // 处理自定义的非法请求异常
    @ExceptionHandler(CustomBadRequestException.class)
    public ResponseEntity<ErrorResponse> handleBadRequestException(CustomBadRequestException ex, WebRequest request) {
        ErrorResponse error = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    // 处理所有其他未处理的异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex, WebRequest request) {
        ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected error occurred");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

2.4 在Controller中使用异常
在Controller中直接抛出自定义异常,以便由全局异常处理器捕获。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyController {

    @GetMapping("/item/{id}")
    public String getItem(@PathVariable int id) {
        if (id == 1) {
            return "Item 1";
        } else if (id == 2) {
            throw new CustomNotFoundException("Item not found");
        } else {
            throw new CustomBadRequestException("Invalid request");
        }
    }
}
  1. 返回格式示例
    假设你请求 /api/item/2,将会返回如下JSON格式的错误响应:
{
    "status": 404,
    "message": "Item not found",
    "timestamp": 1665891017191
}
  1. 扩展:日志与监控
    除了捕获异常和返回响应,通常也会在异常处理过程中记录日志,以便后续分析问题。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex, WebRequest request) {
        logger.error("Unhandled exception occurred: ", ex); // 记录异常信息
        ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected error occurred");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}