第十一节 SpringBoot捕获全局异常

亮子 2021-05-11 13:45:22 11624 0 0 0

1、全局异常的意义

1)、客户端无法处理

在项目中经常出现系统异常的情况,比如NullPointerException等等。如果默认未处理的情况下,springboot会响应默认的错误提示,这样对用户体验不是友好,系统层面的错误,用户不能感知到,即使为500的错误,可以给用户提示一个类似服务器开小差的友好提示等。

2)、统一处理异常

异常发生,而我们又没有及时处理,这是也可以通过全局异常处理机制,记录异常信息并格式化异常信息返回给客户端,让客户端知道,服务器出现了异常,可以根据情况给用户相应的提示。

2、全局异常处理流程

1)、创建全局异常处理类

@ControllerAdvice
public class GlobalExceptionHandler {

    //空指针异常
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseBody
    public String nullPointerExceptionHandler(NullPointerException ex) {
        ex.printStackTrace();
        return "NullPointerException捕获了";
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    @ResponseBody
    public String classCastExceptionHandler(ClassCastException ex) {
        ex.printStackTrace();
        return "ClassCastException捕获了";
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    @ResponseBody
    public String iOExceptionHandler(IOException ex) {
        ex.printStackTrace();
        return "IOException捕获了";
    }
}

2)、添加全局异常捕获注解

@ControllerAdvice

3)、修改controller

修改controller,增加产生异常接口,代码如下:

    @RequestMapping(value = "/runerr")
    public String runError(Model model) {
        System.out.println("runError .......");

        String msg = null;
        if(msg.length()>0)
            System.out.println("hello world");

        return "index";
    }

4)、其他异常

有一些系统异常,通过之前的方法,还是无法捕获的,比如经常出现的404错误。那么这种错误怎么捕获呢?可以分为以下几个步骤:

(1)修改配置文件

修改配置文件application.properties的内容如下:

# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)
spring.mvc.throw-exception-if-no-handler-found=true
# 是否开启默认的资源处理,默认为true
spring.resources.add-mappings=false

上述配置在SpringBoot 2.5.x以后过时了,需要使用一下配置

# 出现错误时, 直接抛出异常(便于异常统一处理,否则捕获不到404)
spring.mvc.throw-exception-if-no-handler-found=true
# 是否开启默认的资源处理,默认为true
spring.web.resources.add-mappings=false
2)、异常拦截类的编写
package com.shenmazong.shenmablogserver.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.IOException;

/**
 * @Description: 全局异常
 * @Author david
 * @Date 2021/5/3 16:55
 * @Copyright www.shenmazong.com
 * @Version V1.0.0
 */

@Slf4j
@ControllerAdvice
public class ExceptionController {
    @ExceptionHandler(Exception.class)
    public ModelAndView customException(Exception ex) {
        ex.printStackTrace();
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", ex.getMessage());
        mv.setViewName("page_error");
        return mv;
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handle404(Exception ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "您访问的页面不存在!");
        return "page_error";
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(HttpServerErrorException.InternalServerError.class)
    public String handle500(Exception ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "服务器内部错误!");
        return "page_error";
    }

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    public String runtimeExceptionHandler(RuntimeException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "运行时发生错误!");
        return "page_error";
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public String nullPointerExceptionHandler(NullPointerException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "空指针错误!");
        return "page_error";
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public String classCastExceptionHandler(ClassCastException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "类型转换错误!");
        return "page_error";
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    public String iOExceptionHandler(IOException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "IO错误!");
        return "page_error";
    }

    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public String noSuchMethodExceptionHandler(NoSuchMethodException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "未知方法错误!");
        return "page_error";
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex, Model model) {
        ex.printStackTrace();
        model.addAttribute("message", "数组越界错误!");
        return "page_error";
    }
}

2、总结

全局异常主要注解:

  • @ControllerAdvice 返回web页面
  • @RestControllerAdvice 返回json格式数据
  • @ExceptionHandler
@ExceptionHandler(NoHandlerFoundException.class)
@ExceptionHandler(value = NullPointerException.class)