springboot 统一响应格式以及全局异常处理

springboot全局异常处理

gitee地址:springboot全局异常处理

1.目录结构

在这里插入图片描述

2.maven依赖

<parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.7.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <!-- 配置 log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>2.1.7.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.7.RELEASE</version>
                <configuration>
                    <mainClass>com.qq.ExceptionApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

3.配置文件application.yaml

server:
  port: 8080

logging:
  level:
    com.qq: debug
  file: logs/exception.log

4.响应结构

4.1 响应状态码枚举类

/**
 * ResultCodeEnum
 *
 * @blame Android Team
 */
public enum ResultCode {

    SUCCESS(200, "操作成功"),
    ERROR(500, "操作失败"),
    BIZ_ERROR(1000, "通用业务异常"),
    FILE_OUT_MAX(9000, "文件超出最大限制"),
    FILE_FORMAT_ERROR(9001, "文件格式不正确"),
    PARAM_ERROR(9050, "参数错误"),
    JSON_FORMAT_ERROR(9051, "Json解析异常"),
    SQL_ERROR(9052, "Sql解析异常"),
    NETWORK_TIMEOUT(9510, "网络超时"),
    UNKNOWN_INTERFACE(9520, "未知的接口"),
    REQ_MODE_NOT_SUPPORTED(9530, "请求方式不支持"),
    SYS_ERROR(9999, "系统异常");

    /**
     * 状态码
     */
    private final int code;

    /**
     * 状态信息
     */
    private final String msg;

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

}

4.2 统一响应结构

import lombok.Data;

import java.io.Serializable;

/**
 * @author 黔程似景
 * @description 响应结果封装
 * @date 2022/8/21 14:45
 * @blame 黔程似景
 **/
@Data
public class ResponseResult<T> implements Serializable {

    private static final long serialVersionUID = 1175720458347412087L;

    /**
     * 状态码
     */
    private int code;

    /**
     * 响应信息
     */
    private String msg;

    /**
     * 相关数据
     */
    private T data;

    /**
     * 无参响应成功
     */
    public static <T> ResponseResult<T> success() {
        return new ResponseResult<T>();
    }

    /**
     * 成功,默认状态码,返回消息,自定义返回数据
     *
     * @param data 自定义返回数据
     * @param <T>  返回类泛型,不能为String
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> success(T data) {
        return new ResponseResult<T>(data);
    }

    /**
     * 成功,默认状态码,自定义返回消息,无返回数据
     *
     * @param msg 自定义返回消息
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> success(String msg) {
        return new ResponseResult<T>(msg);
    }

    /**
     * 成功,默认状态码,自定义返回消息,返回数据
     *
     * @param msg  自定义返回消息
     * @param data 自定义返回数据
     * @param <T>  返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> success(String msg, T data) {
        return new ResponseResult<T>(msg, data);
    }

    /**
     * 失败,默认状态码,返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> error() {
        return new ResponseResult<T>(ResultCode.ERROR);
    }

    /**
     * 失败,默认状态码,自定义返回消息,无返回数据
     *
     * @param <T> 返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> error(String msg) {
        return new ResponseResult<T>(ResultCode.ERROR.getCode(), msg);
    }

    /**
     * 失败,自定义状态码,返回消息,无返回数据
     *
     * @param code 自定义状态码
     * @param msg  自定义返回消息
     * @param <T>  返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> error(int code, String msg) {
        return new ResponseResult<T>(code, msg);
    }

    /**
     * 失败,使用CodeMsg状态码,返回消息,无返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     * @param <T>        返回类泛型
     * @return 通用返回Result
     */
    public static <T> ResponseResult<T> error(ResultCode resultCode) {
        return new ResponseResult<T>(resultCode);
    }

    /**
     * 成功构造器,无返回数据
     */
    private ResponseResult() {
        this(ResultCode.SUCCESS);
    }

    /**
     * 成功构造器,自定义返回数据
     *
     * @param data 返回数据
     */
    private ResponseResult(T data) {
        this(ResultCode.SUCCESS, data);
    }

    /**
     * 成功构造器,自定义返回消息,无返回数据
     *
     * @param msg 返回消息
     */
    public ResponseResult(String msg) {
        this(ResultCode.SUCCESS.getCode(), msg);
    }

    /**
     * 成功构造器,自定义返回信息,返回数据
     *
     * @param msg  返回信息
     * @param data 返回数据
     */
    private ResponseResult(String msg, T data) {
        this(ResultCode.SUCCESS.getCode(), msg, data);
    }

