SpringBoot错误处理机制(ControllerAdvice+ExceptionHandler自定义错误处理、默认机制源码分析、错误处理实战)

news2024/11/16 19:10:08

目录

  • 1. SpringBoot自己对错误进行处理
    • 1.1 给一个Controller进行错误处理
    • 1.2 使用ControllerAdvice统一处理错误
  • 2. 默认机制源码解析
  • 3. 错误处理机制实战

1. SpringBoot自己对错误进行处理

1.1 给一个Controller进行错误处理

使用@ExceptionHandler,处理一个@Contoller的异常

package com.hh.springboot3test.controller;

import org.springframework.web.bind.annotation.*;




@RestController
public class ControllerTest {

    /*
    对整个RestController的异常进行处理
     */
    @ResponseBody       // 将异常消息返回给客户端
    @ExceptionHandler(Exception.class)      // 标识能处理的异常
    public String handleException(Exception e) {    // 接收异常
        return "出错了, 原因: " + e.getMessage();
    }

}

1.2 使用ControllerAdvice统一处理错误

使用@ControllerAdvice处理所有@Controller发生的错误。优先级比@Controller类的低

package com.hh.springboot3test.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


// 标明这个类是集中处理所有@Controller发生的错误
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {

        return "出错了, 统一处理,原因: " + e.getMessage();
    }
}

2. 默认机制源码解析

如果我们没有进行自定义的错误处理,springBoot提供默认的错误处理机制。错误处理的自动配置都在ErrorMvcAutoConfiguration中。整个处理流程如下:

默认机制

如果SpringMVC处理不了,则将错误请求发送给server.error.path=/error参数配置的路径,如果没有配置参数,则默认是/error。由ErrorMvcAutoConfiguration添加的BasicErrorController组件进行处理。如下所示:

......省略部分......
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
......省略部分......
}

SpringBoot会自适应处理错误,浏览器优先响应页面或移动端优先响应JSON数据。和内容协商一样,header头的accept参数设置application/xml,则以XML格式返回数据。BasicErrorController部分代码如下所示:

    @RequestMapping(
        produces = {"text/html"}    // 返回HTML
    )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView != null ? modelAndView : new ModelAndView("error", model);
    }

    @RequestMapping    // 返回ResponseEntity, 可以是JSON
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = this.getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity(status);
        } else {
            Map<String, Object> body = this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL));
            return new ResponseEntity(body, status);
        }
    }

我们先说HTML的错误处理。在errorHtml方法。错误页面先调用resolveErrorView,通过DefaultErrorViewResolver解析的

		// 解析错误的自定义视图地址
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);

ErrorMvcAutoConfiguration给容器专门添加了一个错误视图解析器DefaultErrorViewResolver

        @Bean
        @ConditionalOnBean({DispatcherServlet.class})
        @ConditionalOnMissingBean({ErrorViewResolver.class})
        DefaultErrorViewResolver conventionErrorViewResolver() {
            return new DefaultErrorViewResolver(this.applicationContext, this.resources);
        }

SpringBoot的DefaultErrorViewResolver,提供了解析自定义错误页的默认规则

    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
        // 先进行精确码处理
        ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);
        // 精确码处理不了,再进行4xx、5xx处理
        if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
            modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
        }

        return modelAndView;
    }

    private ModelAndView resolve(String viewName, Map<String, Object> model) {
        // 先在classpath:templates/error路径下查找
        String errorViewName = "error/" + viewName;
        TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
        // 如果classpath:templates/error没找到,则调用resolveResource方法,从静态路径下面的error文件夹下去找
        return provider != null ? new ModelAndView(errorViewName, model) : this.resolveResource(errorViewName, model);
    }

    private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
        String[] var3 = this.resources.getStaticLocations();
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String location = var3[var5];

            try {
                Resource resource = this.applicationContext.getResource(location);
                resource = resource.createRelative(viewName + ".html");
                if (resource.exists()) {
                    return new ModelAndView(new HtmlResourceView(resource), model);
                }
            } catch (Exception var8) {
            }
        }

        return null;
    }

如果errorHtml方法,调用resolveErrorView处理不了。则在errorHtml方法访问classpath:templates/error.html

        return modelAndView != null ? modelAndView : new ModelAndView("error", model);

如果classpath:templates/error.html都未提供。ErrorMvcAutoConfiguration给容器添加一个默认名为error的view。提供了默认白板功能

        @Bean(
            name = {"error"}
        )
        @ConditionalOnMissingBean(
            name = {"error"}
        )
        public View defaultErrorView() {
            return this.defaultErrorView;
        }

