SpringBoot全局异常配置

上篇提到通过@ControllerAdviceResponseBodyAdvice接口实现对请求接口的拦截封装处理,进行统一格式返回,问题来了:程序在执行过程中难免会出现异常,怎样处理,是否也可以统一处理?

实现全局异常处理

1 创建返回异常信息枚举类

ResultCodeEnum:用于封装错误信息,方便异常抛出时调用。

package com.liyi.common.exception;
import lombok.Getter;

/**
 * @Author 
 * @Description 专门处理异常
 * @Date 21:14 2021/6/25
 * @Param 
 * @return 
**/
@Getter
public enum ResultCodeEnum {

    UNKNOWN_REASON(false, 20001, "未知错误"),
    SERVER_ERROR(false, 500, "服务器忙,请稍后在试"),
    ORDER_CREATE_FAIL(false, 601, "订单下单失败");

    private Boolean success;
    private Integer code;
    private String message;
    private ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }
}

2 创建返回的异常对象

ErrorHandler:异常统一返回的对象

package com.liyi.common.exception;

import lombok.*;
import lombok.experimental.Accessors;

@Builder
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ErrorHandler {

    // 异常的状态码,从枚举中获得
    private Integer status;
    // 异常的消息,写用户看得懂的异常,从枚举中得到
    private String message;
    // 异常的名字
    private String exception;

    /**
     * 对异常处理进行统一封装
     *
     * @param resultCodeEnum 异常枚举
     * @param throwable 异常对象
     * @param message 异常信息
     * @return
     */
    public static ErrorHandler fail(ResultCodeEnum resultCodeEnum, Throwable throwable, String message) {
        ErrorHandler errorHandler = ErrorHandler.fail(resultCodeEnum, throwable);
        errorHandler.setMessage(message);
        return errorHandler;
    }

    /**
     * 对异常枚举进行封装
     *
     * @param resultCodeEnum
     * @param throwable
     * @return
     */
    public static ErrorHandler fail(ResultCodeEnum resultCodeEnum, Throwable throwable) {
        ErrorHandler errorHandler = new ErrorHandler();
        errorHandler.setMessage(resultCodeEnum.getMessage());
        errorHandler.setStatus(resultCodeEnum.getCode());
        errorHandler.setException(throwable.getClass().getName());
        return errorHandler;
    }
}

3 对异常进行全局拦截

GlobalExceptionHandler:

package com.liyi.configuration;
import com.liyi.common.exception.ErrorHandler;
import com.liyi.common.exception.OrderException;
import com.liyi.common.exception.ResultCodeEnum;
import com.liyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 对服务器端出现500异常进行统一处理
     */
    @ExceptionHandler(Throwable.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorHandler makeExcepton(Throwable e, HttpServletRequest request) {
        ErrorHandler errorHandler = ErrorHandler.fail(ResultCodeEnum.SERVER_ERROR, e);
        log.error("请求的地址是:{},出现的异常是:{}", request.getRequestURL(), e.getMessage());
        return errorHandler;
    }
}
  • makeExcepton方法的作用是:把运行时异常封装为ErrorHandler对象进行统一捕获处理。
  • @RestControllerAdvice和@ControllerAdvice它是对controller的增强扩展处理,而全局异常就是一种扩展能力之一。
  • @ExceptionHandler(Throwable.class) :统一处理某一类型异常,从而减少代码的出现异常的复杂度和重复率,
  • @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR):指定客户端收到的http状态码,这里配置的是500,就显示成500错误。不指定也是没问题的。因为返回是根据自己的枚举进行处理了。

4.测试

package com.liyi.controller;

import com.liyi.common.exception.OrderException;
import com.liyi.common.exception.ResultCodeEnum;
import com.liyi.common.exception.ServiceException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(description = "订单管理")
@RequestMapping("/order/")
public class OrderController {

    @GetMapping("createOrder")
    @ApiOperation(value = "创建订单")
    public void createOrder(Integer id){
        if(id==1){
            throw new OrderException(ResultCodeEnum.ORDER_CREATE_FAIL);
        }
        if(id ==2){
            throw new ServiceException(ResultCodeEnum.UNKNOWN_REASON);
        }
    }
}

5 创建具体要抛出的异常类

ServiceException:自定义的异常类

package com.liyi.common.exception;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
public class ServiceException extends RuntimeException{
    private Integer code;
    private String message;
    public ServiceException(ResultCodeEnum resultCodeEnum){
        this.code = resultCodeEnum.getCode();
        this.message = resultCodeEnum.getMessage();
    }
    public ServiceException(Integer code ,String message){
        this.code = code;
        this.message = message;
    }
}

6.添加自定义异常处理方法

package com.liyi.configuration;
import com.liyi.common.exception.ErrorHandler;
import com.liyi.common.exception.OrderException;
import com.liyi.common.exception.ResultCodeEnum;
import com.liyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 对服务器端出现500异常进行统一处理
     */
    @ExceptionHandler(Throwable.class)
	 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorHandler makeExcepton(Throwable e, HttpServletRequest request) {
        ErrorHandler errorHandler = ErrorHandler.fail(ResultCodeEnum.SERVER_ERROR, e);
        log.error("请求的地址是:{},出现的异常是:{}", request.getRequestURL(), e.getMessage());
        return errorHandler;
    }

    @ExceptionHandler(ServiceException.class)
    public ErrorHandler makeServiceException(ServiceException serviceException,HttpServletRequest request){
        ErrorHandler errorHandler = ErrorHandler.builder().
                                message(serviceException.getMessage()).
                                status(serviceException.getCode()).build();
        log.error("请求路径为:{},出现的异常是:{}",request.getRequestURL(),serviceException.getMessage());
        return errorHandler;
    }
}

该文章仅学习记录使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值