SpringBoot中全局异常的捕获与包装

@ControllerAdvice从Spring3.2开始,引入了一个叫做@ControllerAdvice的注解,这个注解用来编写含有 @ExceptionHandler, @InitBinder, or @ModelAttribute这三个注解的类。官方文档注释如下:这个注解有几个参数,可以用来

@ControllerAdvice

从Spring3.2开始,引入了一个叫做@ControllerAdvice的注解,这个注解用来编写含有 @ExceptionHandler, @InitBinder, or @ModelAttribute这三个注解的类。官方文档注释如下:

在这里插入图片描述

这个注解有几个参数,可以用来限定该类对哪些Controller起作用:

在这里插入图片描述

所以比起上面的参数,我们更需要关心的是被该注解注解过得类里面的其他三个注解。

@ExceptionHandler

当Controller捕捉到异常后,若异常类型匹配,将执行被该注解注解的方法。其中,value值为异常的类型,表示该注解处理该类型,如下:

在这里插入图片描述

该被注解方法的入参和出参:

在这里插入图片描述

实践

项目中使用到的编码如下:

@ControllerAdvice
public class ExceptionHandle {

    public static final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
    private static final Map<String, String> EMPTY_DATA = new HashMap<>();

    @ResponseBody
    @ExceptionHandler(value = Exception.class) // 处理所有异常
    public JsonView exceptionGet(Exception e) {
        logger.error("Exception for handle ", e);
        // 自定义类,项目中用作API统一响应模板
        JsonView jsonView;
        if (e instanceof ApplicationException) { // 项目中用到的自定义异常
            jsonView = new JsonView();
            jsonView.setData(EMPTY_DATA);
            ApplicationException applicationException = (ApplicationException) e;
            jsonView.setCode(applicationException.getRetStub().getCode());
            jsonView.setMessage(applicationException.getRetStub().getMsg());
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException applicationException = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> violations = applicationException.getConstraintViolations();
            StringBuilder stringBuilder = new StringBuilder();
            for (ConstraintViolation<?> item : violations) {
                stringBuilder.append("[" + item.getMessage() + "]");
            }
            String msg = stringBuilder.toString();
            logger.error("ConstraintViolation msg is : " + msg);
            jsonView = new JsonView(SysStubInfo.PARAMETER_TYPE_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException applicationException = (MethodArgumentNotValidException) e;
            List<ObjectError> allErrors = applicationException.getBindingResult().getAllErrors();
            StringBuilder stringBuilder = new StringBuilder();
            for (ObjectError error : allErrors) {
                stringBuilder.append("[" + error.getDefaultMessage() + "]");
            }
            String msg = stringBuilder.toString();
            logger.error("ArgumentNotValid  msg is : " + msg);
            jsonView = new JsonView(SysStubInfo.PARAMETER_TYPE_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException applicationException = (MissingServletRequestParameterException) e;
            String parameterName = applicationException.getParameterName();
            String parameterType = applicationException.getParameterType();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder
                    .append("parameter " + parameterName + " is null " + " , expect: " + parameterType);
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.PARAMETER_IS_NULL, msg, EMPTY_DATA);
        } else if (e instanceof HttpMediaTypeNotSupportedException) {
            HttpMediaTypeNotSupportedException applicationException = (HttpMediaTypeNotSupportedException) e;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(applicationException.getContentType().getSubtype());
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.CONTENT_TYPE_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            HttpRequestMethodNotSupportedException applicationException = (HttpRequestMethodNotSupportedException) e;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(applicationException.getMethod());
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.METHOD_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof NoHandlerFoundException) {
            NoHandlerFoundException applicationException = (NoHandlerFoundException) e;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(
                    applicationException.getHttpMethod() + " --> " + applicationException.getRequestURL());
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.RESOURCE_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException applicationException = (MethodArgumentTypeMismatchException) e;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(
                    "parameter " + applicationException.getName() + " is not type of " + applicationException
                            .getRequiredType().getSimpleName());
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.PARAMETER_TYPE_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof HttpMessageNotReadableException) {
            HttpMessageNotReadableException applicationException = (HttpMessageNotReadableException) e;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(applicationException.getMessage());
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.REQUEST_BODY_INVALID, msg, EMPTY_DATA);
        } else if (e instanceof BindException) {
            BindException applicationException = (BindException) e;
            BindingResult bindingResult = applicationException
                    .getBindingResult();
            FieldError fieldError = bindingResult.getFieldError();
            String field = fieldError.getField();
            // String code = fieldError.getCode();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(field);
            String msg = stringBuilder.toString();
            jsonView = new JsonView(SysStubInfo.PARAMETER_IS_NULL, msg, EMPTY_DATA);
        } else {
            jsonView = new JsonView(SysStubInfo.DEFAULT_FAIL, EMPTY_DATA);
        }
        return jsonView;
    }
}

希望自己能够对正在进行中的项目的架构有一个比较清晰的认识。

参考: https://www.cnblogs.com/magicalSam/p/7198420.html

Read more

Volcano 与 Kubernetes GPU 调度学习笔记

本笔记系统整理 Volcano 调度器、Kubernetes 调度框架、GPU Device Plugin、HAMi 等云原生 AI 调度领域的核心知识,适合用于学习、复习和工程实践参考。 目录 * 第一部分:Volcano 入门 * 1. Volcano 是什么 * 2. 安装与快速使用 * 3. 核心特性一览 * 第二部分:Volcano 整体架构 * 4. Volcano 解决的核心问题 * 5. 整体架构与数据流 * 6. 三层抽象模型 * 第三部分:Volcano 核心实现原理 * 7. Session 机制 * 8. Gang Scheduling 实现 * 9. Queue 与 DRF 公平调度

容器镜像(4):镜像的常用工具箱

容器镜像(4):镜像的常用工具箱

前几篇在讲多架构镜像时已经用过 skopeo 和 crane 做镜像复制,这篇系统整理这两个工具的完整能力,同时介绍几个日常操作镜像时同样好用的工具。 一、skopeo:不依赖 Daemon 的镜像瑞士军刀 skopeo 的核心价值是绕过 Docker daemon,直接与 Registry API 交互。上一篇用它做镜像复制和离线传输,但它的能力远不止于此。 1.1 安装 # Ubuntu / Debian sudo apt install -y skopeo skopeo --version # skopeo version 1.15.1 1.2 inspect:免拉取检查镜像元数据 docker inspect 需要先把镜像拉到本地,skopeo inspect 直接向 Registry

容器镜像(3):多架构镜像构建

容器镜像(3):多架构镜像构建

一、什么是多架构镜像 1.1 OCI Image Index 上一篇介绍了单平台镜像的结构:一个 Manifest 指向 Config 和若干 Layer blob。多架构镜像在此之上多了一层——OCI Image Index(也叫 Manifest List),是一个轻量的索引文件,把多个单平台 Manifest 组织在一起: $ docker manifest inspect golang:1.22-alpine { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests&

容器镜像(2):containerd 视角下的镜像

容器镜像(2):containerd 视角下的镜像

一、为什么需要了解 containerd 如果你只用 docker run 跑容器,从来不关心底层,那可以不了解 containerd。但如果你在用 Kubernetes,或者想真正理解"容器运行时"是什么,containerd 是绕不开的。 事实上,当你执行 docker run 的时候,containerd 早就在后台悄悄工作了——Docker 从 1.11 版本开始,就把核心运行时剥离出来交给 containerd 负责。 1.1 Docker 的架构演变 早期的 Docker(1.10 及之前)是一个"大一统"的单体程序:一个 dockerd