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

SpringBoot分层架构下业务逻辑如何合理使用异常:抛异常还是返回null?

SpringBoot业务验证:抛异常还是返回null?

核心结论

绝对不要返回null,应该抛出自定义业务异常。

为什么不选返回null?

  • 返回null无法传递任何失败细节,Controller层只能知道“操作失败”,但无法明确是参数错误、库存不足还是权限问题,没法给前端返回精准的错误提示。
  • 后续维护时,其他开发者完全无法从null判断失败场景,还容易引发空指针异常,大幅增加调试和维护成本。

关于“抛异常的性能顾虑”

所谓的性能问题属于过度担忧:业务验证不通过本身是异常场景(非高频发生),JVM对异常处理已经做了足够优化,只要不是在循环等高频逻辑中频繁抛异常,性能影响可以忽略不计,远比不上代码可读性、可维护性的价值。


业务逻辑中合理使用异常的原则

  1. 只在异常场景抛异常:异常是用来处理“不符合业务规则的异常情况”,比如用户输入非法、库存不足,这类可预见但不符合正常流程的场景,用自定义异常传递信息;正常流程(比如查询结果为空但业务允许)则返回空集合或Optional,不用异常。
  2. 自定义业务异常类:不要直接抛RuntimeException,要定义专属的业务异常(比如BusinessException),包含错误码、错误信息字段,让上层能精准识别错误类型。
  3. 全局统一处理异常:用Spring的@RestControllerAdvice+@ExceptionHandler实现全局异常捕获,避免每个Controller都写重复的try-catch代码,简化逻辑。
  4. 异常信息要明确:抛出异常时,错误信息要清晰指向具体问题,比如“参数格式不符合要求”“库存不足无法下单”,方便前端展示和问题排查。

改造后的示例代码

自定义业务异常

public class BusinessException extends RuntimeException {
    private String errorCode;
    private String errorMsg;

    public BusinessException(String errorCode, String errorMsg) {
        super(errorMsg);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    // getter方法
    public String getErrorCode() { return errorCode; }
    public String getErrorMsg() { return errorMsg; }
}

Service层代码

@Service
public class BusinessService {
    public String business() {
        if (!checkConditions_1()) {
            throw new BusinessException("PARAM_ERROR", "参数格式不符合要求");
        }
        if (!checkConditions_2()) {
            throw new BusinessException("STOCK_NOT_ENOUGH", "库存不足");
        }
        if (!checkConditions_3()) {
            throw new BusinessException("PERMISSION_DENIED", "无操作权限");
        }
        // 执行正常业务逻辑
        return "success";
    }

    private boolean checkConditions_1() {
        // 具体验证逻辑
        return false;
    }

    private boolean checkConditions_2() {
        // 具体验证逻辑
        return false;
    }

    private boolean checkConditions_3() {
        // 具体验证逻辑
        return false;
    }
}

全局异常处理器

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Map<String, String>> handleBusinessException(BusinessException e) {
        Map<String, String> result = new HashMap<>();
        result.put("errorCode", e.getErrorCode());
        result.put("errorMsg", e.getErrorMsg());
        return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
    }
}

Controller层代码

@RestController
public class TestController {
    @Autowired
    private BusinessService businessService;

    @GetMapping("/test")
    public String testController() {
        return businessService.business();
    }
}

相关代码规范与书籍参考

代码规范

  • 阿里巴巴Java开发手册:明确规定“不要返回null,优先返回空集合或自定义异常”,对异常的使用场景、自定义异常的设计有清晰要求,是国内Java开发的通用规范。
  • Spring官方文档:推荐结合@RestControllerAdvice实现全局异常处理,给出了Spring生态下优雅处理业务异常的最佳实践。

书籍

  • 《Effective Java》:第6章专门讲解异常的正确使用原则,比如“只在异常条件下使用异常”“抛出与抽象对应的异常”等,是Java开发者的必读经典。
  • 《Spring实战》:包含Spring应用中异常处理的章节,结合实际业务场景讲解如何设计和处理异常,贴合SpringBoot开发需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:42:47