    /**
     * 构造器,自定义状态码,返回消息
     *
     * @param code 状态码
     * @param msg  返回消息
     */
    private ResponseResult(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
     * 构造器,自定义状态码,返回消息,返回数据
     *
     * @param code 状态码
     * @param msg  返回消息
     * @param data 返回数据
     */
    private ResponseResult(int code, String msg, T data) {
        this(code, msg);
        this.data = data;
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     */
    private ResponseResult(ResultCode resultCode) {
        this(resultCode.getCode(), resultCode.getMsg());
    }

    /**
     * 构造器,使用CodeMsg状态码与返回信息,自定义返回数据
     *
     * @param resultCode CodeMsg,参数如下:
     *                   <p> code 状态码
     *                   <p> msg  返回消息
     * @param data       返回数据
     */
    private ResponseResult(ResultCode resultCode, T data) {
        this(resultCode);
        this.data = data;
    }

}

5.异常自定义、异常捕获

5.1 异常自定义

/**
 * @author 黔程似景
 * @description 自定义异常
 * @date 2022/8/21 18:15
 * @blame 黔程似景
 **/
public class MyException extends Exception {

    /**
     * 错误码
     */
    private int code;

    /**
     * 错误消息
     */
    private String message;

    public MyException(int code , String message){
        this.code = code;
        this.message = message;
    }

    public MyException() {
    }

    /**
     * Returns the detail message string of this throwable.
     */
    @Override
    public String getMessage() {
        if (super.getMessage() == null){
            return this.message;
        }
        return super.getMessage();
    }

    /**
     * 获取
     * @return code
     */
    public int getCode() {
        return code;
    }

    /**
     * 设置
     * @param code
     */
    public void setCode(int code) {
        this.code = code;
    }

    /**
     * 设置
     * @param message
     */
    public void setMessage(String message) {
        this.message = message;
    }

}

5.2 异常捕获

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author 黔程似景
 * @description 异常拦截处理
 * @date 2022/8/21 16:42
 * @blame 黔程似景
 **/
@RestControllerAdvice
public class GlobalExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 空指针异常处理
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult<String> handleTypeMismatchException(NullPointerException exception) {
        logger.error("空指针异常:" , exception);
        return ResponseResult.error(500, "空指针异常");
    }

    /**
     * 自定义异常处理
     */
    @ExceptionHandler(MyException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult myExceptionHandler(MyException exception) {
        logger.error("自定义异常:" , exception);
        return ResponseResult.error(exception.getCode(), exception.getMessage());
    }

    /**
     * 运行时异常处理
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult throwable(RuntimeException exception) {
        logger.error("运行时异常:" , exception);
        return new ResponseResult<String>("运行时异常:" + exception.getMessage());
    }

    /**
     * 系统异常处理
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult exception(Exception exception) {
        logger.error("系统异常:" , exception);
        return new ResponseResult<String>("异常: " + exception.getMessage());
    }
}

6.controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 黔程似景
 * @description 异常处理接口
 * @date 2022/8/22 21:41
 * @blame 黔程似景
 **/
@RestController
public class ExceptionController {

    @GetMapping("/success")
    public ResponseResult demo(){
        return ResponseResult.success("访问成功!");
    }

    /**
     * 空指针
     */
    @GetMapping("/null")
    public ResponseResult nullPoint(){
        throw new NullPointerException("空指针异常");
    }

    /**
     * 自定义异常
     */
    @GetMapping("/myException")
    public ResponseResult myException() throws MyException {
        throw new MyException(500,"自定义异常");
    }

    /**
     * 运行异常
     */
    @GetMapping("/runtimeException")
    public ResponseResult runtimeException() {
        int a = 1/0;
        return null;
    }

    /**
     * 异常
     */
    @GetMapping("/exception")
    public ResponseResult exception() throws Exception {
        throw new Exception("系统异常");
    }

}

7.启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author 黔程似景
 * @description 启动类
 * @date 2022/8/22 21:40
 * @blame 黔程似景
 **/
@SpringBootApplication
public class ExceptionApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExceptionApplication.class, args);
    }
}

8.测试

8.1 成功访问

在这里插入图片描述

8.2 自定义异常访问

在这里插入图片描述

