SpringBoot如何编写统一异常管理呢?

转自:

SpringBoot如何编写统一异常管理呢?

下文笔者讲述使用AOP实现统一异常管理的方法分享,如下所示

实现思路:
    1.引入AOP相应的jar包
	2.编写相应的异常类
	3.使用注解为编写exceptionhandler
	4.编写AOP拦截所有错误信息

引入相应的starter器

 
<!--spring切面aop依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

定义返回报文的格式

返回报文包含以下信息:

成功标志:是一个布尔值,用于表示是否运行正常
错误代码:使用整型作为标志位
错误信息:使用String作为错误信息的描述,留给前端是否展示给用户或者进入其他错误流程的使用。
结果集:在无错误信息的情况下所得到的正确数据信息。一般是个Map,前端根据Key取值 

例:
结果集定义方式

public class Result<T> {

   //    error_code 状态值:0 极为成功,其他数值代表失败
   private Integer status;

   //    error_msg 错误信息,若status为0时,为success
   private String msg;

   //    content 返回体报文的出参,使用泛型兼容不同的类型
   private T data;

   public Integer getStatus() {
       return status;
   }

   public void setStatus(Integer code) {
       this.status = code;
   }

   public String getMsg() {
       return msg;
   }

   public void setMsg(String msg) {
       this.msg = msg;
   }

   public T getData(Object object) {
       return data;
   }

   public void setData(T data) {
       this.data = data;
   }

   public T getData() {
       return data;
   }

   @Override
   public String toString() {
       return "Result{" +
               "status=" + status +
               ", msg='" + msg + '\'' +
               ", data=" + data +
               '}';
   }

定义一个枚举类用于设置代码和信息的关联

public enum ExceptionEnum {
    UNKNOW_ERROR(-1,"未知错误"),
    USER_NOT_FIND(-101,"用户不存在"),
;

    private Integer code;

    private String msg;

    ExceptionEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

统一返回的结果集工具类

public class ResultUtil {
    /**
     * 返回成功,传入返回体具体出參
     * @param object
     * @return
     */
    public static Result success(Object object){
        Result result = new Result();
        result.setStatus(0);
        result.setMsg("success");
        result.setData(object);
        return result;
    }

    /**
     * 提供给部分不需要出參的接口
     * @return
     */
    public static Result success(){
        return success(null);
    }

    /**
     * 自定义错误信息
     * @param code
     * @param msg
     * @return
     */
    public static Result error(Integer code,String msg){
        Result result = new Result();
        result.setStatus(code);
        result.setMsg(msg);
        result.setData(null);
        return result;
    }

    /**
     * 返回异常信息,在已知的范围内
     * @param exceptionEnum
     * @return
     */
    public static Result error(ExceptionEnum exceptionEnum){
        Result result = new Result();
        result.setStatus(exceptionEnum.getCode());
        result.setMsg(exceptionEnum.getMsg());
        result.setData(null);
        return result;
    }
}

异常类定义

public class DescribeException extends RuntimeException{

    private Integer code;

    /**
     * 继承exception,加入错误状态值
     * @param exceptionEnum
     */
    public DescribeException(ExceptionEnum exceptionEnum) {
        super(exceptionEnum.getMsg());
        this.code = exceptionEnum.getCode();
    }

    /**
     * 自定义错误信息
     * @param message
     * @param code
     */
    public DescribeException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

异常处理类封装

    @ControllerAdvice
    public class ExceptionHandle {

      private final static Logger LOGGER = LoggerFactory.getLogger(ExceptionHandle.class);

      /**
       * 判断错误是否是已定义的已知错误,不是则由未知错误代替,同时记录在log中
       * @param e
       * @return
       */
      @ExceptionHandler(value = Exception.class)
      @ResponseBody
      public Result exceptionGet(Exception e){
          if(e instanceof DescribeException){
              DescribeException MyException = (DescribeException) e;
              return ResultUtil.error(MyException.getCode(),MyException.getMessage());
          }

          LOGGER.error("【系统异常】{}",e);
          return ResultUtil.error(ExceptionEnum.UNKNOW_ERROR);
      }
    }
注意事项: 
    1.此处使用@ControllerAdvice注解
	  则Spring会加载该类
      并将所有捕获的异常统一返回结果Result这个实体
    2.此处的操作方式可捕捉类的异常,但如果接口出现异常
      则无法知道是谁调用了接口,所以此时我们需引入AOP

AOP捕捉异常

@Aspect
@Component
public class HttpAspect {

    private final static Logger LOGGER = LoggerFactory.getLogger(HttpAspect.class);

    @Autowired
    private ExceptionHandle exceptionHandle;

    @Pointcut("execution(public * com.java265.controller.*.*(..))")
    public void log(){

    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //url
        LOGGER.info("url={}",request.getRequestURL());
        //method
        LOGGER.info("method={}",request.getMethod());
        //ip
        LOGGER.info("id={}",request.getRemoteAddr());
        //class_method
        LOGGER.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
        //args[]
        LOGGER.info("args={}",joinPoint.getArgs());
    }

