看完这篇,SpringBoot再也不用写try/catch了

前言

使用 SpringBoot 开发 Web 应用时,异常处理是必不可少的一部分。在应用中,异常可能会出现在任何地方,例如在控制器、服务层、数据访问层等等。如果不对异常进行处理,可能会导致应用崩溃或者出现未知的错误。因此,对于异常的处理是非常重要的。

本篇主要讲述在SpringBoot 中,如何用全局异常处理优雅的处理异常。

为什么要优雅的处理异常

如果我们不统一的处理异常,开发人员经常会在代码中东一块的西一块的写上 try catch代码块,长久以往容易堆积成屎山。

@Slf4j
@Api(value = "User Interfaces", tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * @param userParam user param
     * @return user
     */

    @ApiOperation("Add User")
    @ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.classrequired true)
    @PostMapping("add")
    public ResponseEntity<String> add(@Valid @RequestBody UserParam userParam) {
        // 每个接口都需要手动try catch
        try {
            // do something
        } catch(Exception e) {
            return ResponseEntity.fail("error");
        }
        return ResponseEntity.ok("success");
    }
}

那我们应该如何实现统一的异常处理呢?

使用 @ControllerAdvice + @ExceptionHandler注解

@ControllerAdvice 定义该类为全局异常处理类

@ExceptionHandler 定义该方法为异常处理方法。value 的值为需要处理的异常类的 class 文件。

首先自定义异常类 BusinessException :

/**
 * 业务异常类
 * @author rango
 */

@Data
public class BusinessException extends RuntimeException {
    private String code;
    private String msg;
 
    public BusinessException(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

然后编写全局异常类,用 @ControllerAdvice 注解:

/**
 * 全局异常处理器
 * @author rango
 */

@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
    /**
     * 处理 Exception 异常
     * @param httpServletRequest httpServletRequest
     * @param e 捕获异常
     * @return
     */

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity exceptionHandler(HttpServletRequest httpServletRequestException e
{
        logger.error("服务错误:", e);
        return new ResponseEntity("******""服务出错");
    }
 
    /**
     * 处理 BusinessException 异常
     * @param httpServletRequest httpServletRequest
     * @param e 捕获异常
     * @return
     */

    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public ResponseEntity businessExceptionHandler(HttpServletRequest httpServletRequestBusinessException e
{
        logger.info("业务异常报错!code:" + e.getCode() + "msg:" + e.getMsg());
        return new ResponseEntity(e.getCode(), e.getMsg());
    }
}

定义了全局异常处理器,项目就可以对不同的异常进行统一处理了。通常,为了使 controller 中不再使用任何 try/catch,会在 GlobalExceptionHandler 中对 Exception 做统一的拦截处理。这样其他没有用 @ExceptionHandler 配置的异常就都会统一被处理。

遇到异常时主动抛出异常

在业务中,遇到业务异常的地方,我们直接 throw 抛出对应的业务异常即可。如下所示

throw new BusinessException(ERROR_CODE, "用户账号/密码有误");

在 Controller 中的写法

Controller 中,不需要再写 try/catch,除非特殊场景。

@RequestMapping(value = "/test")
public ResponseEntity test() {
    ResponseEntity re = new ResponseEntity();
    // 业务处理
    return re;
}

结果展示

异常抛出后,返回如下结果。

{
    "code""E0014",
    "msg""用户账号/密码有误",
    "data"null
}

注意!!!

  • 抛出的异常如果被代码内的 try/catch 捕获了,就不会被 GlobalExceptionHandler 处理
  • 异步方法中的异常不会被全局异常处理(多线程)
  • 不是 controller 层抛出的异常才能被 GlobalExceptionHandler 处理,只要异常最后是从 contoller 层抛出去的都可以被捕获并处理

总结

本文介绍了使用 SpringBoot 时,如何通过配置全局异常处理器统一处理项目中的一些通用的异常,避免程序员不断的写try/catch导致的代码冗余,有利于代码的维护。

本文由 mdnice 多平台发布

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值