8.3 系统异常访问

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 课程目标:你将对研发框架的代码封装和开发规范制定的底层实现逻辑有所掌握,并形成自己的开发封装套路,告别CRUD课程简介:   1. 课程背景: 能帮你解决什么问题?企业中通常由架构师搭建好开发框架,里面包含了很多封装好的基础结构,日志规范以及响应异常统一处理,还有相应的参数校验等。很多初中高级开发工程师没有机会接触这部分代码的逻辑,而这部分代码逻辑又是非线性的,单纯看代码逻辑是看不出来执行顺序的,需要大量调试总结。不像mvc代码结构,你知道从Controller层看到Service再到Dao层,而这样底层的基础性代码则像积木,不熟悉的前提下需要一块块的插入拔出,不断总结,而沿着本课程的顺序梳理与实战你将会豁然开朗。市面上的大多文章结构较散,并且处理不够全面,比如返回结构通常是 具体的正例与反例日志统一处理 统一异常处理及特殊的情况处理 参数优雅校验 1基础的校验 2. 自定义校验 3.分组校验最重要的是给大家捋顺了一个清晰的实现结构以上在我们后面章节Spring Boot HelloWorld的至少10个可扩展点里有更多的相关介绍,在核心章节里有更细致的讲解实现。理解框架升级底层逻辑: 全网首套基于Spring Boot 3.x+Java 17开发系列 SpringBoot3的升级背景和路线逻辑掌握代码重构及编码效率提升技巧学习基于最为前沿的Spring Boot 3.x 和 Java 17 开发代码依赖于Spring Boot 3.x Java 17环境开发穿插相应新版本的变化讲解可编写完成一个生产级开发规范框架的制定 包含不限于 统一响应结构统一异常处理基于ThreadLocal处理请求RequestId基于日志框架的MDC 统一记录日志统一状态码处理Filter中的异常及状态码处理,以及日志的完整性处理自定义优雅参数校验学习源码剖析方式方法等等 3. 课程规划1.  课程章节规划 2. 讲课方式代码实战为主+图文演示为辅例如说明后端校验的重要性 以一张图清晰明了的展示说明解答了为何前端有了前端校验还要后端校验的问题 3. 特别说明本课程所有代码使用版本会随着Spring Boot 3.x的开发进度而更新,直到Spring Boot 3.x的正式版本发布,可放心食用本课程的重点会侧重放在研发框架的基础规范编码上,并非专注于SpringBoot3.x和Java17的新特性上讲解。主要是两点原因,1课程的方向侧重点, 2. SpringBoot3.x 官方尚处于MileStone/Snapshot版并未Release,所以大家可关注本人编程燃风后续的产品课程。本课程代码同样适用于Spring Boot 1.x 2.x 只需微调API和相关库版本的即可(注意1.x已经归档不维护) 常见问题:问:是否讲解Java17和SpringBoot3新特性答:本课程的重点会侧重放在研发框架的基础规范编码上,并非专注于SpringBoot3.x和Java17的新特性上讲解。主要是两点原因,1课程的方向侧重点是框架基础规范编码实战 2. SpringBoot3.x 官方尚处于MileStone/Snapshot版并未Release,所以大家可关注本人编程燃风后续的讲解课程。问:代码仅限于SpringBoot3吗? SpringBoot2和SpringBoot1是否适用?答:本课程代码同样适用于Spring Boot 1.x 2.x 只需微调API和相关库版本的即可(注意1.x已经归档不维护)。另外本课程重点讲解代码封装和底层实现逻辑和具体API版本关联不大,只是基于最新的SpringBoot3和Java17实现而已,请放心使用。
Spring Boot 中,可以通过全局异常处理机制来统一处理应用程序中的异常全局异常处理可以捕获应用程序中抛出的异常,并根据需要进行处理和响应。 下面是一种实现全局异常处理的方式: 1. 创建一个自定义的异常处理类,可以命名为 `GlobalExceptionHandler`。 ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { // 根据需要进行异常处理逻辑 // 可以返回自定义的错误信息或错误码等 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred"); } } ``` 2. 使用 `@ControllerAdvice` 注解标记该类为全局异常处理类。 3. 使用 `@ExceptionHandler` 注解来指定需要处理的异常类型,可以通过传入 `Exception.class` 来处理所有类型的异常。 4. 在 `handleException` 方法中,可以根据需要编写异常处理逻辑。可以返回自定义的错误信息或错误码等。 在上述示例中,`handleException` 方法会捕获所有类型的异常,并返回一个带有错误信息的 `ResponseEntity` 对象。 您可以根据实际需求在全局异常处理类中定义多个方法,每个方法处理不同类型的异常。这样可以根据不同的异常类型,提供不同的错误处理逻辑。 请注意,在实际应用中,您可能还需要使用其他注解,如 `@RestControllerAdvice` 或 `@ResponseBody`,以确保正确地处理异常并返回适当的响应。 通过实现全局异常处理,您可以统一处理应用程序中的异常,并提供一致的错误响应。这有助于提高代码的可维护性和用户体验。 希望对您有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值