    @Around("log()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Result result = null;
        try {

        } catch (Exception e) {
            return exceptionHandle.exceptionGet(e);
        }
        if(result == null){
            return proceedingJoinPoint.proceed();
        }else {
            return result;
        }
    }

    @AfterReturning(pointcut = "log()",returning = "object")//打印输出结果
    public void doAfterReturing(Object object){
        LOGGER.info("response={}",object.toString());
    }
}
 以上代码将使用@Aspect来声明这是一个切面
   使用@Pointcut来定义切面所需要切入的位置
    此处AOP将对HTTP请求做一个切入
   在进入方法之前我们使用@Before记录了调用的接口URL,调用的方法,调用方的IP地址以及输入的参数等
   
	在整个接口代码运作期间
我们使用@Around来捕获异常信息,并用之前定义好的Result进行异常的返回
    最后我们使用@AfterReturning来记录我们的出參。
通过以上方法即可实现日志监控

例:

Controller示例编写

@RestController
@RequestMapping("/result")
public class ResultController {

    @Autowired
    private ExceptionHandle exceptionHandle;

    /**
     * 返回体测试
     * @param name
     * @param pwd
     * @return
     */
    @RequestMapping(value = "/getResult",method = RequestMethod.POST)
    public Result getResult(@RequestParam("name") String name, @RequestParam("pwd") String pwd){
        Result result = ResultUtil.success();
        try {
            if (name.equals("maomaojava265")){
                result =  ResultUtil.success(new UserInfo());
            }else if (name.equals("pzz")){
                result =  ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
            }else{
                int i = 1/0;
            }
        }catch (Exception e){
            result =  exceptionHandle.exceptionGet(e);
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以在Spring Boot中实现全局异常处理并捕获所有未处理的异常。常见的做法是创建一个ExceptionHandler类并使用@ControllerAdvice注释。在该类中,可以使用@ExceptionHandler注释来处理特定的异常类型,并在@ExceptionHandler方法中定义异常处理逻辑。如果发生异常没有被@ExceptionHandler处理,可以使用@ResponseStatus定义一个自定义的HTTP响应状态代码,如@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)。最后,将ExceptionHandler类包含在Spring Boot的主类中即可。 ### 回答2: 在Spring Boot中,可以通过以下方式设置全局异常处理: 1. 创建一个自定义的异常处理类,该类需要使用@ControllerAdvice注解进行标记。这个类可以包含多个异常处理方法,每个方法用来处理不同的异常类型。 ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { // 处理异常逻辑 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error"); } @ExceptionHandler(YourCustomException.class) public ResponseEntity<String> handleYourCustomException(YourCustomException ex) { // 处理自定义异常逻辑 return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Bad Request"); } } ``` 2. 在上面的异常处理类中,使用@ExceptionHandler注解标记每个处理方法。注解的参数指定要处理的异常类型。 3. 在处理方法中,可以根据具体的异常类型进行相应的处理逻辑。可以通过返回ResponseEntity对象来指定异常处理后返回的HTTP状态码和响应内容。 4. 在Spring Boot的配置文件application.properties(或application.yml)中,可以配置全局异常处理的相关配置,如是否显示异常详细信息、指定异常处理类等。 ```properties # application.properties server.error.include-stacktrace=always server.error.whitelabel.enabled=false ``` 上述配置可以让异常详细信息始终显示,并禁用Spring Boot默认的错误页面(Whitelabel Error Page)。 通过以上步骤,在Spring Boot中设置全局异常处理即可。当应用程序发生异常时,将会被自定义的异常处理类捕获并处理,最终返回自定义的异常信息给客户端。 ### 回答3: 在Spring Boot中设置全局异常处理可以通过以下几个步骤实现: 1. 创建一个异常处理类,可以命名为GlobalExceptionHandler。该类需要使用@ControllerAdvice注解进行标记,表示它是一个全局异常处理类。 2. 在GlobalExceptionHandler类中,可以定义一些方法来处理不同类型的异常。可以使用@ExceptionHandler注解来指定要处理的异常类型。在方法中编写异常处理的逻辑,比如返回一个自定义的错误信息、跳转到指定的错误页面等。 3. 需要注意的是,如果希望返回一个统一的错误结果,可以在方法的参数中添加一个HttpServletRequest对象或者一个包含HttpServletRequest的对象,比如ResponseEntityExceptionHandler。这样就可以使用该对象获取请求的信息,比如请求的URL、请求的方法等。 4. 最后,在GlobalExceptionHandler类中可以添加一些全局的异常处理方法,比如处理未捕获的其他异常,通过添加@ExceptionHandler(Exception.class)注解实现。 5. 将GlobalExceptionHandler类注册为一个Bean,可以使用@Configuration注解或者@Component注解进行标记,确保Spring Boot能够扫描到该类。 6. 在应用启动类中,通过使用@EnableWebMvc注解或者继承WebMvcConfigurerAdapter类,来启用MVC配置。这样,Spring Boot会自动识别并使用GlobalExceptionHandler类进行全局异常处理。 通过以上步骤,就可以在Spring Boot中设置全局异常处理。这样,在应用中发生异常时,就会执行GlobalExceptionHandler类中定义的异常处理逻辑。这样能够更好地管理和处理异常,提高应用的可靠性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值