Spring 异常处理三种方式
- @ExceptionHandler
- 实现HandlerExceptionResolver接口
- @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方法抛出异常的地方)。
执行流程
- 当应用程序中的某个方法抛出异常时,Spring Boot会捕获该异常。
- Spring Boot会搜索在类路径下带有
@ControllerAdvice
注解的类。
- 在找到
@ControllerAdvice
类后,Spring Boot会查找该类中使用 @ExceptionHandler
注解标记的方法,以确定哪个方法能够处理抛出的异常。方法的参数应与异常类型匹配。
- 如果找到了匹配的
@ExceptionHandler
方法,Spring Boot会调用该方法,将抛出的异常传递给它。
@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, "访问过于频繁,请稍后重试"), 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; } }
|