SpringBoot Combat (14) | Унифицированная обработка исключений

Spring Boot

Публичный аккаунт WeChat: отличная трата времени Если у вас есть какие-либо вопросы или предложения, оставьте сообщение в фоновом режиме, и я сделаю все возможное, чтобы решить вашу проблему.

предисловие

Как следует из названия, сегодня я расскажу, как SpringBoot единообразно обрабатывает глобальные исключения. Две основные аннотации для глобальной обработки исключений в SpringBoot:@ControllerAdviceа также@ExceptionHandler, где @ControllerAdvice — аннотация компонента, класс, добавляющий эту аннотацию, может перехватить запрос контроллера, а аннотация ExceptionHandler может задать тип исключения в глобальном элементе управления обработкой, чтобы перехватить обрабатываемое исключение. Например: @ExceptionHandler(значение = NullPointException.class).

Готов к работе

  • SpringBoot 2.1.3
  • IDEA
  • JDK 8

Конфигурация зависимостей

<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>

конфигурационный файл

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

возвращенный класс сообщения

public class Message<T> implements Serializable {

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

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

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

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

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

Инструменты

Он используется для обработки возвращаемых данных и информационных классов, а комментарии к коду очень подробные.

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());
    }
}

пользовательское исключение

Наследуя от RuntimeException , декларативный код используется для определения пользовательских исключений разных типов. Он в основном используется для перехвата исключения, чтобы получить код и установить код в класс сообщения для возврата.

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;

    }
}

класс перехватчика исключений

Объявите этот класс для перехвата запросов контроллера, добавив @RestControllerAdvice, добавьте @ExceptionHandler в метод дескриптора и укажите в этой аннотации класс исключения, который нужно перехватить.

@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());
        }
    }
}

Здесь обрабатываются только пользовательские исключения и неизвестные исключения.Если вы точно знаете, что в методе может быть выброшено исключение, вы можете добавить специальную обработку. Например, если вы явно знаете, что метод может генерировать NullPointException, вы можете добавить обработчик NullPointException:

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());
}

слой контроллера

@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);
        }
    }
}

полный код

https://github.com/turoDog/Demo/tree/master/springboot_exception_demo

Если вы считаете, что это полезно для вас, пожалуйста, поставьте звезду и уходите, большое спасибо.

Почтальон тест

Посетите http://localhost:8080/student/5, чтобы проверить нормальные результаты возврата данных.

返回正常结果

Посетите http://localhost:8080/student/0, чтобы проверить результаты неизвестного исключения.

测试未知异常的情况

Посетите http://localhost:8080/student/-11, чтобы проверить результат пользовательского исключения.

测试自定义异常情况

послесловие

Если эта статья поможет вам хоть немного, пожалуйста, помогите. Твоя внешность мотивирует меня продолжать писать.

Кроме того, я отправляю его после того, как обратил внимание1024Доступны бесплатные учебные материалы. Подробнее см. в этой старой статье:Python, C++, Java, Linux, Go, внешний интерфейс, алгоритм обмена данными

一个优秀的废人