六、Spring Boot异常处理
Spring Boot中提供了五中处理异常的方法,按异常处理范围可划分为局部捕获异常和全局捕获异常两类。
6.1 自定义错误页面
自定义错误页面,顾名思义也就是自己定义一个显示错误信息的页面,让错误信息显示出来。
那么为什么要让错误信息显示出来呢?我们都知道当我们的代码出现逻辑或者其他异常的时候,页面中会给我们显示出来默认的页面错误的信息(如下图所示),这是因为在 SpringBoot中提供了一个叫BasicExceptionController来处理 /error 请求,然后跳转到默认显示异常的页面来展示异常信息。
当然我们可以自定义一个异常页面来显示异常的信息,这样更方便的查找异常信息,注意这个页面必须在/templates/下定义一个名为:error的页面才可以显示!!。
异常测试:
@Controller
public class ExceptionController {
/**
* 测试异常处理
* @return
*/
@GetMapping("/testException")
public String testException(){
System.out.println(1/0);
return "index";
}
}
自定义异常显示页面error.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>异常显示页面</h2>
<div th:text="${msg}"></div>
</body>
</html>
注意(敲重点!!):
这个自定义页面必须在/templates/下定义,名字必须为:error,这样才会显示错误信息!!!
6.2 @ExceptionHandler注解
@ExceptionHandler注解是在Controller内部创建方法处理异常,但是只能处理使用@ExceptionHandler注解的方法的Controller的异常,对于其他Controller的异常却不能处理,如果其他的Controller确实需要进行异常处理,只能再使用同样的方法使用@ExceptionHandler注解捕获异常,很明显,这种方式会很麻烦,所以一般不推荐使用。
该方法需要有一个返回值,目的是封装异常信息以及视图的指定:
package cn.boot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.Map;
@Controller
public class ExceptionController {
/**
* 测试异常处理
* @return
*/
@GetMapping("/testException")
public String testException(){
System.out.println(1/0);
return "index";
}
/**
* 集合接收异常信息
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String,String> exceptionHandler1(Exception e){
Map<String,String> map = new HashMap<>();
map.put("code","100");
map.put("msg","Map返回异常信息100"+e.getMessage());
return map;
}
/**
* 视图对象接收异常信息
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
public ModelAndView exceptionHandler2(Exception e){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","ModelAndView返回异常信息100:"+e);
modelAndView.setViewName("error");
return modelAndView;
}
}
注意:
这两种返回异常信息的方式只可使用一种,不能两个一起使用!
6.3 @ControllerAdvice+@ExceptionHandler注解
@ControllerAdvice+@ExceptionHandler注解注解创建一个能够处理异常的全局异常类,在该类上需要添加@ControllerAdvice注解。
package cn.boot.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String,String> exceptionHandler1(Exception e){
Map<String,String> map = new HashMap<>();
map.put("code","101");
map.put("msg","Map返回异常处理信息101:"+e.getMessage());
return map;
}
@ExceptionHandler(value = Exception.class)
public ModelAndView exceptionHandler2(Exception e){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","ModelAndView返回异常信息处理信息101:"+e);
modelAndView.setViewName("error");
return modelAndView;
}
}
注意:
这两种返回异常信息的方式只可使用一种,不能两个一起使用!
6.4 配置SimpleMappingExceptionResolver处理异常
配置SimpleMappingWxceptionResolver处理异常是在全局异常类中添加一个方法完成异常的统一处理,缺点是不能将详细的异常信息显示到页面,该方法的返回值类型必须是SimpleMappingExceptionResolver。
package cn.boot.controller;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.Properties;
@Configuration
public class SimpleMappingException {
@Bean
public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
//两个参数,一个是异常的类型(注意必须是异常类型的全名) 另一个是视图名称
properties.put("java.lang.ArithmeticException","error1");
properties.put("java.lang.NullPointException","error2");
resolver.setExceptionMappings(properties);
System.out.println(resolver);
return resolver;
}
}
error1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>java.lang.ArithmeticException异常信息</h2>
</body>
</html>
error2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>java.lang.NullPointException异常信息</h2>
</body>
</html>
6.5 实现 HandlerExceptionResolver 接口处理异常
自定义HandlerExceptionResolver类处理异常是通过实现HandlerExceptionResolver接口做全局异常处理。
package cn.boot.controller;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Configuration
public class GlobalException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("error");
modelAndView.addObject("msg","实现接口HandlerExceptionResolver显示的异常信息:"+e.toString());
return modelAndView;
}
}
error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>异常显示页面</h2>
<div th:text="${msg}"></div>
</body>
</html>
6.6 小总结
- 这些实现异常处理的方法中每次只使用一种即可,切记不可全部使用,否则会报错;
- 在Map和ModelAndView两种方式实现视图的指定时,Map返回的是一个json格式的数据,可自定义显示异常的页面,ModelAndView返回的是一个对象,默认跳转到error页面显示异常信息。