首先,我们需要在Spring Boot项目中添加全局异常处理器。具体步骤如下:
- 在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 创建一个ExceptionHandler类,用于捕获全局异常。代码如下:
@ControllerAdvice // 开启全局异常处理
public class ExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handleException(Exception ex) {
return new Result(ResultCode.EXCEPTION, ex.getMessage());
}
}
在上述代码中,@ControllerAdvice注解表示开启全局异常处理,@ExceptionHandler注解表示该方法用于捕获异常,@ResponseBody注解表示返回的是JSON数据,而不是视图。
- 自定义异常类。为了更好地处理业务异常,可以自定义一个异常类。代码如下:
public class BizException extends RuntimeException {
private Integer code;
public BizException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
public Integer getCode() {
return code;
}
}
在上述代码中,BizException类继承了RuntimeException类,用于表示业务异常,@code注解用于存储异常码,getMessage()方法用于获取异常信息。
- 抛出自定义异常。在代码中,如果需要抛出自定义异常,可以通过如下方式实现:
throw new BizException(ResultCodeEnum.USER_NOT_EXIST);
上述代码表示抛出一个业务异常,其异常码为USER_NOT_EXIST。
- 验证异常处理器是否起作用。可以在Controller中编写测试接口,通过发送错误请求等方式验证异常处理器是否捕获到异常,并正确返回异常信息。
在以上的步骤中,我们通过自定义异常和全局异常处理器搭配使用,能够更加优雅地处理全局异常。下面,我们通过两个例子进一步深入理解。
例子1:
假设我们有一个用户服务,其中有一个查询用户信息的接口。当输入的用户ID不合法时,我们希望返回一个业务异常。
- 首先,在result包下新建ResultCodeEnum类,用于枚举所有异常的类型和信息。
public enum ResultCodeEnum {
SUCCESS(200, "操作成功!"),
USER_NOT_EXIST(1001, "用户不存在!"),
PARAM_ERROR(1002, "参数错误!"),
AUTH_FAILED(1003, "认证失败!"),
EXCEPTION(9999, "系统异常,请稍后再试!");
private Integer code;
private String message;
ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
在上述代码中,我们枚举了所有异常的类型和信息,其中USER_NOT_EXIST代表“用户不存在”这个业务异常。
- 在BizException类中添加USER_NOT_EXIST异常。代码如下:
public class BizException extends RuntimeException {
private Integer code;
public BizException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
public Integer getCode() {
return code;
}
// 新增代码如下
public static void throwUserNotExistException() {
throw new BizException(ResultCodeEnum.USER_NOT_EXIST);
}
}
在上述代码中,我们添加了一个静态方法throwUserNotExistException(),用于抛出“用户不存在”这个业务异常。
- 在UserController中添加查询用户信息的接口。若用户ID不存在,我们将抛出USER_NOT_EXIST异常。代码如下:
@PostMapping("/getUserInfo")
@ResponseBody
public Result getUserInfo(@RequestParam("userId") Integer userId) {
// 查询用户信息,如果不存在则抛出USER_NOT_EXIST异常
if (user == null) {
BizException.throwUserNotExistException();
}
// 业务逻辑处理...
return Result.success();
}
从上述代码中,我们可以看到,当参数不合法时,会抛出“用户不存在”这个业务异常。
- 最后,在ExceptionHandler类中捕获这个业务异常。代码如下:
@ExceptionHandler(BizException.class)
@ResponseBody
public Result handleBizException(BizException ex) {
return new Result(ex.getCode(), ex.getMessage());
}
从上述代码中,我们可以看到,当捕获到业务异常时,会将异常码和异常信息返回给前端。
例子2:
假设我们有一个购物车服务,其中有一个添加商品到购物车的接口。当商品库存不足时,我们希望返回一个业务异常。
- 首先,在result包下新建ResultCodeEnum类,用于枚举所有异常的类型和信息。代码如下:
public enum ResultCodeEnum {
SUCCESS(200, "操作成功!"),
PRODUCT_NOT_ENOUGH(2001, "商品库存不足!"),
PARAM_ERROR(2002, "参数错误!"),
AUTH_FAILED(2003, "认证失败!"),
EXCEPTION(9999, "系统异常,请稍后再试!");
private Integer code;
private String message;
ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
在上述代码中,我们枚举了所有异常的类型和信息,其中PRODUCT_NOT_ENOUGH代表“商品库存不足”这个业务异常。
- 在BizException类中添加PRODUCT_NOT_ENOUGH异常。代码如下:
public class BizException extends RuntimeException {
private Integer code;
public BizException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
public Integer getCode() {
return code;
}
// 新增代码如下
public static void throwProductNotEnoughException() {
throw new BizException(ResultCodeEnum.PRODUCT_NOT_ENOUGH);
}
}
在上述代码中,我们添加了一个静态方法throwUserNotExistException(),用于抛出“商品库存不足”这个业务异常。
- 在CartController中添加添加商品到购物车的接口。若商品库存不足,我们将抛出PRODUCT_NOT_ENOUGH异常。代码如下:
@PostMapping("/addProduct")
@ResponseBody
public Result addProduct(@RequestParam("productId") Integer productId, @RequestParam("count") Integer count) {
// 判断商品库存是否充足
if (product.getCount() < count) {
BizException.throwProductNotEnoughException();
}
// 业务逻辑处理...
return Result.success();
}
从上述代码中,我们可以看到,当商品库存不足时,会抛出“商品库存不足”这个业务异常。
- 最后,在ExceptionHandler类中捕获这个业务异常。代码如下:
@ExceptionHandler(BizException.class)
@ResponseBody
public Result handleBizException(BizException ex) {
return new Result(ex.getCode(), ex.getMessage());
}
从上述代码中,我们可以看到,当捕获到业务异常时,会将异常码和异常信息返回给前端。
总的来说,为了优雅地实现全局异常处理,我们应该按以下步骤操作:添加异常枚举类、添加自定义异常、添加全局异常处理器、根据业务需求抛出自定义异常、在ExceptionHandler类中捕获这些异常,并向前端返回正确的异常信息。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot优雅地实现全局异常处理的方法详解 - Python技术站