再说移动端的错误处理。DefaultErrorAttributes封装了JSON格式的错误信息

    @Bean
    @ConditionalOnMissingBean(
        value = {ErrorAttributes.class},
        search = SearchStrategy.CURRENT
    )
    public DefaultErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes();
    }

规则总结:

  1. 解析一个错误页
    1. 如果发生了403、404、500、503这些错误
      1. 如果有模板引擎,默认在classpath:/templates/error/精确码.html。如403.html文件
      2. 如果没有模板引擎,在静态资源文件夹下的error文件夹下找精确码.html
    2. 如果匹配不到精确码.html这些精确的错误页,就去找5xx.html,4xx.html模糊匹配
      1. 如果有模板引擎,默认在classpath:/templates/error/5xx.html。如5xx.html文件
      2. 如果没有模板引擎,在静态资源文件夹下的error文件夹下找 5xx.html
  2. 如果上面处理不了,则从模板引擎路径classpath:templates下找error.html页面。如果error.html页面都没有,则使用springboot提供的默认白板页面

3. 错误处理机制实战

  • 前后分离
    • 后台发生的所有错误,@ControllerAdvice + @ExceptionHandler进行统一异常处理,将错误数据返回给前端
  • 服务端页面渲染
    • 不可预知的一些,HTTP码表示的服务器或客户端错误
      • 给classpath:/templates/error/下面,放常用精确的错误码页面。如500.html、404.html
      • 给classpath:/templates/error/下面,放通用模糊匹配的错误码页面。如5xx.html、4xx.html
    • 发生业务错误
      • 核心业务,每一种错误,都应该代码控制,跳转到自己定制的错误页
      • 通用业务,用classpath:/templates/error.html页面,显示错误信息

model中会默认存放一些数据。如下所示。我们自己也可以向model添加数据,然后再错误页面渲染的时候进行使用
model

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1262277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电源芯片】ZTP7193

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大…

销售流程中如何有效开发客户

在销售的海洋中&#xff0c;如何游刃有余地开发客户是一大关键。这需要深入了解你的目标客户&#xff0c;制定一份精细的销售计划&#xff0c;选择最合适的沟通方式&#xff0c;建立信任和信誉&#xff0c;并持续不断地跟进。 每一个潜在的客户都是一颗璀璨的星辰&#xff0c;…

地理坐标系转换

1.EPSG代码 搜索地理坐标系对应的EPSG代码 https://epsg.io/ 常用的地理坐标系EPSG代码&#xff1a; 2. 坐标系转换 转换网址&#xff1a; https://epsg.io/transform &#xff08;1&#xff09;修改 input coordinate system 和 output coordinate system&#xff0c; 可以…

【开源】基于Vue.js的农村物流配送系统的设计和实现

项目编号&#xff1a; S 024 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S024&#xff0c;文末获取源码。} 项目编号&#xff1a;S024&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2…

人工智能学习2(python数据清洗)

编译工具&#xff1a;PyCharm 一.数据清洗 转化数据类型、处理重复数据、处理缺失数据 import pandas as pddf pd.read_csv("/data.csv") df.sample(10) # 用于随机获取数据并返回结果 df.head(10) # 查看前十条数据 df.tail(10) # 查看后十条数据 df.shape …

Zookeeper 实战 | Zookeeper 和Spring Cloud相结合解决分布式锁、服务注册与发现、配置管理

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…

Emeya散发的时代之光,似乎正盖过Panamera的余晖

路特斯Emeya的首秀象征着在超豪华汽车领域&#xff0c;纯电与超跑轿车的绝美融合正式拉开序幕。自由与灵感的碰撞&#xff0c;诗意与理想的贯通&#xff0c;汽车工业的性感似乎在Emeya上出现了全新的表达。 但短短不到一周的时间&#xff0c;我们又见到了全新Panamera的首秀。…

四招心理博弈术,让别人不敢欺负你,敬你三分

教你四招心理博弈术&#xff0c;让别人不敢欺负你&#xff0c;无论在职场中还是跟朋友交往中&#xff0c;为什么总是有人敢欺负你呢&#xff0c;是因为你不懂得人性博弈。其本质原因&#xff0c;是你做人没有边界感&#xff0c;或者没有原则&#xff0c;即便你有原则&#xff0…

【APUE】进程间通信

