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

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


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. 最后:

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值