欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 异常处理器深度解析与实践指南

异常处理器深度解析与实践指南

2025/5/9 10:23:04 来源:https://blog.csdn.net/2403_87845034/article/details/147784788  浏览:    关键词:异常处理器深度解析与实践指南

SpringMVC-异常处理器

Spring MVC 异常处理器是处理 Spring MVC 应用中发生的异常的机制

一、异常处理的核心价值

  1. 系统健壮性保障

    • 防止未处理异常导致服务崩溃

    • 避免敏感信息泄露(如数据库连接信息)

    • 确保关键业务逻辑的容错能力

  2. 可观测性提升

    • 统一的错误日志格式

    • 精准的错误分类统计

    • 完整的调用链追踪支持

  3. 开发效率优化

    • 减少重复的错误处理代码

    • 规范化的错误响应格式

    • 明确的错误定位指引


二、异常体系设计规范

  1. 异常分类标准

    异常类型错误码范围典型场景处理策略
    系统异常50xxx数据库连接失败、Redis超时报警+自动恢复
    参数校验异常60xxx手机号格式错误、必填项缺失前端提示重填
    业务规则异常61xxx库存不足、订单状态冲突引导用户修正操作
    权限认证异常62xxx未登录访问、接口权限不足跳转登录页/提示升级权限
    第三方服务异常70xxx支付接口超时、短信服务失败降级处理+异步重试

 


三、异常处理器方法注解

  • @ControllerAdvice:用于定义一个全局的异常处理类。它可以标注在一个类上,表明该类是一个处理控制器层异常的切面类。使用这个注解后,该类中的异常处理方法可以应用到所有被 @RequestMapping 注解标注的方法上。
  • @ExceptionHandler:用于标注在方法上,指定该方法用来处理特定类型的异常。它可以在 @ControllerAdvice 类中使用,也可以在单个控制器类中使用。当指定的异常类型发生时,Spring MVC 会调用被该注解标注的方法来处理异常。

 


四、出现异常现象的常见位置与常见诱因

  • 数据绑定阶段
    • 诱因:当客户端发送的数据与服务器端期望的数据类型不匹配时,就会发生数据绑定异常。例如,客户端发送一个字符串类型的数据,而服务器端期望接收一个整数类型的数据。
    • 示例:在表单提交中,用户输入了非数字字符,而后台需要将该字段解析为整数。
  • 业务逻辑执行阶段
    • 诱因:业务逻辑中可能会出现各种异常,如违反业务规则、数据库操作失败等。例如,在进行用户注册时,用户名已经存在,这就违反了业务规则。
    • 示例:在保存订单时,数据库突然出现连接问题,导致订单数据无法插入到数据库中。
  • 控制器方法调用阶段
    • 诱因:控制器方法在执行过程中可能会抛出各种异常,如空指针异常、数组越界异常等。这可能是由于代码逻辑不完善或者参数传递不正确导致的。
    • 示例:控制器方法中调用了一个可能返回空值的服务方法,而没有进行空值判断,导致后续操作出现空指针异常。

项目异常处理方案

  • 全局异常处理:通过使用 @ControllerAdvice 和 @ExceptionHandler 注解,可以创建一个全局的异常处理器,统一处理所有控制器中抛出的异常。这样可以将异常处理逻辑集中在一个地方,便于维护和管理。
  • 局部异常处理:在单个控制器类中,也可以使用 @ExceptionHandler 注解来处理该控制器中特定的异常。这种方式适用于某些控制器有特殊的异常处理需求,不适合全局处理的情况。
  • 自定义异常处理:可以根据项目的业务需求,自定义异常类型。例如,定义一个 BusinessException 来表示业务逻辑上的异常,然后在异常处理器中对自定义异常进行特殊处理,返回给客户端特定的错误信息和状态码。

五、异常处理器结构示例 

自定义异常(BusinessException SystemException)

  • 定义异常:在自定义异常类中,可以定义一个异常编码字段,用于表示不同类型的异常。例如:
package com.weilai.controller.exceptionHandler;public class BusinessException extends RuntimeException {private final Integer errorCode;private final String errorMessage;public BusinessException(Integer errorCode, String errorMessage) {super(errorMessage);this.errorCode = errorCode;this.errorMessage = errorMessage;}// Getterspublic Integer getErrorCode() {return errorCode;}public String getErrorMessage() {return errorMessage;}
}
package com.weilai.controller.exceptionHandler;public class SystemException extends RuntimeException {private final Integer errorCode;private final String errorMessage;public SystemException(Integer errorCode, String errorMessage, Throwable cause) {super(errorMessage, cause);this.errorCode = errorCode;this.errorMessage = errorMessage;}// Getterspublic Integer getErrorCode() {return errorCode;}public String getErrorMessage() {return errorMessage;}
}

异常编码 (Code)

package com.weilai.controller.exceptionHandler;/*** 全局异常错误码定义(按模块分类)*/
public class Code {//------------------------ 系统级错误(50xxx)------------------------/** 系统未知错误(如未明确捕获的异常) */public static final Integer SYSTEM_UNKNOW_ERROR = 50001;/** 系统超时错误(如接口响应超时) */public static final Integer SYSTEM_TIMEOUT_ERROR = 50002;/** 数据库错误(如连接失败、SQL异常) */public static final Integer SYSTEM_DB_ERROR = 50011;/** 网络通信错误(如HTTP调用失败) */public static final Integer SYSTEM_NETWORK_ERROR = 50021;/** 第三方服务异常(如微信支付接口错误) */public static final Integer SYSTEM_THIRD_PARTY_ERROR = 50031;/** 配置文件错误(如缺失必要配置) */public static final Integer SYSTEM_CONFIG_ERROR = 50041;/** 文件IO异常(如读写文件失败) */public static final Integer SYSTEM_IO_ERROR = 50051;/** 数据格式错误(如JSON解析失败) */public static final Integer SYSTEM_DATA_FORMAT_ERROR = 50061;/** 权限不足(如系统资源访问被拒绝) */public static final Integer SYSTEM_ACCESS_DENIED = 50071;/** 资源不足(如内存溢出、线程池耗尽) */public static final Integer SYSTEM_RESOURCE_EXHAUSTED = 50081;/** 加密/解密异常(如AES解密失败) */public static final Integer SYSTEM_ENCRYPTION_ERROR = 50091;/** 序列化/反序列化错误(如Redis缓存数据转换失败) */public static final Integer SYSTEM_SERIALIZATION_ERROR = 50101;//------------------------ 项目级错误(60xxx)------------------------/** 参数校验失败(如@Valid校验不通过) */public static final Integer PROJECT_VALIDATE_ERROR = 60001;/** 业务逻辑异常(如用户余额不足) */public static final Integer PROJECT_BUSINESS_ERROR = 60002;/** 数据重复(如唯一键冲突) */public static final Integer PROJECT_DATA_DUPLICATE = 60011;/** 数据状态冲突(如订单已支付无法取消) */public static final Integer PROJECT_STATE_CONFLICT = 60021;/** 用户权限不足(如非管理员操作) */public static final Integer PROJECT_ACCESS_DENIED = 60031;/** 数据不存在(如查询ID不存在) */public static final Integer PROJECT_DATA_NOT_FOUND = 60041;/** 操作限制(如频繁调用接口) */public static final Integer PROJECT_OPERATION_LIMIT = 60051;/** 依赖服务异常(如内部微服务不可用) */public static final Integer PROJECT_DEPENDENCY_ERROR = 60061;/** 版本冲突(如乐观锁更新失败) */public static final Integer PROJECT_VERSION_CONFLICT = 60071;/** 流程错误(如审批流程未按顺序执行) */public static final Integer PROJECT_WORKFLOW_ERROR = 60081;

全局异常处理器 (GlobalExceptionHandler)

