SpringBoot actual combat (14) | unified handling of exceptions

  exception handling, java, springboot

WeChat Public Number: An Outstanding Disabled Person
If you have any questions or suggestions, please leave a message backstage. I will try my best to solve your problem.

Preface

For example, today I will introduce how SpringBoot handles global exceptions in a unified way. The two comments that play a major role in global exception handling in SpringBoot are@ControllerAdviceAnd@ExceptionHandler, where @ControllerAdvice is a component annotation, the class added with this annotation can intercept the Controller’s request, while ExceptionHandler annotation can set the exception type in global processing control to intercept the exception to be processed. For example: @ exceptionhandler (value = nullpointexception.class).

Preparatory work

  • SpringBoot 2.1.3
  • IDEA
  • JDK 8

Dependency configuration

<dependencies>
        <!-- JPA 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- mysql 连接类 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- lombok 依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 单元测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Configuration file

spring:
  # 数据库相关
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true
    username: root
    password: 123456

  jpa:
    hibernate:
      ddl-auto: update   #ddl-auto:设为 create 表示每次都重新建表
    show-sql: true

Message class returned

public class Message<T> implements Serializable {

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

    /**
     * 返回信息
     */
    private String message;

    /**
     * 返回的数据类
     */
    private T data;

    /**
     * 时间
     */
    private Long time;

    // getter、setter 以及 构造方法略。。。
}

Tool class

For processing the returned data and information classes, code comments are not mentioned in detail.

public class MessageUtil {

    /**
     * 成功并返回数据实体类
     * @param o
     * @param <E>
     * @return
     */
    public static <E>Message<E> ok(E o){
        return new Message<>(200, "success", o, new Date().getTime());
    }

    /**
     * 成功,但无数据实体类返回
     * @return
     */
    public static <E>Message<E> ok(){
        return new Message<>(200, "success", null, new Date().getTime());
    }

    /**
     * 失败,有自定义异常返回
     * @param code
     * @param msg
     * @return
     */
    public static <E>Message<E> error(Integer code,String msg){
        return new Message<>(code, msg, null, new Date().getTime());
    }
}

Custom exception

By inheriting RuntimeException, the declaration code is used to define different types of custom exceptions. It is mainly used for exception interception to obtain code and setting code into message class to return.

public class CustomException extends RuntimeException{

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

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public CustomException(Integer code, String message){

        super(message);
        this.code = code;

    }
}

Exception interception class

Declare that the class can intercept Controller requests by adding @ restcontroleradvice, and add @ExceptionHandler to the handle method and specify the exception class to intercept in the annotation.

@RestControllerAdvice // 控制器增强处理(返回 JSON 格式数据),添加了这个注解的类能被 classpath 扫描自动发现
public class ExceptionHandle {

    @ExceptionHandler(value = Exception.class) // 捕获 Controller 中抛出的指定类型的异常,也可以指定其他异常
    public <E>Message<E> handler(Exception exception){

        if (exception instanceof CustomException){
            CustomException customException = (CustomException) exception;
            return MessageUtil.error(customException.getCode(), customException.getMessage());
        } else {
            return MessageUtil.error(120, "异常信息:" + exception.getMessage());
        }
    }
}

Only custom exceptions and unknown exceptions are handled here. If you know clearly in a certain method that an exception may be thrown, you can add a specific handling. For example, if you know clearly that this method may throw a NullPointException, you can add NullPointException processing:

if (exception instanceof CustomException){
     CustomException customException = (CustomException) exception;
     return MessageUtil.error(customException.getCode(), customException.getMessage());
} else if (exception instanceof NullPointException ){
     return MessageUtil.error(500, "空指针异常信!");
} else {
     return MessageUtil.error(120, "异常信息:" + exception.getMessage());
}

Controller layer

@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/{id}")
    public Message<Student> findStudentById(@PathVariable("id") Integer id){

        if (id < 0){
            //测试自定义错误
            throw new CustomException(110, "参数不能是负数!");

        } else if (id == 0){
            //硬编码,为了测试
            Integer i = 1/id;
            return null;
        } else {
            Student student = studentService.findStudentById(id);
            return MessageUtil.ok(student);
        }
    }
}

Complete code

https://github.com/turoDog/De …

If you think it is helpful to you, please give a Star before you leave. thank you very much.

Postman test

Accesshttp://localhost: 8080/student/5 Test Returns Normal Data Results.

返回正常结果

Accesshttp://localhost: 8080/student/0 Tests Results of Unknown Exceptions.

测试未知异常的情况

Accesshttp://localhost: 8080/student/-11 Tests Results of Custom Exceptions.

测试自定义异常情况

Postscript

If this article is of any help to you, please help me look good. Your good looks are my motivation to persist in writing.

In addition, after the attention is sent1024Free study materials are available. For details of the information, please refer to this old article:Python, C++, Java, Linux, Go, Front End, Algorithm Data Sharing

一个优秀的废人