SpringBoot(异常处理)
1.基本介绍
2.debug异常处理机制
1.找到 DefaultErrorViewResolver
2.下断点
3.debug启动,浏览器输出一个不存在的页面
4.第一次查找 error/404
1.查看目前要找的视图名
2.准备去查找资源
3.准备从四个默认存放静态资源的路径来查找
4.从第一个静态资源的存放路径查找资源即在error目录下的404.html
5.在四个路径下都找不到error/404.html
5.第二次查找 error/4xx
1.准备进行第二次查找
2.这次要查找到error/4xx
3.依然从四个静态路径中查找,可想而知还是查不到
6.如果都查找不到,则创建一个ModelAndView对象返回
7.放行,返回错误页面
3.过滤器和拦截器的区别
1.示意图
2.对请求转发的处理
- 过滤器不会处理请求转发
- 拦截器会处理请求转发
3.过滤器和拦截器的执行流程示意图
4.自定义异常页面
1.需求分析
2.具体实现
1.注意事项
1.错误文件放置位置
- 错误页面的格式是
error/404.html
或者error/4xx.html
- 如果使用的模板引擎则放到templates目录下
- 如果没有使用模板引擎则放到四个默认存放静态资源的目录下即可
2.错误页面可以获取的错误信息(request域中)
2.在templates目录下存放几个错误页面
3.404.html 取出错误信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>404</h1>
状态码<h2 th:text="${status}"></h2>
错误信息<h2 th:text="${error}"></h2>
</body>
</html>
4.测试
5.MyErrorController.java 测试异常
package com.sun.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
/**
* @author 孙显圣
* @version 1.0
*/
@Controller
public class MyErrorController {
@GetMapping("/err")
public String err() {
int i = 10 / 0; //此时的错误是500
return "sss";
}
@PostMapping("/err2") //一会使用get的方式请求err2,这样会出现4开头的客户端错误
public String err2() {
return "sss";
}
}
6.测试
3.过滤器和拦截器在找不到资源下的执行流程
5.全局异常
1.基本说明
2.需求分析
3.具体实现
1.创建一个全局异常处理类 Global.java
package com.sun.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;
/**
* @author 孙显圣
* @version 1.0
*/
@ControllerAdvice //处理异常的Controller
@Slf4j
public class Global {
//编写方法处理指定的异常
@ExceptionHandler({ArithmeticException.class, NullPointerException.class}) //指定全局处理的异常
public String handerException(Exception e, Model model) {
System.out.println("异常信息:" + e.getMessage());
model.addAttribute("msg", e.getMessage()); //将异常信息放到request域中
return "/error/global"; //由于目前使用的模板引擎,所以这里返回的结果会通过路径拼接到templates下面的error/global.html
}
}
2.\resources\templates\error\global.html 处理全局异常的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>全局异常</h1>
错误信息:<h2 th:text="${msg}"></h2>
</body>
</html>
3.测试
6.默认异常和全局异常小结(使用模板引擎方式)
1.默认异常执行流程
- 出现异常,中央控制器向/error进行请求转发
- /error会从静态资源的存放路径(如果是模板引擎就是templates下面)查找对应的异常处理页面(以404为例)
- 首先查找error/404.html,返回一个ModelAndView对象
- 如果没有查找到就会查找error/4xx.html,返回一个ModelAndView对象
- 如果都没有查找到就会返回一个默认的ModelAndView对象
- 视图解析器根据得到的ModelAndView将请求转发到指定的异常处理页面
- 将异常处理页面响应到浏览器
2.全局异常
- 出现异常,优先查看全局异常处理类
- 如果里面有方法处理的该类型的异常,则按照方法的逻辑执行
- 如果没有则按照默认异常执行流程执行
7.自定义异常
1.基本介绍
2.需求分析
3.具体实现(使用默认异常处理机制)
1.编写自定义异常 AccessException.java
package com.sun.springboot.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* @author 孙显圣
* @version 1.0
* 自定义异常
*/
@ResponseStatus(HttpStatus.FORBIDDEN) //指定如果发生异常返回的状态码HttpStatus.FORBIDDEN 这里是403
public class AccessException extends RuntimeException { //继承RuntimeException则表示是一个异常类
//表示可以在抛出异常时,指定异常信息
public AccessException(String message) {
super(message);
}
//无参构造
public AccessException() {
}
}
2.触发自定义异常 MyErrorController.java
package com.sun.springboot.controller;
import com.sun.springboot.exception.AccessException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author 孙显圣
* @version 1.0
*/
@Controller
public class MyErrorController {
//触发自定义的异常
@GetMapping("/err3")
public String err3() {
throw new AccessException("自定义异常被触发!");
}
}
3.如果使用默认异常处理机制需要在静态资源文件夹下编写异常处理的html,error/403.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>自定义异常被触发</h1>
</body>
</html>
4.浏览器测试
8.SpringBoot异常处理小结
1.异常处理机制的类型
1.默认异常处理机制(明白原理即可)
- 到中央控制器,请求转发到/error
- 根据异常的状态码去静态资源下的error/xxx.html找到指定的文件
- 不论是否找到都会返回一个ModelAndView对象给视图解析器
- 视图解析器根据这个对象,请求转发到指定的error/xxx.html
- 将error/xxx.html返回到浏览器
- 需要注意的是,如果找不到指定的error/xxx.html文件则会返回一个默认创建的ModelAndView对象,最终在浏览器中体现的错误样式就是如下图:
一句话概括默认异常处理机制:根据异常的状态码来找到指定的error/xxx.html文件返回到浏览器
2.全局异常处理机制(掌握!)
- @ControllerAdvice + @ExceptionHandler({})注解可以创建全局异常处理类
- 如果出现异常,则优先会查找全局异常处理类中是否能够捕获到指定异常
- 如果可以捕获则按照捕获到异常的方法来进行异常处理
- 否则按照默认异常处理机制处理
2.自定义异常
1.编写自定义异常类
- 继承RuntimeException
- 在上面加注解@ResponseStatus()指定响应状态码
- 添加有参构造器可以在抛出该异常时指定异常信息
2.触发自定义异常
- 直接 throw new 异常类名(“异常信息”);
3.处理方式
- 自定义异常跟其他异常一样,也可以通过默认异常处理机制或全局异常处理机制来处理