目录 一、管道 1.1 匿名管道 1.2 命名管道 二、XSI IPC 2.1 概述 2.2 消息队列 2.2.1 msgget 2.2.2 msgsnd 2.2.3 msgrcv 2.2.4 msgctl 2.2.5 代码示例 2.3 信号量数组 2.3.1 semget 2.3.2 semop 2.3.3 semctl 2.3.4 代码示例 2.3 共享内存 2.3.1 shmget…

服务器如何做好入侵防护

不管是企业还是个人&#xff0c;网上业务都需要依赖于服务器&#xff0c;服务器一旦被黑客入侵&#xff0c;企业会面临很多安全风险&#xff0c;比如业务被中断、数据被窃取、被加密勒索、服务器不稳定等影响。入侵防护&#xff0c;主机安全也是目前网络安全防护的一个重点。关…

碳酸氢锂/硫酸锂溶液纯化除钙镁解决方案

碳酸锂是锂电行业阳极生产中的一个重要原材料&#xff0c;主要用于制造钴酸锂、镍酸锂、锰酸锂等电极材料&#xff0c;也用于充电 锂电池中作非水溶液电解质等&#xff0c;具有良好的电化学性能&#xff0c;应用领域还在不断扩大。工业级碳酸锂主含量&#xff08;Li2CO3&#x…

idea创建spring boot项目,java版本只能选择17和21

1.问题描述 java版本为"11.0.20"&#xff0c;idea2023创建spring boot项目时&#xff08;File->Project->Spring Initializr&#xff09;&#xff0c;java版本无法选择11&#xff0c;导致报错&#xff0c;如下图所示&#xff1a; 2.原因 spring2.X版本在2023…

java设计模式学习之【抽象工厂模式】

文章目录 引言抽象工厂模式简介定义与用途实现方式&#xff1a; 使用场景优势与劣势抽象工厂模式在spring中的应用银行和贷款服务示例代码地址 引言 在我们之前的讨论中&#xff0c;我们探索了工厂方法模式——一种简化单一产品创建的设计模式。现在&#xff0c;我们将视角转向…

QT linux下应用程序打包

一、应用程序app 1、应用程序的pro文件 2、 程序工作函数 3、app的UI界面 二、动态库lib 1、Lib类头文件 2、.cpp文件 三、对应用程序和动态库进行构建 1、对动态库进行qmake,然后进行构建 2、对应用程序进行qmake&#xff0c;然后进行构建 3、查看构建目录 四、编写脚本 …

零基础学编程轻松学编程,分享一款中文编程工具,编程构件简介

零基础学编程轻松学编程&#xff0c;分享一款中文编程工具&#xff0c;编程构件简介 中文编程开发语言工具编辑区界面截图如上图。 给大家分享一款中文编程工具 零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#…

Mac苹果视频剪辑:Final Cut Pro Mac

Final Cut Pro是一款由Apple公司开发的专业视频非线性编辑软件&#xff0c;是业界著名的视频剪辑软件之一。它最初发布于1999年&#xff0c;是Mac电脑上的一款独占软件。Final Cut Pro具有先进的剪辑工具、丰富的特效和颜色分级、音频处理等功能&#xff0c;使得用户可以轻松地…

Java后端开发——MVC商品管理程序

Java后端开发——MVC商品管理程序 本篇文章内容主要有下面几个部分&#xff1a; MVC架构介绍项目环境搭建商品管理模块Servlet代码重构BaseServlet文件上传 MVC 是模型-视图-控制器&#xff08;Model-View-Controller&#xff09;&#xff0c;它是一种设计模式&#xff0c;也…

打破限制!MySQL 5.7至8.0跨版本迁移,1分钟搞定多版本数据迁移

在上个月&#xff0c;MySQL 5.7 正式结束了生命周期&#xff0c;即EOL&#xff08;End of Life&#xff09;&#xff0c;意味着Oracle将不再为 MySQL 5.7 提供技术支持&#xff0c;包括Bug修复或安全漏洞&#xff0c;大大增加了使用数据库的风险。在全球关系型数据库市场中&…

WinMerge使用教程,WinMerge下载

一、下载 官方下载 WinMerge - You will see the difference… 官方地址&#xff1a;https://winmerge.org/ 阿里云盘下载 文件内容对比工具WinMerge2.16.25.25 https://www.alipan.com/s/r7MzudB235x 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘…

Webpack——Webpack简介

1、什么是Webpack&#xff1f; Webpack是一个开源的JavaScript模块打包工具&#xff0c;其最核心的功能是解决模块之间的依赖&#xff0c;把各个模块按照特定的规则和顺序组织在一起&#xff0c;最终合并为一个JS文件&#xff08;有时会有多个&#xff0c;这里讨论的只是最基本…