六、Spring Boot异常处理

Spring Boot中提供了五中处理异常的方法,按异常处理范围可划分为局部捕获异常和全局捕获异常两类。

6.1 自定义错误页面

自定义错误页面,顾名思义也就是自己定义一个显示错误信息的页面,让错误信息显示出来。

那么为什么要让错误信息显示出来呢?我们都知道当我们的代码出现逻辑或者其他异常的时候,页面中会给我们显示出来默认的页面错误的信息(如下图所示),这是因为在 SpringBoot中提供了一个叫BasicExceptionController来处理 /error 请求,然后跳转到默认显示异常的页面来展示异常信息。

springboot 统一异常页面 springboot的异常处理_Spring Boot异常处理


当然我们可以自定义一个异常页面来显示异常的信息,这样更方便的查找异常信息,注意这个页面必须在/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>

springboot 统一异常页面 springboot的异常处理_spring boot_02

注意(敲重点!!):
这个自定义页面必须在/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;
    }
}

注意:
这两种返回异常信息的方式只可使用一种,不能两个一起使用!

springboot 统一异常页面 springboot的异常处理_异常信息_03

springboot 统一异常页面 springboot的异常处理_Spring Boot异常处理_04

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;
    }
}

注意:
这两种返回异常信息的方式只可使用一种,不能两个一起使用!

springboot 统一异常页面 springboot的异常处理_springboot 统一异常页面_05


springboot 统一异常页面 springboot的异常处理_springboot 统一异常页面_06

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>

springboot 统一异常页面 springboot的异常处理_异常信息_07

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>

springboot 统一异常页面 springboot的异常处理_springboot 统一异常页面_08

6.6 小总结

  • 这些实现异常处理的方法中每次只使用一种即可,切记不可全部使用,否则会报错;
  • 在Map和ModelAndView两种方式实现视图的指定时,Map返回的是一个json格式的数据,可自定义显示异常的页面,ModelAndView返回的是一个对象,默认跳转到error页面显示异常信息。