当前位置: 首页 > news >正文

Spring 的 异常管理的相关注解@ControllerAdvice 和@ExceptionHandler

 @ControllerAdvice 和 @ExceptionHandler 是 Spring 框架中用于全局异常处理的关键注解,它们可以帮助你优雅地处理应用程序中抛出的异常,避免直接将错误信息暴露给用户。下面详细介绍这两个注解的作用和用法:

一、全局异常处理的作用

在 Spring 应用中,当控制器方法抛出异常时,默认会返回 HTTP 500 错误(Internal Server Error),这对用户体验和调试都不友好。全局异常处理可以:

统一错误响应格式:将不同类型的异常转换为标准化的 JSON 或 XML 格式返回给客户端。

隐藏敏感信息:避免直接暴露堆栈跟踪或数据库错误等内部信息。

提高可维护性:将异常处理逻辑集中管理,避免在每个控制器中重复编写。

二、核心注解解析

1. @ControllerAdvice

作用:标记一个类为全局异常处理器,它可以拦截所有控制器中抛出的异常。

使用方式:

@ControllerAdvice

public class GlobalExceptionHandler {

// 异常处理方法

}

特性:

可通过basePackages属性指定拦截特定包下的控制器。

可与@RestControllerAdvice(等价于@ControllerAdvice + @ResponseBody)替换使用。

2. @ExceptionHandler

作用:定义具体的异常处理方法,用于捕获并处理特定类型的异常。

使用方式:

java

@ExceptionHandler(ConstraintViolationException.class)

public ResponseEntity<ErrorResponse> handleValidationException(ConstraintViolationException ex) {

// 处理异常逻辑

}

特性:

可指定多个异常类(如@ExceptionHandler({Exception1.class, Exception2.class}))。

方法返回值可以是ResponseEntity、视图名称或直接返回对象(需配合@ResponseBody)。

三、示例:完善的全局异常处理器

下面是一个更完整的全局异常处理器示例,包含常见的异常类型处理:

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.validation.BindException;

import org.springframework.validation.FieldError;

import org.springframework.web.bind.MethodArgumentNotValidException;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.validation.ConstraintViolation;

import javax.validation.ConstraintViolationException;import java.util.HashMap;

import java.util.Map;

@ControllerAdvice

public class GlobalExceptionHandler {

    // 处理请求参数校验异常(@RequestBody参数)

    @ExceptionHandler(MethodArgumentNotValidException.class)

public ResponseEntity<Map<String, String>>

handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {

        Map<String, String> errors = new HashMap<>();

        ex.getBindingResult().getAllErrors().forEach((error) -> {

            String fieldName = ((FieldError) error).getField();

            String errorMessage = error.getDefaultMessage();

            errors.put(fieldName, errorMessage);

        });

        return ResponseEntity.badRequest().body(errors);

    }

    // 处理请求参数校验异常(@PathVariable和@RequestParam参数)

    @ExceptionHandler(ConstraintViolationException.class)

    public ResponseEntity<Map<String, String>> handleConstraintViolation(ConstraintViolationException ex) {

        Map<String, String> errors = new HashMap<>();

        ex.getConstraintViolations().forEach((violation) -> {

            String propertyPath = violation.getPropertyPath().toString();

            String errorMessage = violation.getMessage();

            errors.put(propertyPath, errorMessage);

        });

        return ResponseEntity.badRequest().body(errors);

    }

    // 处理BindException(表单数据绑定错误)

    @ExceptionHandler(BindException.class)

    public ResponseEntity<Map<String, String>> handleBindException(BindException ex) {

        Map<String, String> errors = new HashMap<>();

        ex.getBindingResult().getFieldErrors().forEach((error) -> {

            errors.put(error.getField(), error.getDefaultMessage());

        });

        return ResponseEntity.badRequest().body(errors);

    }

    // 处理其他未明确捕获的异常

    @ExceptionHandler(Exception.class)

