全局异常处理@ExceptionHandler

在代码的编写过程当中含有的一些不可避免的情况,就是会出现异常,在后端进行处理操作。

{
  "timestamp": "2023-12-21T09:49:08.199+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "",
  "path": "/content/course"
}

当出现异常的情况的话,若我们不对异常的信息进行处理操作的话,就会直接不断的向上抛出异常,最终抛给spring容器,但是spring容器是不会对异常进行处理操作的,那么就会直接将异常抛给前端使得前端直接报错了。

这个报错可不是简单的报错,仅仅是因为在填写表单处理的时候一个关键的课程名称没有填就直接报了一个服务器异常500.这是多么不可原谅的事情呀!!一个小错误导致整个系统都出现了一个大的问题。

那解决这个问题的方式有很多种!

在填写课程名称的时候前端工程对其进行设定操作。后端工程也是可以对其进行操作的,对异常的进行相应的处理操作。不要让后端工程出现500服务器出现问题的情况。那么异常的情况含有很多种,直接使用try catch的方式来对其进行处理操作。异常进行处理了就不会直接报错了。但是这种情况不是非常友好,首先你要只知道那一段代码可能后报错,才能准确的对其进行处理操作。还有一种情况就是会使得代码非常的冗余,很多的地方都是出现try catch的情况。

那么还有一种方法就是直接使用全局异常处理的操作。当程序中出现异常的情况直接通过全局异常处理器对异常进行处理。这个处理的方式通过获取这个异常的类型。设定专门的异常处理的相关类来进行操作。

例如:当抛出了空指针异常的时候,直接使用一个接口对这个异常进行接收。然后对其就处理操作,使得不会直接包报500错误的情况。同时还可以和前端工程师商量,向前端抛出一个什么类型的json数据格式就是属于异常信息,那么前端就可以通过获得这个异常信息进行前端的展示了。这样就可以规范出一套完整的代码。

通过这张图就可以看到以固定的格式返回json数据

那该怎么进行全局异常处理的操作呢??

首先我们知道在处理异常的情况下,我们可以直接对系统内部的异常进行抓取并进行相应的处理操作。

同时我们也可以设置我们自己编写的异常类,来对认为可能会出现异常的情况下进行我们自己异常的抛出。同时我们可以对其进行全局异常处理(自己的异常类)。

1.编写自定义异常

package com.xuecheng.base.exception;

/**
 * @program: xuecheng-plus-root
 * @description
 * @author: YangTao
 * @create: 2023-12-21 19:03
 **/
public class XueChengPlusException extends RuntimeException{

    private String message;

    public XueChengPlusException() {
        super();
    }

    public XueChengPlusException(String message) {
        super(message);
        this.message = message;
    }
    
