当前位置: 首页 > news >正文

十二,Spring Boot 异常处理(自定义异常页面,全局异常,自定义异常)

十二,Spring Boot 异常处理(自定义异常页面,全局异常,自定义异常)

文章目录

  • 十二,Spring Boot 异常处理(自定义异常页面,全局异常,自定义异常)
  • 1. 基本介绍
  • 2. 自定义异常页面
  • 3. 全局异常
  • 4. 自定义异常
  • 5. 补充:拦截器 VS 过滤器
  • 6. 总结:
  • 7. 最后:


1. 基本介绍

默认情况下,Spring Boot 提供 / error 处理所有的错误的映射,也就是说当出现错误时,
Spring Boot 底层会请求转发到 /error 这个映射。
注意是:请求转发,不是重定向的。

Spring Boot 它是有自己的默认的处理机制的,在你创建的一个 Spring Boot 项目去访问一个没有的路径会发现,Spring Boot 它是会弹出来这样的信息。

在这里插入图片描述

这是 Spring Boot 给我们内置好的,编写好的,默认配置好的 错误信息页面。

如下是 Spring Boot 检索,显示对应错误页面存放位置的结构视图:官网地址:https://docs.spring.io/spring-boot/reference/web/reactive.html#web.reactive.webflux.error-handling.error-pages

在这里插入图片描述

src/+- main/+- java/|   + <source code>+- resources/+- public/+- error/|   +- 404.html+- <other public assets>
src/+- main/+- java/|   + <source code>+- resources/+- templates/+- error/|   +- 5xx.mustache+- <other templates>

一旦项目发生了错误,Spring Boot 会根据对应错误状态码,上述的结构路径,上找到对应的错误页面。

2. 自定义异常页面

根据上述的说明,我们根据在 Spring Boot 默认错误页面的检索路径结构,创建对应的目录,同时存放对应的错误页面。如下图所示:

在这里插入图片描述

自定义 404.html,500.html, 4xx.html ,5xx.html 当发生相应错误时,显示自定义的页面信息.

首先,我们先定义前端错误的 4开头 的错误页面。

在这里插入图片描述

在定义两个后端错误的 5 开头 的错误页面。

在这里插入图片描述

编写好之后,我们就可以模拟错误异常,试试,Spring Boot是否会走我们的自定义的错误页面,在前端展示出来

测试:4开头的,前端错误

在这里插入图片描述

在这里插入图片描述

测试: 5开头的后端错误的

在这里插入图片描述

3. 全局异常

全局异常:就是作用于整个项目的异常的,也可以是整个项目的异常页面。

@ControllerAdvice + @ExceptionHandler 这两个注解定义全局异常。

在这里插入图片描述

在这里插入图片描述

底层是 ExceptionHandlerExceptionResolver 支持的,不可以省略其它的。

在这里插入图片描述

定义一个全局异常。

在这里插入图片描述

package com.rainbowsea.springboot.exception;import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;@Slf4j
@ControllerAdvice  // 使用它可以标识一个全局异常处理器/对象
public class GlobalExceptionHandler {// 1.编写方法,处理指定异常,比如:我们处理算术异常,可以指定多个异常// 2. 这里要处理的异常,由程序员来指定// 3. Exception e : 表示异常发生后,传递的异常对象// 4. Model model : 可以将我们的异常信息,放入 model ,再放入到请求域当中,并传递显示页面@ExceptionHandler({ArithmeticException.class, NullPointerException.class})public String handleAritException(Exception e, Model model) {log.info("异常信息={}",e.getMessage());  // 自定义的异常也是可以获取到的// 这里老师将发生的异常放入到model,可以再错误页面取出显示model.addAttribute("msg",e.getMessage());return "/error/global";  // 视图地址}
}

在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>全局异常</title>
</head>
<body>
<h1>全局异常处理/错误,发生:)</h1>
异常/错误信息: <h1 th:text="${msg}"></h1></body>
</html>

运行测试:

