《springboot实战》第六章 实现自定义全局异常处理

简介: 《springboot实战》第六章 实现自定义全局异常处理

前言

springboot实现自定义全局异常处理,以及统一返回数据。

1、分析

首先,实现全局异常的流程

从图中可以看到,实现全局异常会需要这样几个类:

  • 自定义异常接口类
  • 自定义异常枚举类
  • 自定义异常类
  • 自定义异常处理类
  • 自定义全局响应类

2、创建所需类

2.1、为了代码解耦,创建一个接口类出来,定义自定义接口所需要的方法

/**
 * Http状态信息接口
 */
public interface HttpStatusInfoInterface {
    int getCode();
    String getMessage();
}

2.2、定义一个枚举类,实现上述接口,重写上述接口的两个方法来操作这个枚举类内部的各个具体枚举值

后续方便管理所有错误枚举的错误信息以及code码,通过构造方法传入code值和message或者直接传入一个枚举值都行

/**
 * Http状态码
 */
public enum HttpStatusEnum implements HttpStatusInfoInterface{
    //定义状态枚举值
    SUCCESS(200 , "成功!"),
    BODY_NOT_MATCH(400 , "数据格式不匹配!"),
    NOT_FOUND(404 , "访问资源不存在!"),
    INTERNAM_SERVER_ERROR(500 , "服务器内部错误!"),
    SERVER_BUSY(503 , "服务器正忙,请稍后再试!"),
    REQUEST_METHOD_SUPPORT_ERROR(10001 , "当前请求方法不支持!"),
    REQUEST_DATA_NULL(10002 , "当前请求参数为空!"),
    USER_NOT_EXISTS(10003 , "该用户不存在!"),
    USER_INVALID(10004 , "当前登录信息已生效,请重新登录!"),
    PASSWORD_ERROR(10005 , "密码错误!"),
    USER_NAME_LOCK(10006 , "该账号已被锁定!");
    //状态码
    private int code;
    //提示信息
    private String message;
    //构造方法
    HttpStatusEnum(int code , String message) {
        this.code = code;
        this.message = message;
    }
    @Override
    public int getCode() {
        return this.code;
    }
    @Override
    public String getMessage() {
        return this.message;
    }
}

2.3、自定义一个异常类

就像空指针异常类、IO流异常类一样。此处自定义的异常类属于异常类,所有肯定是要继承一个异常类的,此处需要继承RuntimeException,原因如下:

RuntimeException相比Exception来讲,他是在程序运行时才会爆出异常,在编译时是不会出现异常的,这就表示,如果你throw了一个RuntimeException,不需要做额外操作;而throw一个Exception,程序会要求你try-catch,否则你根本启动不了程序,程序会提示(必须对其进行捕获或声明以便抛出)

import com.xxxx.springbootmybatis.common.HttpStatusEnum;
import lombok.Data;
@Data
public class HttpException extends RuntimeException{
    //错误码
    private int code;
    //错误信息
    private String message;
    // 默认构造函数
    public HttpException() {
        super();
    }
    public HttpException(HttpStatusEnum httpStatusEnum) {
        super(String.valueOf(httpStatusEnum.getCode()));
        this.code = httpStatusEnum.getCode();
        this.message = httpStatusEnum.getMessage();
    }
}

2.4、封装统一返回类

封装返回值类BaseResponse类和RespGenerator类都是属于规范方法返回值结构体的类,也有利于一致化后端所有接口的返回结构,方便前端读取所需要的数据。

HttpResult类:规定返回值结构。

HttpResultGenerator类:将逻辑处理后的数据包装转换成HttpResult类进行返回给前端。

import lombok.Data;
/**
 * http 统一返回类
 * @param <T>
 */
@Data
public class HttpResult<T> {
    private Integer code;
    private String message;
    private T data;
    //构造方法
    public HttpResult(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
    //默认构造函数
    public HttpResult() {
        super();
    }
}
public class HttpResultGenerator {
    //正常返回时调用方法
    public static HttpResult success(Object data) {
        return new HttpResult(HttpStatusEnum.SUCCESS.getCode() , "接口调用成功!" , data);
    }
    //失败时调用方法(入参是异常枚举)
    public static HttpResult fail(HttpStatusEnum httpStatusEnum) {
        return new HttpResult(httpStatusEnum.getCode() , httpStatusEnum.getMessage() , null);
    }
    //失败时调用方法(提供给GlobalExceptionHandler类使用)
    public static HttpResult fail(int code ,  String message) {
        return new HttpResult(code , message , null);
    }
}

2.5、自定义异常处理类

@RestControllerAdvice注解是@ResponseBody和@ControllerAdvice的组合。

@ResponseBody注解:通常用来将java对象转成JSON对象,返回给前端JSON数据。

@ControllerAdvice注解:结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。

@ExceptionHandler注解统一处理某一类异常,从而能够减少代码重复率和复杂度,value值为什么异常类型,就处理什么异常类型的逻辑。

import lombok.extern.slf4j.Slf4j;
import com.xxxx.springbootmybatis.common.HttpResult;
import com.xxxx.springbootmybatis.common.HttpResultGenerator;
import com.xxxx.springbootmybatis.common.HttpStatusEnum;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * 自定义异常处理类
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    //处理自定义异常
    @ExceptionHandler(value = HttpException.class)
    public HttpResult<Object> baseExceptionHandler(HttpException e) {
        log.error("发生业务异常!原因是:{}" , e.getMessage());
        return HttpResultGenerator.fail(e.getCode() , e.getMessage());
    }
    //处理空指针异常
    @ExceptionHandler(value = NullPointerException.class)
    public HttpResult<Object> exceptionHandler(Exception e) {
        log.error("发生异常!原因是:{}" , e);
        return HttpResultGenerator.fail(HttpStatusEnum.INTERNAM_SERVER_ERROR);
    }
}

