SpringBoot统一异常处理

首先定义一个异常类CustomException 。

/**
 * 自定义异常类型
 * @author kavito
 * @date 2019/5/31 16:39
 */
public class CustomException extends RuntimeException {

    //错误代码
    ResultCode resultCode;
    
    public CustomException(ResultCode resultCode){
        this.resultCode = resultCode;
    }
    public ResultCode getResultCode(){
        return resultCode;
    }

}

 ResultCode接口:

/**
 * 返回结果代码接口
 */
public interface ResultCode {
    //操作是否成功,true为成功,false操作失败
    boolean success();
    //操作代码
    int code();
    //提示信息
    String message();
}

按照模块划分,可以定义不同实现类(比如UserCode)。下面是一个公共的(枚举类)实现类:

@ToString
public enum CommonCode implements ResultCode{
    INVALID_PARAM(false,10003,"非法参数!"),
    SUCCESS(true,10000,"操作成功!"),
    FAIL(false,11111,"操作失败!"),
    UNAUTHENTICATED(false,10001,"此操作需要登陆系统!"),
    UNAUTHORISE(false,10002,"权限不足,无权操作!"),
    SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!");

    //操作是否成功
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;
    private CommonCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }
    @Override
    public boolean success() {
        return success;
    }
    @Override
    public int code() {
        return code;
    }
    @Override
    public String message() {
        return message;
    }

}

对异常类静态封装,省去不必要的代码:

/**
 * 静态封装,省去throw new()
 * @author kavito
 * @date 2019/5/31 16:39
 */
public class ExceptionCast {

    public static void cast(ResultCode resultCode){
        throw new CustomException(resultCode);
    }
}

 全局统一异常处理类:

import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 统一捕获类(抛出的异常被这个类捕获)
 * @author kavito
 * @date 2019/5/31 16:39
 */
@ControllerAdvice//控制器增强,(如果全部异常处理返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就可以不需要添加 @ResponseBody)
public class ExceptionCatch {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);
    //定义map,配置异常类型所对应的错误代码
    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
    //定义map的builder对象,去构建ImmutableMap
    protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();

    //捕获CustomException此类异常,(捕获自定义异常)
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException customException){
        //记录日志
        LOGGER.error("catch exception:{}",customException.getMessage());
        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }

    //捕获Exception此类异常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
        //记录日志
        LOGGER.error("catch exception:{}",exception.getMessage());
        if(EXCEPTIONS == null){
            EXCEPTIONS = builder.build();//EXCEPTIONS构建成功
        }
        //从EXCEPTIONS中找异常类型所对应的错误代码,如果找到了将错误代码响应给用户,如果找不到给用户响应99999异常
        ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
        if(resultCode !=null){
            return new ResponseResult(resultCode);
        }else{
            //返回99999异常
            return new ResponseResult(CommonCode.SERVER_ERROR);
        }
    }

    static {
        //定义异常类型所对应的错误代码
        builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);
    }
}
@ControllerAdvice//控制器增强
@ExceptionHandler(CustomException.class):当抛出(自定义)CustomException异常后,会被这个方法捕获。

 ResponseResult:响应结果接口的实现类。其他模块可以通过继承该类来扩展,比如UserResult中我通过构造返回一个User对象。

@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response {
    //操作是否成功
    boolean success = SUCCESS;
    //操作代码
    int code = SUCCESS_CODE;
    //提示信息
    String message;
    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }
    public static ResponseResult SUCCESS(){
        return new ResponseResult(CommonCode.SUCCESS);
    }
    public static ResponseResult FAIL(){
        return new ResponseResult(CommonCode.FAIL);
    }

}
@Data
@NoArgsConstructor
public class UserResult extends ResponseResult {
    User user;
    public UserResult(ResultCode resultCode,User user) {
        super(resultCode);
        this.user= user;
    }
}

写一个简单的controller测试抛出异常: 

@RestController
@RequestMapping("/exception")
public class ExceptionController {

    @PostMapping("/test/{id}")
    public ResponseResult test(@PathVariable("id") int id) {
        if (id != 1) {
            //id不是1抛出非法参数异常
            ExceptionCast.cast(CommonCode.INVALID_PARAM);
        }
        return new ResponseResult(CommonCode.SUCCESS);
        //return new UserResult (CommonCode.SUCCESS,user);
    }
}

当我们请求localhost:31400/exception/test/2的时候,抛出我们自定义的异常customException,然后被ExceptionCatch捕获到。

响应给客户端:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值