首页 > 其他分享 >springboot全局异常处理示例

springboot全局异常处理示例

时间:2025-01-17 17:29:41浏览次数:3  
标签:springboot 示例 springframework public ResponseEntity org import 全局 response

这种错误交给前端无法处理。

  • 需要自定义一些错误响应类给前端
package cn.yam.bloomfilter.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleAllExceptions(Exception ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.put("message", "服务器内部错误");
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
  1. 创建一个全局异常处理类。
  2. 使用 @ControllerAdvice@ExceptionHandler 注解。|
  3. 定义返回 JSON 格式的错误响应

处理完成之后,就变成如下图所示。

如何自定义发现的异常

以请求参数错误为例子:

  • 定义一个 异常类InvalidParameterException
package cn.yam.bloomfilter.exception;

public class InvalidParameterException extends RuntimeException {
    public InvalidParameterException(String message) {
        super(message);
    }
}
  • 抛出
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user == null) {
            throw new InvalidParameterException("用户ID: " + id);
        }
        return ResponseEntity.ok(user);
    }
}
  • 全局异常异常处理器
package cn.yam.bloomfilter.exception;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(InvalidParameterException.class)
    public ResponseEntity<Map<String, Object>> handleInvalidParameterException(InvalidParameterException ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.BAD_REQUEST.value());
        response.put("message", "参数错误: " + ex.getMessage());
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

}

探究 ResponseEntity作用


场景描述

假设我们有一个 /resource/{id} 接口,用于根据 ID 查找资源。如果资源不存在,返回 404 Not Found 和错误信息;如果资源存在,返回 200 OK 和资源数据。


  1. 不加 ResponseEntity 的例子
package cn.yam.bloomfilter.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class ResourceController {

    @GetMapping("/resource/{id}")
    public Map<String, Object> getResource(@PathVariable int id) {
        Map<String, Object> response = new HashMap<>();

        // 模拟资源查找
        if (id == 1) {
            response.put("data", "Resource Data");
        } else {
            response.put("status", 404);
            response.put("message", "资源未找到");
        }

        return response;
    }
}

测试结果

  • 请求 /resource/1:
    • 响应体:
{
  "data": "Resource Data"
}
- 状态码: `200 OK`(默认状态码)
  • 请求 /resource/2:
    • 响应体:
{
  "status": 404,
  "message": "资源未找到"
}
- 状态码: `200 OK`(默认状态码)

问题

  • 即使资源未找到,状态码仍然是 200 OK,这不符合 RESTful API 的设计规范。
  • 客户端无法通过状态码快速判断请求是否成功。

  1. ResponseEntity 的例子
package cn.yam.bloomfilter.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class ResourceController {

    @GetMapping("/resource/{id}")
    public ResponseEntity<Map<String, Object>> getResource(@PathVariable int id) {
        Map<String, Object> response = new HashMap<>();

        // 模拟资源查找
        if (id == 1) {
            response.put("data", "Resource Data");
            return new ResponseEntity<>(response, HttpStatus.OK);
        } else {
            response.put("status", 404);
            response.put("message", "资源未找到");
            return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
        }
    }
}

测试结果

  • 请求 /resource/1:
    • 响应体:
{
  "data": "Resource Data"
}
- 状态码: `200 OK`
  • 请求 /resource/2:
    • 响应体:
{
  "status": 404,
  "message": "资源未找到"
}
- 状态码: `404 Not Found`

优点

  • 状态码和响应体都符合 RESTful API 的设计规范。
  • 客户端可以通过状态码快速判断请求是否成功。

  1. 对比总结
特性**不加 **ResponseEntity**加 **ResponseEntity
状态码控制无法动态设置状态码,默认返回 200 OK可以动态设置状态码(如 200 OK404 Not Found)。
响应体可以返回自定义 JSON 数据。可以返回自定义 JSON 数据。
是否符合 RESTful 规范不符合,状态码无法反映实际错误。符合,状态码和响应体都能正确反映请求结果。
客户端处理客户端需要解析响应体才能判断是否出错。客户端可以通过状态码快速判断是否出错。

常见异常总结:

  1. 参数错误
// 访问的是http://localhost:8080/api/users/id
// id 默认是1-5 ,测试访问http://localhost:8080/api/users/999
  • 定义InvalidParameterException 异常类
package cn.yam.bloomfilter.exception;

public class InvalidParameterException extends RuntimeException {
    public InvalidParameterException(String message) {
        super(message);
    }
}
  • 在控制层抛出InvalidParameterException
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        if (user == null) {
            throw new InvalidParameterException("用户ID: " + id);
        }
        return ResponseEntity.ok(user);
    }
}
  • 在全局异常拦截类中拦截
package cn.yam.bloomfilter.exception;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Object handleAllExceptions(Exception ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.put("message", ex.getMessage());
        return response;
    }
    @ExceptionHandler(InvalidParameterException.class)
    public ResponseEntity<Map<String, Object>> handleInvalidParameterException(InvalidParameterException ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.BAD_REQUEST.value());
        response.put("message", "参数错误: " + ex.getMessage());
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }

}

  1. 路径匹配错误
// 访问的是http://localhost:8080/ap##??djjd
  • 补充 yml 配置
spring:
  mvc:
    throw-exception-if-no-handler-found: true
  web:
    resources:
      add-mappings: false

  1. 用来兜底处理所有未被特定异常处理器捕获的异常。
package cn.yam.bloomfilter.exception;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public Object handleAllExceptions(Exception ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.put("message", ex.getMessage());
        return response;
    }
}

标签:springboot,示例,springframework,public,ResponseEntity,org,import,全局,response
From: https://blog.csdn.net/web2u/article/details/145211451

相关文章