    //直接生成一个静态的方法将异常进行抛出
    public static void cast(String message){
        throw  new XueChengPlusException(message);
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

//这里也可以使用枚举的异常信息进行抛出,对于一些比较固定的异常信息[请求参数为空 , 对象为空],这样就可以直接获取相应的枚举的异常信息,不要对所有的异常信息进行设定,可以直接就进行获取。也可以对我们抛出的大类异常进行相应枚举的操作。

2.创建枚举类(异常)

package com.xuecheng.base.exception;

/**
 * @program: xuecheng-plus-root
 * @description
 * @author: YangTao
 * @create: 2023-12-21 19:17
 **/
public enum CommonError {
    //生成相应的枚举类,可以对枚举类进行对象的获取
    UNKOWN_ERROR("执行过程异常,请重试。"),
    PARAMS_ERROR("非法参数"),
    OBJECT_NULL("对象为空"),
    QUERY_NULL("查询结果为空"),
    REQUEST_NULL("请求参数为空");

    private String message;

    CommonError(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

在自定义的异常类添加的相应的枚举的异常处理操作

//这里也可以使用枚举的异常信息进行抛出,对于一些比较固定的异常信息[请求参数为空 , 对象为空]
public static void cast(CommonError error){
    throw new XueChengPlusException(error.getMessage());
}

3.编写前端返回的异常处理的信息

package com.xuecheng.base.exception;

import java.io.Serializable;

/**
 * @program: xuecheng-plus-root
 * @description
 * @author: YangTao
 * @create: 2023-12-21 21:27
 **/
//跟前端约定好的处理异常的时候返回的json数据,当设定的json的属性是不一样的时候就会得到一个错误的结果。前端得不到errMessage的相关信息。
public class RestErrorResponse implements Serializable {
     private  String errMessage;

    public RestErrorResponse(String errMessage) {
        this.errMessage = errMessage;
    }

    public String getErrMessage() {
        return errMessage;
    }

    public void setErrMessage(String errMessage) {
        this.errMessage = errMessage;
    }
}

异常的抛出的相关类,枚举类,和响应给前端的类都编写完了。

那么就要一个异常处理的类来对抛出的异常统一的处理操作。以统一的格式相应给前端。

4.编写异常处理器

在Spring里,我们可以使用@ControllerAdvice来声明一些全局性的东西,最常见的是结合@ExceptionHandler注解用于全局异常的处理。

@ControllerAdvice是在类上声明的注解,其用法主要是

和@ExceptionHandler注解标注的方法结合使用的:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;

package com.xuecheng.base.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

/**
 * @program: xuecheng-plus-root
 * @description
 * @author: YangTao
 * @create: 2023-12-21 19:36
 **/
@ControllerAdvice
//@ControllerAdvice和@ResponseBody的结合体是ReControllerAdvice.
//直接使用这个注解就可以不需要对每一个方法进行相应的转json的格式了。方便一点
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(XueChengPlusException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//对进入到异常的相关响应直接返回一个状态码
    public RestErrorResponse handleXueChengPlusException(XueChengPlusException e){
        //将异常打印出来
        log.error(e.getMessage());
        String message = e.getMessage();
        return new RestErrorResponse(message);
    }


    @ExceptionHandler(Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse handleException(Exception e){
        //将异常打印出来
        log.error(e.getMessage());
        //对于不是自己定义的异常我们可以直接使用枚举类来获得异常的信息
        RestErrorResponse restErrorResponse = new RestErrorResponse(CommonError.UNKOWN_ERROR.getMessage());
        String message = restErrorResponse.getErrMessage();
        return restErrorResponse;
    }
}

进入到这个异常当中,直接对处理并且返回相应的结果。前端得到这个结果和返回的状态码.

前端响应的结果为json的数据。

前端的约定是得到的data当中含有的属性errMessage就对其进行相应的解析操作的。得到里面的内容,当前端和后端设定的属性的名称是不一致的话就对其解析是错误的。得不到正确的结果。

使得前端得不到提示!

根据不同的异常类型来得到不同的响应结果。

好的,您想了解关于使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理的内容,这是一个常用的方案,可以实现全局异常的捕获和处理,让程序更加健壮和稳定。 @ExceptionHandler注解用于标记一个方法,该方法用于处理指定的异常类型。@ControllerAdvice注解用于标记一个类,该类用于处理全局异常。枚举则可以用于定义异常类型,方便异常处理时的统一管理。 在实现全局异常处理时,我们可以通过 @ExceptionHandler 注解来捕获指定的异常类型,并在方法中进行相应的处理。@ControllerAdvice注解可以让我们在一个类中定义多个 @ExceptionHandler方法,用于处理不同类型的异常。同时,我们也可以使用枚举来定义不同的异常类型,方便管理和调用。 下面是一个简单的示例,演示如何使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = BusinessException.class) @ResponseBody public ResultVO handleBusinessException(BusinessException e) { return ResultVO.error(e.getCode(), e.getMessage()); } } public enum ExceptionEnum { PARAMETER_ERROR(1001, "参数错误"), DATA_NOT_FOUND(1002, "数据不存在"), SYSTEM_ERROR(5000, "系统错误"); private final int code; private final String message; ExceptionEnum(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } } public class BusinessException extends RuntimeException { private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(ExceptionEnum exceptionEnum) { super(exceptionEnum.getMessage()); this.code = exceptionEnum.getCode(); } public int getCode() { return code; } } ``` 在上面的示例中,GlobalExceptionHandler类标记了@ControllerAdvice注解,用于全局异常处理。其中,handleBusinessException方法用于处理BusinessException异常,返回一个ResultVO对象,其中包含错误码和错误信息。 BusinessException则是一个自定义的异常类,它包含一个code属性和一个message属性,用于表示异常的错误码和错误信息。同时,它还提供了一个构造方法,可以根据ExceptionEnum来构造一个BusinessException对象。 ExceptionEnum则是一个枚举类,包含了不同的异常类型,每个异常类型都有一个对应的错误码和错误信息。 在实际开发中,我们可以根据实际需求来定义不同的异常类型和错误码,以便更好地管理和调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值