springboot的异常统一管理

这篇文章主要介绍了Spring注解@RestControllerAdvice原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

前言

前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice。现在把此注解的用法总结一下。

用法

首先定义返回对象ResponseDto

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

package com.staff.points.common;

 

import lombok.Data;

 

import java.io.Serializable;

 

@Data

public class ResponseDto<T> implements Serializable {

  private static final long serialVersionUID = -284719732991678911L;

 

  private String code;

 

  private String message;

 

  private T data;

 

  public static <T> ResponseDto<T> assemblingSuccessResponse(T data) {

    ResponseDto<T> responseDto = new ResponseDto<>();

    responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());

    responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());

    responseDto.setData(data);

    return responseDto;

  }

 

  public static <T> ResponseDto<T> assemblingSuccessResponse() {

    ResponseDto<T> responseDto = new ResponseDto<>();

    responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());

    responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());

    responseDto.setData(null);

    return responseDto;

  }

 

  public static <T> ResponseDto<T> assemblingFailureResponse(ResponseCodeEnum data) {

    ResponseDto<T> responseDto = new ResponseDto<>();

    responseDto.setCode(data.FAILURE.getCode());

    responseDto.setMessage(data.FAILURE.getMessage());

    return responseDto;

  }

 

  public static <T> ResponseDto<T> assemblingFailureResponse() {

    ResponseDto<T> responseDto = new ResponseDto<>();

    responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());

    responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());

    return responseDto;

  }

}

然后定义返回码的枚举类,此处只定义了两种,有需要可以往下添加很多。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package com.staff.points.common;

 

import lombok.AllArgsConstructor;

import lombok.Getter;

 

@AllArgsConstructor

@Getter

public enum ResponseCodeEnum {

  SUCCESS("00", "成功"),

  FAILURE("01", "系统异常");

 

 

  private String code;

  private String message;

}

下面是自定义的异常类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package com.staff.points.common;

 

import lombok.Data;

 

@Data

public class StaffPointsException extends RuntimeException{

  private String code;

  private String message;

  public StaffPointsException () {}

 

  public StaffPointsException (Exception e) {

    super(e);

  }

 

  public StaffPointsException (String code, String message) {

    super(message);

    this.code = code;

    this.message = message;

  }

 

  public StaffPointsException (ResponseCodeEnum codeEnum) {

    super(codeEnum.getMessage());

    this.code = codeEnum.getCode();

    this.message = codeEnum.getMessage();

  }

}

然后是关键的@RestControllerAdvice修饰的类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

package com.staff.points.exception;

 

import com.staff.points.common.ResponseCodeEnum;

import com.staff.points.common.ResponseDto;

import com.staff.points.common.StaffPointsException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.bind.annotation.RestControllerAdvice;

 

@RestControllerAdvice

@Component

public class UnifyExceptionHandler {

  private Logger logger = LoggerFactory.getLogger(UnifyExceptionHandler.class);

 

  @ExceptionHandler(Exception.class)

  public ResponseDto handlerCommonException (Exception e) {

    ResponseDto responseDto = new ResponseDto<>();

    responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());

    responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());

    logger.info("UnifyExceptionHandler.handlerCommonException exception:" + e);

    return responseDto;

  }

  // 报StaffPointException时,对其进行拦截并处理的方法

  @ExceptionHandler(StaffPointsException.class)

  public ResponseDto handlerCustomizeException (StaffPointsException e) {

    ResponseDto responseDto = new ResponseDto<>();

    responseDto.setCode(e.getCode());

    responseDto.setMessage(e.getMessage());

    logger.info("UnifyExceptionHandler.handlerCustomizeException StaffPointsException:" + e);

    return responseDto;

  }

}

运行代码时,如果出现了StaffPointException,那么就会被拦截进入第27行的方法(就是说可以自由的在业务代码里往外throw自定义异常了);如果出现了其他的异常,则进入18行的方法,统一返回。

验证一下,在代码里造一个NPE异常时,返回结果:

1

2

3

4

5

{

 "code": "01",

 "message": "系统异常",

 "data": null

}

造一个StaffPointsException异常时,返回结果:

1

2

3

4

5

{

 "code": "99",

 "message": "自定义业务异常",

 "data": null

}

它的作用原理,大体是先在spring初始化时将类扫描进容器,出异常后,在DispatcherServlet类的doDispatch方法中调用了对异常的拦截处理。

小结

看@RestControllerAdvice源码可以知道,它就是@ControllerAdvice和@ResponseBody的合并。此注解通过对异常的拦截实现的统一异常返回处理,如果大家在项目中有类似的需求,不妨试一下,好用又方便。

#@Le.Hao#

帮助到您请点赞关注收藏谢谢!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Spring Boot中,可以使用AOP(面向切面编程)来实现统一异常处理。下面是一个简单的示例: 首先,在你的Spring Boot项目中创建一个全局异常处理类,例如 `GlobalExceptionHandler`。 ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { // 处理异常逻辑 // 返回自定义的异常信息 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("发生异常,请联系管理员"); } } ``` 在上面的代码中,我们使用了 `@ControllerAdvice` 注解来标识全局异常处理类,并使用 `@ExceptionHandler` 注解来指定处理的异常类型。 接下来,我们需要在Spring Boot应用程序的入口类上添加 `@EnableAspectJAutoProxy` 注解以启用AOP功能。 ```java @SpringBootApplication @EnableAspectJAutoProxy public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` 然后,创建一个切面类来捕获所有被 `@Controller` 或 `@RestController` 注解标识的类中抛出的异常,并将其委托给全局异常处理类进行处理。 ```java @Aspect @Component public class ExceptionAspect { @Autowired private GlobalExceptionHandler globalExceptionHandler; @Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)") public void controllerPointcut() {} @AfterThrowing(pointcut = "controllerPointcut()", throwing = "ex") public Object handleException(JoinPoint joinPoint, Exception ex) throws Throwable { return globalExceptionHandler.handleException(ex); } } ``` 在上面的代码中,我们使用 `@Aspect` 注解标识该类为切面类,并使用 `@Component` 注解将其作为Spring组件进行管理。 通过 `@Pointcut` 注解指定切入点,我们选择了所有被 `@Controller` 或 `@RestController` 注解标识的类。 在 `@AfterThrowing` 注解中,我们指定了切入点为 `controllerPointcut()`,并指定了异常类型为 `Exception`,在方法中调用全局异常处理类的方法进行异常处理。 这样,当被 `@Controller` 或 `@RestController` 注解标识的类中抛出异常时,切面类会捕获到异常并委托给全局异常处理类进行处理。 这就是使用AOP实现Spring Boot统一异常处理的基本步骤。你可以根据自己的需求进行扩展和定制化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@lehao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值