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

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

文章目录

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

java 复制代码
src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>
java 复制代码
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 支持的,不可以省略其它的。

定义一个全局异常。

java 复制代码
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";  // 视图地址
    }
}
html 复制代码
<!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 的异常,该自定异常的状态码为:

java 复制代码
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 无参数构造方法被调用");

    }
}

运行测试:

java 复制代码
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. 最后:

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

相关推荐
BD_Marathon4 小时前
【Flink】部署模式
java·数据库·flink
鼠鼠我捏,要死了捏6 小时前
深入解析Java NIO多路复用原理与性能优化实践指南
java·性能优化·nio
ningqw6 小时前
SpringBoot 常用跨域处理方案
java·后端·springboot
你的人类朋友6 小时前
vi编辑器命令常用操作整理(持续更新)
后端
superlls7 小时前
(Redis)主从哨兵模式与集群模式
java·开发语言·redis
胡gh7 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
一只叫煤球的猫8 小时前
看到同事设计的表结构我人麻了!聊聊怎么更好去设计数据库表
后端·mysql·面试
uzong8 小时前
技术人如何对客做好沟通(上篇)
后端
叫我阿柒啊8 小时前
Java全栈工程师面试实战:从基础到微服务的深度解析
java·redis·微服务·node.js·vue3·全栈开发·电商平台
颜如玉8 小时前
Redis scan高位进位加法机制浅析
redis·后端·开源