    public ResponseEntity<Map<String, String>> handleGeneralException(Exception ex) {

        Map<String, String> error = new HashMap<>();

        error.put("message", "Internal Server Error");

        error.put("details", ex.getMessage());

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);

}

}

四、异常处理方法详解

1. MethodArgumentNotValidException

触发场景:当@RequestBody参数校验失败时抛出。

处理逻辑:提取字段错误信息,返回 HTTP 400(Bad Request)。

2. ConstraintViolationException

触发场景:当@PathVariable或@RequestParam参数校验失败时抛出。

处理逻辑:提取路径变量 / 请求参数的错误信息,返回 HTTP 400。

3. BindException

触发场景:当表单数据绑定时校验失败(如@ModelAttribute参数)。

处理逻辑:提取表单字段的错误信息,返回 HTTP 400。

4. 通用异常处理

触发场景:捕获所有未被明确处理的异常(如数据库异常、空指针等)。

处理逻辑:返回 HTTP 500(Internal Server Error),隐藏敏感信息。

五、自定义错误响应格式

为了统一 API 返回格式,通常会定义一个标准的错误响应类:

public class ErrorResponse {

    private int status;

    private String message;

    private Map<String, String> details;

    private long timestamp;

// 构造方法、getter和setter

}

修改异常处理方法,返回自定义格式:

@ExceptionHandler(MethodArgumentNotValidException.class)

public ResponseEntity<ErrorResponse>

handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {

    Map<String, String> errors = new HashMap<>();

    ex.getBindingResult().getAllErrors().forEach((error) -> {

        errors.put(((FieldError) error).getField(), error.getDefaultMessage());

    });

    

    ErrorResponse response = new ErrorResponse(

        HttpStatus.BAD_REQUEST.value(),

        "Validation Failed",

        errors,

        System.currentTimeMillis()

    );

    

return ResponseEntity.badRequest().body(response);

}

六、总结

通过@ControllerAdvice和@ExceptionHandler,可以实现:

集中异常处理:将所有异常处理逻辑放在一个类中。

自定义错误响应:根据不同异常类型返回标准化的错误格式。

提升用户体验:避免直接暴露原始异常信息给客户端。

在实际项目中,建议根据业务需求扩展更多异常处理方法,如处理数据库异常(DataAccessException)、认证异常(AuthenticationException)等。同时,可以结合国际化资源文件(message.properties)实现多语言错误提示。

http://www.xdnf.cn/news/453781.html

相关文章:

  • 2011-2019年各省总抚养比数据
  • 【GESP真题解析】第 5 集 GESP一级 2023 年 3 月编程题 2:长方形面积
  • Python实例题:Python抓取相亲网数据
  • Maplibgre-gl 学习1 初识
  • leetcode刷题日记——旋转链表
  • 深入理解Java HotSpot中的即时编译
  • 规控算法分类
  • 【Vue.js 的核心魅力:深入理解声明式渲染】
  • 学习黑客NFC技术详解
  • 互联网协议的多路复用、Linux系统的I/O模式
  • 【FileZilla】sftp协议的数据传输上传和下载
  • 软考软件设计师中级——软件工程笔记
  • QT---信号与槽
  • scons user 3.1.2
  • hls 的使用方式
  • ICML-2024《Image Clustering with External Guidance》
  • PADS入门笔记【一】
  • 基于etcd的分布式任务调度系统:设计、实现与实战经验
  • CS016-2-unity ecs
  • 计算机系统结构——Cache性能分析
  • 苹果处理器“仿生“命名背后的营销策略与技术创新
  • 【ROS2】报错记录及对应解决方案
  • Open3D 体素化下采样
  • 当DeepSeek遇上百年医院:解码AI医疗落地实践
  • 香橙派/树莓派读取GY39数据
  • Spring Boot 日志
  • 仿真每日一练 | 多刚体动力学分析中的自由度问题
  • 领麦微红外温度传感器:发面机非接触测温
  • AI短期学习计划(持续完善更新)
  • 基于CETOL 6σ的生产不良判定与故障分析技术应用