Боевая серия Spring Boot (4) унифицированная обработка исключений

Spring Boot задняя часть внешний интерфейс GitHub

Кажется невозможным обеспечить нулевые исключения при разработке проекта.Будь то системное исключение или информация об исключении, вызванная проблемой кодирования самой программы, она должна быть возвращена в согласованной структуре данных.Дружественный метод обработки находится на переднем плане. режим разделения конечной и внутренней части (внутренняя часть обеспечивает интерфейс API для внешней части) может значительно повысить эффективность общения и работы каждого. Унифицированная обработка исключений на основе Spring Boot, которая в основном используется в этой статье.@ControllerAdviceаннотация.

Быстрая навигация

  • Единая структура возвращаемых данных
    • [统一返回数据结构]Определите интерфейс для возврата структуры данных
    • [统一返回数据结构]Определение модели поля интерфейса данных
    • [统一返回数据结构]Инкапсулировать метод возврата интерфейса (успех, сбой)
  • Унифицированная обработка исключений
    • [统一异常处理]Перечисление сообщений о состоянии
    • [统一异常处理]пользовательский класс исключений
    • [统一异常处理]@ControllerAdvice единообразно обрабатывает исключения
  • тестовое задание
    • [测试]Проверка нормального возврата и системного исключения с нулевым указателем
    • [测试]Пользовательский тест-исключение

Примеры в этой статье основаны наБоевая серия Spring Boot (3) АОП-аспектно-ориентированное программирование /глава 3/глава 3-1Исходный код доступен на Github

Единая структура возвращаемых данных

Определите интерфейс для возврата структуры данных

Сначала определите интерфейс для возврата структуры данных, код 0 означает, что операция выполнена успешно, а не 0 означает исключение. Среди них данные будут возвращены только в случае успешной обработки, другие случаи не будут возвращены или те интерфейсы, которым не нужно возвращать данные (обновление, удаление...)

{
 	"code": 0,
 	"message": "SUCCESS",
 	"data": {

 	}
}

Определение модели поля интерфейса данных

Создайте/domain/Result.javaКласс определяет поля, задействованные в вышеупомянутом интерфейсе данных.

Result.java

package com.angelo.domain;

public class Result<T> {
    private Integer code; // 状态码

    private String message; // 状态描述信息

    private T data; // 定义为范型

    // 以下 getter、setter方法省略
}

Инкапсулировать метод возврата интерфейса

Создайте/util/MessageUtil.javaКласс, который единообразно инкапсулирует возвращенный успех и неудачу.

MessageUtil.java

package com.angelo.util;

import com.angelo.domain.Result;

public class MessageUtil {

    /**
     * 成功方法
     * @param object
     * @return
     */
    public static Result success(Object object) {
        Result result = new Result();
        result.setCode(0);
        result.setMessage("SUCCESS");
        if (object != null) {
            result.setData(object);
        }

        return result;
    }

    /**
     * 成功但是
     */
    public static Result success() {
        return success(null);
    }

    /**
     * 失败方法
     * @param code
     * @param message
     * @return
     */
    public static Result error(Integer code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);

        return result;
    }
}

Унифицированная обработка исключений

Перечисление сообщений о состоянии

Информация о коде состояния и описании, используемая в проекте, должна иметь единый файл для определения перечисления.С одной стороны, его можно использовать повторно. С другой стороны, если код состояния и описание изменены, его нужно изменить только в место, где определяется перечисление.

новый/enums/MessageEnum.javaперечислить

package com.angelo.enums;

public enum MessageEnum {
    SYSTEM_ERROR(1001, "系统异常"),
    NAME_EXCEEDED_CHARRACTER_LIMIT(2000, "姓名超过了限制,最大4个字符!");

    private Integer code;

    private String message;

    MessageEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

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

Инфраструктура Spring Boot откатывает только созданное исключение RuntimeException, поэтому исключение RuntimeException, инкапсулированное Spring Boot, также является унаследованным исключением.

новый/exception/UserException.javaкласс, унаследованный отRuntimeException

UserException.java

package com.angelo.exception;

import com.angelo.enums.MessageEnum;

public class UserException extends RuntimeException {
    private Integer code;

    public UserException(MessageEnum messageEnum) {
        super(messageEnum.getMessage());
        this.code = messageEnum.getCode();
    }

    public Integer getCode() {
        return code;
    }

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

@ControllerAdvice единообразно обрабатывает исключения

о@ControllerAdviceДля получения дополнительной информации, пожалуйста, обратитесь к официальной документацииhttps://docs.spring.io/spring-framework/docs/5.0.0.M1/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

  • @ControllerAdvice, недавно добавленный весной 3.2, используемый для определения@ExceptionHandler, @InitBinder, а также@ModelAttributeметод и применим ко всем@RequestMappingметод.

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

  • 注意:Я уже говорил об аспектно-ориентированном программировании АОП, аннотации@AfterThrowingОн будет собирать информацию об ошибке в проекте. Если эта аннотация используется, она вернется сразу после сбора информации об ошибке, она не будет запускаться@ControllerAdviceАннотированный.
package com.angelo.handle;

import com.angelo.domain.Result;
import com.angelo.exception.UserException;
import com.angelo.util.MessageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class ExceptionHandle {

    private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e) {
        logger.info("进入error");

        // 是否属于自定义异常
        if (e instanceof UserException) {
            UserException userException = (UserException) e;

            return MessageUtil.error(userException.getCode(), userException.getMessage());
        } else {
            logger.error("系统异常 {}", e);

            return MessageUtil.error(1000, "系统异常!");
        }
    }
}

тестовое задание

Проверка нормального возврата и системного исключения с нулевым указателем

ИсправлятьUsercontroller.javaдобавьте обработку возвращаемого значения в интерфейс пользовательского списка запросов, как показано ниже:

/**
 * 查询用户列表
 * @return
 */
@RequestMapping(value = "/user/list/{exception}")
public Result<User> userList(@PathVariable("exception") Boolean exception) {
    if (exception) {
        return null; // 测试空指针异常
    }

    return MessageUtil.success(userRepository.findAll());
}
  • вернуть успех

图片描述

  • вернуть системное исключение

图片描述

Пользовательский тест-исключение

ИсправлятьUsercontroller.javaclass, добавьте проверку длины имени в интерфейсе сохранения информации о пользователе и выдайте пользовательскую ошибку, как показано ниже:

/**
 * 保存一个用户
 * @param name
 * @param age
 * @return
 */
@PostMapping(value = "/user")
public User userAdd(@RequestBody User userParams) throws Exception {
    User user = new User();
    user.setName(userParams.getName());
    user.setAge(userParams.getAge());

    if (userParams.getName().length() > 4) { // 校验测试异常类
        throw new UserException(MessageEnum.NAME_EXCEEDED_CHARRACTER_LIMIT);
    }

    return userRepository.save(user);
}

图片描述

Посмотреть полный пример этой статьи на Github, глава 4-1.

Автор: май июнь
Связь:Вухуу. ИМО OC.com/article/260…
Источник: МООК
Github: Боевая серия Spring Boot