  • 全局异常处理器中使用异常编码:在异常处理器方法中,可以根据异常的编码来返回不同的响应信息。
1.生成专门的error页面返回异常信息 
package com.weilai.controller.exceptionHandler;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;@ControllerAdvice
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);// 统一构建错误视图private ModelAndView buildErrorView(Integer errorCode, String message, HttpStatus status, HttpServletRequest request) {ModelAndView mav = new ModelAndView("errorView");mav.addObject("errorCode", errorCode != null ? errorCode : status.value());mav.addObject("errorMessage", message);mav.addObject("timestamp", System.currentTimeMillis());mav.addObject("path", request.getRequestURI());mav.setStatus(status);return mav;}// 处理业务异常@ExceptionHandler(BusinessException.class)public ModelAndView handleBusinessException(BusinessException ex, HttpServletRequest request) {return buildErrorView(ex.getErrorCode(), ex.getErrorMessage(), HttpStatus.BAD_REQUEST, request);}// 处理系统异常@ExceptionHandler(SystemException.class)public ModelAndView handleSystemException(SystemException ex, HttpServletRequest request) {logger.error("系统异常 [code={}, path={}]", ex.getErrorCode(), request.getRequestURI(), ex);return buildErrorView( ex.getErrorCode(), ex.getErrorMessage(), HttpStatus.INTERNAL_SERVER_ERROR, request);}// 处理参数校验异常@ExceptionHandler(MethodArgumentNotValidException.class)public ModelAndView handleValidationException(MethodArgumentNotValidException ex) {BindingResult result = ex.getBindingResult();List<String> errors = result.getFieldErrors().stream().map(f -> f.getField() + ": " + f.getDefaultMessage()).collect(Collectors.toList());ModelAndView mav = buildErrorView( Code.PROJECT_VALIDATE_ERROR, "参数校验失败", HttpStatus.BAD_REQUEST, null);mav.addObject("errors", errors);return mav;}// 处理404异常@ExceptionHandler(NoHandlerFoundException.class)public ModelAndView handleNotFound(NoHandlerFoundException ex, HttpServletRequest request) {return buildErrorView(Code.PROJECT_DATA_NOT_FOUND, "资源不存在", HttpStatus.NOT_FOUND, request);}// 处理全局未分类异常(其他异常)@ExceptionHandler(Exception.class)public ModelAndView handleGlobalException(Exception ex, HttpServletRequest request) {// 常见系统异常分类if (ex instanceof NullPointerException) {return handleSystemException(new SystemException(Code.SYSTEM_UNKNOWN_ERROR, "空指针异常", ex),request);} else if (ex instanceof IllegalArgumentException) {return handleSystemException(new SystemException(Code.PROJECT_VALIDATE_ERROR, "非法参数", ex),request);}logger.error("未捕获异常 [path={}]", request.getRequestURI(), ex);return buildErrorView( Code.SYSTEM_UNKNOWN_ERROR, "系统繁忙,请稍后重试", HttpStatus.INTERNAL_SERVER_ERROR, request);}
}

这段代码定义了一个名为 GlobalExceptionHandler 的全局异常处理类,使用了 Spring 的 @ControllerAdvice 注解,其作用是对整个 Spring MVC 应用中控制器抛出的异常进行统一处理,增强了应用的健壮性和可维护性。下面是对代码的详细总结:

