10、SpringBoot之异常处理
第一种:自定义错误页面
- SpringBoot默认的处理异常的机制:SpringBoot默认的已经提供了一套处理异常的机制。
- 一旦程序中出现了异常SpringBoot会向/error的url发送请求。
- SpringBoot中提供了一个名为BasicErrorController来处理/error请求,然后跳转到默认显示异常的页面来展示异常信息。
由于没有找到/error映射的文件,所以将错误返回到springboot的页面将异常信息进行输出
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Apr 23 23:29:38 CST 2020
There was an unexpected error (type=Internal Server Error, status=500).
No message available
如果需要将所有异常统一跳转到自定义的错误页面,需要在**src/main/resources/templates** 目录下创建**error.html**页面。注意:页面必须叫**error**
当有一个命名为error的错误页面时,出现异常则直接跳到该页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
出现错误异常
</body>
</html>
缺点:当捕获到不同的异常想要跳转至不同页面是,自定义错误页面没办法实现;
第二种:通过@ExceptionHandler注解处理异常
- 修改Controller
- 创建页面
@ExceptionHandler注解可以做到根据不同异常类型,来跳转到不同的页面进行异常信息的显示
我们需要在能够产生异常的方法所在的controller当中再添加一个处理异常的方法
@Controller
public class UsersController {
/**
* 定义一个会报出空指针异常的方法
* @return
*/
@RequestMapping("showInfo")
public String showInfo(){
String str = null;
str.length();
return "ok";
}
/**
* 该方法会处理当前这个controller出现的空指针异常
* @param e
* @return
*/
@ExceptionHandler(value = {java.lang.NullPointerException.class})
public ModelAndView nullpointExceptionHandler(Exception e){
// e对象会接收放错传入的异常对象
ModelAndView mv = new ModelAndView();
mv.addObject("err", e);
mv.setViewName("error1");
return mv;
}
}
error1页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
出错了。。。
<span th:text="${err}"></span>
</body>
</html>
缺点:单用一个@ExceptionHandler注解只能作用他当前的controller进行异常处理,如果其他controller也出现同样的异常是不会进行处理的,复用性差,这个时候需要@ControllerAdvice结合使用,使异常处理方法可以全局使用。
第三种:通过@ControllerAdvice与@ExceptionHandler注解处理异常
- 创建全局异常处理类
Controller
@Controller
public class UsersController {
/**
* 定义一个会报出空指针异常的方法
* @return
*/
@RequestMapping("showInfo")
public String showInfo(){
String str = null;
str.length();
return "ok";
}
/**
* 定义一个会报出算术异常的方法
* @return
*/
@RequestMapping("showInfo2")
public String showInfo2(){
int i = 10/0;
return "ok";
}
}
全局异常处理类
/**
* 全局异常处理类
*/
@ControllerAdvice
public class GlobalException {
/**
* 处理空指针异常
* @param e
* @return
*/
@ExceptionHandler(value = {java.lang.NullPointerException.class})
public ModelAndView nullpointExceptionHandler(Exception e){
// e对象会接收放错传入的异常对象
ModelAndView mv = new ModelAndView();
mv.addObject("err", e);
mv.setViewName("error1");
return mv;
}
/**
* 处理算术异常
* @param e
* @return
*/
@ExceptionHandler(value = {java.lang.ArithmeticException.class})
public ModelAndView ArithmeticExceptionHandler(Exception e){
// e对象会接收放错传入的异常对象
ModelAndView mv = new ModelAndView();
mv.addObject("err", e);
mv.setViewName("error2");
return mv;
}
}
当项目中出现空指针异常都会被该方法拦截并进行处理
全局异常处理类有个缺点就是会定义特别多的方法来处理异常
第四种,通过SimpleMappingExceptionResolver对象处理异常
SimpleMappingExceptionResolve可以通过一个方法来处理多个不同的异常,并且跳转到不同的页面
/**
* 全局异常
* SimpleMappingExceptionResolver
*/
@Configuration
public class GloballException2 {
/**
* 此方法返回值必须是SimpleMappingExceptionResolver,方法名可以随意
* @return
*/
@Bean
public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
//简单映射异常解析,也是可以根据异常类型和需要跳转视图做一个映射处理
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
/**
* 参数1:异常类型(全名)
* 参数2:跳转页面(视图)
*/
//这里只是做,视图与异常类型的映射,并没有传递异常对象,所以跳转到对应的视图后并没有传递异常对象过去
properties.put("java.lang.NullPointerException","error3");
properties.put("java.lang.ArithmeticException","error4");
resolver.setExceptionMappings(properties);
return resolver;
}
}
error3.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
出错了。。。空指针异常
</body>
</html>
error4.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
<meta charset="UTF-8">
<title>error2</title>
</head>
<body>
出错了。。。算术异常
</body>
</html>
缺点:只能做异常和视图的映射,不能获取到异常信息
第五种,通过自定义HandlerExceptionResolver对象处理异常
- 创建全局异常处理类
全局异常处理类 GloballException3
/**
* 自定义HandlerExceptionResolve对象处理异常
* 必须要实现HandlerExceptionResolver
*/
@Configuration
public class GloballException3 implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
ModelAndView mv = new ModelAndView();
//判断不同异常类型,做不同视图的跳转
if(e instanceof NullPointerException){
mv.setViewName("error5");
}
if(e instanceof ArithmeticException){
mv.setViewName("error6");
}
//不管跳到哪个视图,携带的异常信息不变所以不用带入if判断里面
mv.addObject("error", e.toString());
return mv;
}
}
error5.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
<meta charset="UTF-8">
<title>error5</title>
</head>
<body>
出错了。。。空指针异常
<span th:text="${error}"></span>
</body>
</html>
error6.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
<meta charset="UTF-8">
<title>error6</title>
</head>
<body>
出错了。。。算术异常
<span th:text="${error}"></span>
</body>
</html>