在这里插入图片描述

注意:全局异常> 自定义异常>内置异常 的优先级

当一个异常,即在自定义异常当中,也在全局异常当中定义处理了,那么Spring Boot 优先走 全局异常/(全局异常的页面)

在这里插入图片描述

当发生ArithmeticException,NullPointerException,不使用默认异常的机制,匹配的 xxx.html,而是显示全局异常机制指定的错误页面。所以,全局异常可以说是最高优先级了。

4. 自定义异常

如果 Spring Boot 提供的异常不能满足开发需求,程序员也可以自定义异常。

  1. @ResponseStatus + 自定义异常。

在这里插入图片描述

  1. 底层是 ResponseStatusExceptionResolver。

在这里插入图片描述

  1. 当抛出自定义异常后,仍然会根据状态码,去匹配使用 xxx.html 显示。

关于自定义异常,我们在Java基础中是讲解过 => 融合贯通

  • @ResponseStatus(value = HttpStatus.FORBIDDEN) : 表示发生 AccessException异常,我们通过http
  • 协议返回的状态码 403
  • 这个状态码和自定义异常的对应关系是由程序员来决定【尽量合理来设置】

演示: 自定义一个异常AccessException,当用户访问某个无权访问的路径时,抛出该异常,显示自定义异常状态。

下面我们就自定义一个名为:AccessException 的异常,该自定异常的状态码为:

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.springboot.exception;import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;/*** 关于自定义异常,我们在Java基础中是讲解过 => 融合贯通** @ResponseStatus(value = HttpStatus.FORBIDDEN) : 表示发生 AccessException异常,我们通过http* 协议返回的状态码 403* 这个状态码和自定义异常的对应关系是由程序员来决定【尽量合理来设置】*/@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class AccessException extends  RuntimeException{// 老师提供一个构造器,可以指定信息public AccessException(String message) {super(message);System.out.println("AccessException 有参数构造方法被调用");}// 显示的定义一个无参构造器public AccessException() {System.out.println("AccessException 无参数构造方法被调用");}
}

运行测试:

在这里插入图片描述

package com.rainbowsea.springboot.controller;import com.rainbowsea.springboot.exception.AccessException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
public class MyErrorController {// 编写方法, 模拟一个AccessException@GetMapping("/err3")public String err3(String name) {// 如果用户不是tom,我们就认为:无权访问-模拟if (!"tom".equals(name)) {throw new AccessException("我们自己定义的异常");// 这里编写了放入的信息new AccessException("我们自己定义的异常") ,可以进行在后面放入// 到前端获取到,并显示出来。/*log.info("异常信息={}",e.getMessage());  // 自定义的异常也是可以获取到的// 这里老师将发生的异常放入到model,可以再错误页面取出显示model.addAttribute("msg",e.getMessage());*/}return "manage"; // 视图地址}}

执行效果如图:浏览器: http://locathos:8080/err3

在这里插入图片描述

在这里插入图片描述

简单的说:其实就是我们在 java se 当中学习到自定义异常处理

如果把自定义异常类型,放在全局异常回来,那么仍然走全局异常处理机制。
简单的说:我们自定义的异常类型,也是可以放到全局异常当中的。

在这里插入图片描述

运行测试:注意:全局异常的优先级比自定义异常更高,所以当一个异常,即定义在了“自定义异常” ,也定义在了“全局异常”当中时,优先执行全局异常的错误页面

运行测试:

在这里插入图片描述

5. 补充:拦截器 VS 过滤器

  • 使用范围不同:
  1. 过滤器实现是 javax.servlet.Filter 接口,而这个接口在 Servlet 规范中定义的,也就是说,过滤器 Filter 的使用依赖于 Tomcat 等容器,Filter 只能在 web 程序中使用。
  2. 拦截器(Interceptor) 它是一个 Spring 组件,并由 Spring 容器管理,并不依赖 Tomcat 等容器,是可以单独使用的,不仅能应用在 Web 程序中,而可以用于 Application 等程序中。
  • 过滤器 和 拦截器 的触发时机不同:

在这里插入图片描述