3、测试

新建一个测试controller。

3.1、测试自定义异常全局处理效果

@Slf4j
@RestController
@CrossOrigin("*")
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/loginTest")
    public HttpResult loginTest(@RequestParam(value="name" ,required=false) String userName,
                                @RequestParam(value="pwd" ) String password ) {
        // URL: http://127.0.0.1/user/loginone?userName=zs&pwd=123
        log.info("userName:{} , password:{}" , userName , password);
        if(StringUtils.isEmpty(userName)) {
            throw new HttpException(HttpStatusEnum.USER_NOT_EXISTS);
        } else {
            return HttpResultGenerator.success("登录校验成功");
        }
    }
}

3.2、用postman测试,若username没有传值,会抛出自定义异常

3.3、控制台结果

2023-04-19 17:47:51.411 |-INFO  [http-nio-80-exec-3] com.hqyj.springbootmybatis.controller.UserController [54] -| userName: , password:123
2023-04-19 17:47:51.411 |-ERROR [http-nio-80-exec-3] com.hqyj.springbootmybatis.common.exception.GlobalExceptionHandler [21] -| 发生业务异常!原因是:该用户不存在!

目录
相关文章
|
6月前
|
JSON 前端开发 Java
【十八】springboot实现自定义全局异常处理
【十八】springboot实现自定义全局异常处理
124 1
【十八】springboot实现自定义全局异常处理
|
6月前
|
JSON Java 数据格式
Springboot自定义全局异常处理
BasicErrorController是Spring Boot中默认提供的用于处理基本错误的控制器。它实现了ErrorController接口,用于处理在应用程序中发生的错误,例如404 Not Found等。此种方式是通过请求转发实现的,出现异常时,会转发到请求到/error,该接口对异常进行处理返回,是最符合全局异常处理的。
102 2
|
Java
SpringBoot自定义异常处理
SpringBoot自定义异常处理
64 1
|
Java 开发者 Spring
Spring Boot 中关于自定义异常处理的套路!
Spring Boot 中关于自定义异常处理的套路!
|
安全 Java 数据库
SpringBoot+拦截器+自定义异常+自定义注解+全局异常处理简单实现接口权限管理
提到权限管理这块肯定很多人第一想到的就是Springboot Security或者是Shiro安全框架,但本文介绍的并不是这两种,不是因为他们不好用,实在是自己太懒了,我觉得一个拦截器加上其他的一些处理就能满足项目的需求,我又何必去多用一个框架呢,这篇文章也不是去对比谁好谁坏,各位自行抉择。
84115 6
|
JSON 前端开发 JavaScript
SpringBoot系列教程web篇之自定义异常处理HandlerExceptionResolver
关于Web应用的全局异常处理,上一篇介绍了ControllerAdvice结合@ExceptionHandler的方式来实现web应用的全局异常管理; 本篇博文则带来另外一种并不常见的使用方式,通过实现自定义的HandlerExceptionResolver,来处理异常状态
491 0
SpringBoot系列教程web篇之自定义异常处理HandlerExceptionResolver
Springboot自定义异常处理
1.自定义异常类 import lombok.Data; @Data public class UserException extends RuntimeException { private Long id; public UserException(Long id) { super("user not exist"); this.
1506 0
|
JSON Java 测试技术
看看人家 SpringBoot 的全局异常处理,多么优雅。。。
本篇文章主要介绍的是SpringBoot项目进行全局异常的处理。 SpringBoot全局异常准备
看看人家 SpringBoot 的全局异常处理,多么优雅。。。
|
Java 编译器 程序员
SpringBoot全局异常处理
在开发软件系统过程中,异常信息是常见的,如何处理系统内部异常,快速定位BUG,是非常考验一位软件开发人员的功底。在软件系统开发过程中,统一自定义异常信息,统一对异常进行捕获处理,这样做能提高软件开发效率,并且使代码看起来更优雅。
421 0
|
JSON 前端开发 Java
SpringBoot全局异常处理(三十)下
SpringBoot全局异常处理(三十)下
290 0
SpringBoot全局异常处理(三十)下