主要功能概述

  1. 日志记录:借助 SLF4J 框架记录各类异常信息,便于后续问题排查与系统监控。
  2. 统一错误视图构建buildErrorView 方法可构建包含错误码、错误消息、时间戳、请求路径等信息的错误视图,确保异常处理结果的一致性。
  3. 多类型异常处理
    • 业务异常(BusinessException:针对业务逻辑层面的异常,返回 HttpStatus.BAD_REQUEST 状态码。
    • 系统异常(SystemException:处理系统层面的异常,记录详细日志并返回 HttpStatus.INTERNAL_SERVER_ERROR 状态码。
    • 参数校验异常(MethodArgumentNotValidException:当请求参数校验失败时,收集错误信息并返回 HttpStatus.BAD_REQUEST 状态码。
    • 404 异常(NoHandlerFoundException:若请求的资源不存在,返回 HttpStatus.NOT_FOUND 状态码。
    • 全局未分类异常(Exception:对于其他未明确归类的异常,进一步细分处理,如 NullPointerException 和 IllegalArgumentException,最终统一返回 HttpStatus.INTERNAL_SERVER_ERROR 状态码。

代码结构分析

  • 类定义:使用 @ControllerAdvice 注解,将 GlobalExceptionHandler 类标记为全局异常处理类。
  • 日志记录:定义了 Logger 对象,用于记录异常信息。
  • 方法说明
    • buildErrorView:封装错误信息到 ModelAndView 对象,方便返回给前端。
    • handleBusinessException:处理业务异常,调用 buildErrorView 方法生成错误视图。
    • handleSystemException:处理系统异常,记录错误日志并调用 buildErrorView 方法。
    • handleValidationException:处理参数校验异常,收集校验错误信息并添加到错误视图中。
    • handleNotFound:处理 404 异常,调用 buildErrorView 方法返回资源不存在的错误视图。
    • handleGlobalException:处理其他未分类异常,对常见异常进行分类处理,最终统一处理并记录日志。

2.在当前页面返回异常信息
package com.weilai.controller.exceptionHandler;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;@ControllerAdvice
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);// 处理业务异常@ExceptionHandler(BusinessException.class)public ModelAndView handleBusinessException(BusinessException ex,HttpServletRequest request,RedirectAttributes redirectAttributes) {// 记录警告日志(业务异常通常不需要记录错误级别)logger.warn("业务异常 [code={}, path={}] {}",ex.getErrorCode(),request.getRequestURI(),ex.getMessage());// 设置重定向属性redirectAttributes.addFlashAttribute("errorCode", ex.getErrorCode());redirectAttributes.addFlashAttribute("errorMessage", ex.getErrorMessage());// 获取来源页面并处理空指针String referer = getSafeReferer(request);return new ModelAndView("redirect:" + referer);}// 处理系统异常@ExceptionHandler(SystemException.class)public ModelAndView handleSystemException(SystemException ex,HttpServletRequest request,RedirectAttributes redirectAttributes) {// 记录错误日志(包含异常堆栈)logger.error("系统异常 [code={}, path={}]",ex.getErrorCode(),request.getRequestURI(),ex);// 设置重定向属性redirectAttributes.addFlashAttribute("errorCode", ex.getErrorCode());redirectAttributes.addFlashAttribute("errorMessage", "系统繁忙,请稍后再试");String referer = getSafeReferer(request);return new ModelAndView("redirect:" + referer);}// 处理参数校验异常@ExceptionHandler(MethodArgumentNotValidException.class)public ModelAndView handleValidationException(MethodArgumentNotValidException ex,HttpServletRequest request,RedirectAttributes redirectAttributes) {BindingResult result = ex.getBindingResult();List<String> errors = result.getFieldErrors().stream().map(f -> f.getField() + ": " + f.getDefaultMessage()).collect(Collectors.toList());// 记录校验失败详情logger.info("参数校验失败 [path={}] {}", request.getRequestURI(), errors);redirectAttributes.addFlashAttribute("errors", errors);redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_VALIDATE_ERROR);String referer = getSafeReferer(request);return new ModelAndView("redirect:" + referer);}// 处理404异常@ExceptionHandler(NoHandlerFoundException.class)public ModelAndView handleNotFound(NoHandlerFoundException ex,HttpServletRequest request,RedirectAttributes redirectAttributes) {logger.warn("404异常 [method={}, path={}]",ex.getHttpMethod(),ex.getRequestURL());redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_DATA_NOT_FOUND);redirectAttributes.addFlashAttribute("errorMessage", "请求的资源不存在");// 如果404页面是API请求,可以重定向到首页return new ModelAndView("redirect:/");}// 处理全局未分类异常@ExceptionHandler(Exception.class)public ModelAndView handleGlobalException(Exception ex,HttpServletRequest request,RedirectAttributes redirectAttributes) {// 特殊异常处理if (ex instanceof NullPointerException) {logger.error("空指针异常 [path={}]", request.getRequestURI(), ex);redirectAttributes.addFlashAttribute("errorCode", Code.SYSTEM_UNKNOWN_ERROR);redirectAttributes.addFlashAttribute("errorMessage", "系统内部错误");} else if (ex instanceof IllegalArgumentException) {logger.warn("非法参数异常 [path={}] {}", request.getRequestURI(), ex.getMessage());redirectAttributes.addFlashAttribute("errorCode", Code.PROJECT_VALIDATE_ERROR);redirectAttributes.addFlashAttribute("errorMessage", ex.getMessage());} else {logger.error("未捕获异常 [path={}]", request.getRequestURI(), ex);redirectAttributes.addFlashAttribute("errorCode", Code.SYSTEM_UNKNOWN_ERROR);redirectAttributes.addFlashAttribute("errorMessage", "系统繁忙,请稍后重试");}String referer = getSafeReferer(request);return new ModelAndView("redirect:" + referer);}// 安全获取Referer地址private String getSafeReferer(HttpServletRequest request) {String referer = request.getHeader("Referer");if (referer == null || referer.isEmpty()) {// 默认回退到应用根路径return request.getContextPath() + "/";}return referer;}
}

这段 Java 代码定义了一个名为 GlobalExceptionHandler 的全局异常处理类,使用 Spring 的 @ControllerAdvice 注解,它的作用是对 Spring MVC 应用中控制器抛出的各类异常进行统一处理,确保在不同异常情况下都能给用户友好的反馈。

主要功能概述

  1. 日志记录:利用 SLF4J 框架对不同类型的异常进行日志记录,针对业务异常记录警告日志,系统异常和未捕获异常记录错误日志,参数校验失败记录信息日志,便于后续的问题排查和系统监控。
  2. 异常分类处理
    • 业务异常(BusinessException:捕获业务逻辑层面的异常,记录警告日志,将异常的错误码和错误信息通过 RedirectAttributes 传递到重定向页面,并重定向到来源页面。
    • 系统异常(SystemException:处理系统层面的异常,记录详细的错误日志(包含异常堆栈),设置通用的错误提示信息,将错误码和信息传递到重定向页面,然后重定向到来源页面。
    • 参数校验异常(MethodArgumentNotValidException:当请求参数校验失败时,收集校验错误信息并记录日志,将错误信息和错误码传递到重定向页面,最后重定向到来源页面。
    • 404 异常(NoHandlerFoundException:针对请求的资源不存在的情况,记录警告日志,设置相应的错误码和错误信息,若为 API 请求则重定向到应用首页。
    • 全局未分类异常(Exception:对其他未明确归类的异常进行处理,根据异常类型进一步细分,如 NullPointerException 和 IllegalArgumentException,分别设置不同的错误信息,记录相应日志,最后重定向到来源页面。
  3. 安全获取来源页面:通过 getSafeReferer 方法安全地获取请求的来源页面(Referer 头),若来源页面为空则默认回退到应用根路径。

代码结构分析

  • 类定义:使用 @ControllerAdvice 注解将 GlobalExceptionHandler 标记为全局异常处理类。
  • 日志记录:定义 Logger 对象,用于记录不同级别的异常信息。
  • 异常处理方法:每个 @ExceptionHandler 注解标注的方法对应处理一种或一类异常,在方法内部进行日志记录、错误信息设置和页面重定向操作。
  • 辅助方法getSafeReferer 方法用于安全获取请求的来源页面,避免出现空指针异常。
核心区别说明
ModelAndView.addObject()RedirectAttributes.addFlashAttribute()
存储位置当前请求的 Model 中Session(临时存储,重定向后自动清除)
有效范围当前请求下一个请求(即重定向后的请求)
适用场景直接渲染视图时使用重定向场景下传递临时数据

 前端获取方式对比

原方案(使用 addObject)

<!-- 直接通过 Model 属性访问 -->
<div th:if="${errorCode}">Error Code: [[${errorCode}]]
</div>

新方案(使用 addFlashAttribute)

<!-- 通过 Flash Attribute 访问 -->
<div th:if="${#request.getAttribute('errorCode')}">Error Code: [[${errorCode}]]
</div><!-- 或更简洁的写法(推荐) -->
<div th:if="${errorCode}">Error Code: [[${errorCode}]]
</div>

六、手动抛出异常时机说明

需要明确几个方面:

 **全局异常处理器的作用**:自动捕获未被处理的异常,包括运行时异常和自定义异常。但有些情况下,开发者需要显式地抛出异常,以便异常处理器能够捕获并进行相应的处理。

**何时需要手动抛出异常**:比如在业务逻辑中,当遇到无效参数、权限不足、数据不存在等情况时,主动抛出对应的自定义异常,让异常处理器统一处理,而不是在每个地方都处理错误逻辑。

 **不抛出异常的情况**如果某个异常已经被try-catch块捕获并处理,那么异常处理器就不会再处理它。但如果开发者希望异常被全局处理器处理,就需要在catch块中重新抛出或直接不捕获。

不是所有异常都需要手动抛出。比如,像数据库操作失败导致的DataAccessException,可能由Spring框架自动抛出,但业务相关的异常需要手动抛出。

哪些情况下需要手动抛出异常,比如参数校验失败时抛出BusinessException,数据库操作异常时可能由框架抛出,但需要包装成SystemException。

在Service层抛出业务异常,在Controller层不处理异常,而是让全局处理器统一处理

在使用全局异常处理器的情况下,是否需要手动抛出异常取决于具体的业务场景和设计需求。以下是清晰的分类说明:

1. 需要手动抛出异常的场景

以下情况需要显式抛出异常,由全局异常处理器统一处理:

① 业务规则校验失败
// 用户注册时检查用户名重复
public void registerUser(String username) {if (userRepository.existsByUsername(username)) {throw new BusinessException(Code.PROJECT_DATA_DUPLICATE, "用户名已存在");}// ...其他逻辑
}
② 数据状态冲突
// 取消订单时检查状态
public void cancelOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new BusinessException(Code.PROJECT_DATA_NOT_FOUND, "订单不存在"));if (order.getStatus() == OrderStatus.PAID) {throw new BusinessException(Code.PROJECT_STATE_CONFLICT, "已支付订单不可取消");}// ...取消逻辑
}
③ 权限校验失败
// 管理员操作权限校验
public void adminOperation(User operator) {if (!operator.isAdmin()) {throw new BusinessException(Code.PROJECT_ACCESS_DENIED, "无管理员权限");}// ...操作逻辑
}

2. 不需要手动抛出的场景

以下情况框架会自动抛出异常,无需手动处理:

① 参数校验失败(@Valid)
// 使用@Valid自动触发校验
@PostMapping("/users")
public void createUser(@Valid @RequestBody UserDTO user) {// 如果参数校验失败,会自动抛出MethodArgumentNotValidExceptionuserService.create(user);
}
② 数据库操作异常
// Spring Data JPA 会抛出DataAccessException
@Transactional
public void updateProduct(Product product) {// 如果数据库操作失败(如唯一键冲突),会抛出DataAccessExceptionproductRepository.save(product); 
}
③ 框架级异常
  • NoHandlerFoundException(404)

  • HttpRequestMethodNotSupportedException(405)

  • TypeMismatchException(参数类型错误)


3. 最佳实践原则

场景处理方式
业务逻辑错误手动抛出BusinessException
基础设施错误手动包装SystemException(如捕获数据库异常后转换)
参数校验依赖@Valid+自动异常
权限校验在拦截器/切面中统一抛出异常
不可预知系统错误由全局异常处理器兜底处理(如空指针异常)

4. 为什么需要手动抛出?

  1. 明确错误语义
    通过自定义异常类型,明确区分错误类型(如PROJECT_DATA_DUPLICATE vs PROJECT_STATE_CONFLICT)。

  2. 统一错误处理
    避免每个Controller重复处理错误逻辑,通过全局异常处理器统一生成响应格式。

  3. 代码可读性
    异常抛出点直接反映业务逻辑的失败条件,代码意图更清晰。

  4. 错误传播控制
    在Service层抛出异常后,可以跨多层调用栈传递到Controller层,无需逐层返回错误码。


5. 错误处理流程示例


6. 常见问题解答

Q1:捕获异常后还需要抛出吗?
try {// 可能抛出DataAccessException的操作
} catch (DataAccessException e) {// 需要转换为系统异常后重新抛出throw new SystemException(Code.SYSTEM_DB_ERROR, "数据库操作失败", e);
}
Q2:如何避免过度抛出异常?
  • 校验前置:在参数进入业务逻辑前完成校验(如使用@Valid

  • 状态检查:通过返回OptionalResult对象处理非异常场景

  • 防御性编程:对可预见的错误使用条件判断而非依赖异常


通过合理的手动异常抛出与全局处理器的配合,可以实现:

  • ✅ 清晰的错误分类

  • ✅ 统一的错误响应格式

  • ✅ 业务逻辑与错误处理的解耦

  • ✅ 更易维护的代码结构

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词