  1. 过滤器 Filter 是在请求进入容器后,但在进入 Servlet 之前进行预处理。请求结束时 Servlet 处理完以后。
  2. 拦截器 Interceptor 是在请求进入 servlet 后,在进入 Controller 控制器之后进行预处理的,Controller 中渲染了对应的视图之后,请求结束。
  • 说明:过滤器不会处理请求转发,拦截器会处理请求转发。
  1. 说明:过滤器不会处理请求转发,拦截器会处理请求转发。因为过滤器是自己内部进行过滤转发的,会先找自己同一层的内部的映射,如果没有找到才会走拦截器需要的。
  2. 至于过滤器和拦截器的原理和机制,过滤器在JavaWeb 有所说明,大家可以移步至✏️✏️✏️ JavaWeb 中 Filter过滤器-CSDN博客

6. 总结:

  1. 默认情况下,Spring Boot 提供 / error 处理所有的错误的映射,也就是说当出现错误时,
    Spring Boot 底层会请求转发到 /error 这个映射。**注意是:请求转发,不是重定向的。 **
  2. 稍微记忆一下,Spring Boot,显示对应错误页面存放位置的结构视图:官网地址:https://docs.spring.io/spring-boot/reference/web/reactive.html#web.reactive.webflux.error-handling.error-pages

在这里插入图片描述

  1. 自定义异常错误页面,要根据 Spring Boot检索的错误页面的目录,来存放错误该错误页面的文件

  2. 全局异常:就是作用于整个项目的异常的,也可以是整个项目的异常页面。

    @ControllerAdvice + @ExceptionHandler 这两个注解定义全局异常。

  3. 注意:全局异常(/全局异常错误页面)> 自定义异常(/自定义异常错误页面)>内置异常(/内置异常错误页面)的优先级

  4. 注意:拦截器和过滤器的区别。

7. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Golang数据流处理:掌握Reader和Writer接口的技巧
  • C++设计模式——Mediator中介者模式
  • RAII 与 std::lock_guard 在 C++ 中的应用:自动化互斥锁管理与线程安全
  • 【JavaScript】数据结构之字典 哈希表
  • HTML5下<hr>标签的CSS样式定制
  • 关于Linux Makefile的一些函数知识foreach、if、call、origin、shell、error和warning
  • 如何使用myabtis log plugin插件展示出数据库查询语句
  • 【C++11】智能指针
  • STM32常用数据采集滤波算法
  • Java | Leetcode Java题解之第400题第N位数字
  • 决策树基础概论
  • Android 13 固定systemUI的状态栏为黑底白字,不能被系统应用或者三方应用修改
  • flutter widget.onPressed回调无效
  • 微软面向所有用户推出 Xbox Game Pass Standard
  • 四、链表————相关概念详解
  • (三)从jvm层面了解线程的启动和停止
  • android图片蒙层
  • Invalidate和postInvalidate的区别
  • JAVA多线程机制解析-volatilesynchronized
  • mysql 数据库四种事务隔离级别
  • Python语法速览与机器学习开发环境搭建
  • spark本地环境的搭建到运行第一个spark程序
  • Spring Boot MyBatis配置多种数据库
  • Travix是如何部署应用程序到Kubernetes上的
  • windows下mongoDB的环境配置
  • windows下使用nginx调试简介
  • 第2章 网络文档
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 前端面试总结(at, md)
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 三分钟教你同步 Visual Studio Code 设置
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • 整理一些计算机基础知识!
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • # windows 安装 mysql 显示 no packages found 解决方法
  • (1)bark-ml
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (第30天)二叉树阶段总结
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (七)Activiti-modeler中文支持
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (十三)Flask之特殊装饰器详解
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • .“空心村”成因分析及解决对策122344
  • .Mobi域名介绍
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .NetCore发布到IIS
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件