抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Spring 异常处理三种方式

  1. @ExceptionHandler
  2. 实现HandlerExceptionResolver接口
  3. @ControllerAdvice+@ExceptionHandler

Spring异常处理

使用@ControllerAdvice+@ExceptionHandler全局处理异常

@ControllerAdvice 是一个Spring注解,它本质上是一个特殊类型的@Component。意味着当你使用

@ControllerAdvice 注解标记一个类时,Spring会将该类注册为一个Spring Bean,并将其纳入Spring应用程序

上下文中,使它能够被自动扫描和发现。

同时@ControllerAdvice 是基于Spring AOP(面向切面编程)的一种实现,默认情况下会对所有Controller进行拦

截,当你使用@ControllerAdvice注解标记一个类时,Spring将这个类视为一个AOP切面。这个切面的目的是捕获

Controller中抛出的异常,并在一个统一的地方进行处理。在@ControllerAdvice类中,你可以定义多个

@ExceptionHandler注解的方法,每个方法可以处理特定类型的异常。这些方法被视为AOP通知,它们织入到切

点(Controller方法抛出异常的地方)。

执行流程

  1. 当应用程序中的某个方法抛出异常时,Spring Boot会捕获该异常。
  2. Spring Boot会搜索在类路径下带有 @ControllerAdvice 注解的类。
  3. 在找到 @ControllerAdvice 类后,Spring Boot会查找该类中使用 @ExceptionHandler 注解标记的方法,以确定哪个方法能够处理抛出的异常。方法的参数应与异常类型匹配。
  4. 如果找到了匹配的 @ExceptionHandler 方法,Spring Boot会调用该方法,将抛出的异常传递给它。
  5. @ExceptionHandler 方法可以根据应用的需求执行自定义的异常处理逻辑,例如记录异常、生成响应、发送通知等。

实例

import com.heroxin.seckill.vo.RespBeanEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class GlobalException extends RuntimeException{
private RespBeanEnum respBeanEnum;
}
import com.heroxin.seckill.vo.RespBean;
import com.heroxin.seckill.vo.RespBeanEnum;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public RespBean ExceptionHandler(Exception e) {
if (e instanceof GlobalException) {
GlobalException ex = (GlobalException) e;
return RespBean.error(ex.getRespBeanEnum());
} else if (e instanceof BindException) {
BindException ex = (BindException) e;
RespBean respBean = RespBean.error(RespBeanEnum.BIND_ERROR);
respBean.setMessage("参数校验异常:" + ex.getAllErrors().get(0).getDefaultMessage());
return respBean;
}
return RespBean.error(RespBeanEnum.ERROR);
}
}

@Getter
@ToString
@AllArgsConstructor
public enum RespBeanEnum {

//通用
SUCCESS(200, "SUCCESS"),
ERROR(500, "服务端异常"),

//登录模块
LOGIN_ERROR(500210, "用户名或者密码不正确"),
MOBILE_ERROR(500211, "手机号码格式不正确"),
BIND_ERROR(500212, "参数校验异常"),
MOBILE_NOT_EXIST(500213, "手机号码不存在"),
PASSWORD_UPDATE_FAIL(500214, "更新密码失败"),
SESSION_ERROR(500215, "用户SESSION不存在"),


//秒杀模块
EMPTY_STOCK(500500, "库存不足"),
REPEATE_ERROR(500501, "该商品每人限购一件"),
REQUEST_ILLEGAL(500502, "请求非法,请重新尝试"),
ERROR_CAPTCHA(500503, "验证码错误,请重新输入"),
ACCESS_LIMIT_REACHED(500504, "访问过于频繁,请稍后重试"),
//订单模块5003xx
ORDER_NOT_EXIST(500300, "订单不存在"),
;

private final Integer code;
private final String message;

}
@Data
@NoArgsConstructor
public class RespBean {

private long code;
private String message;
private Object object;

public static RespBean success() {
return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), null);
}

public static RespBean success(Object object) {
return new RespBean(RespBeanEnum.SUCCESS.getCode(), RespBeanEnum.SUCCESS.getMessage(), object);
}

public static RespBean error(RespBeanEnum respBeanEnum) {
return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), null);
}

public static RespBean error(RespBeanEnum respBeanEnum, Object object) {
return new RespBean(respBeanEnum.getCode(), respBeanEnum.getMessage(), object);
}

public RespBean(long code, String message, Object object) {
this.code = code;
this.message = message;
this.object = object;
}
}

评论