SpringBoot中四种异常处理的方式

Java知识点总结:想看的可以从这里进入

2.14、异常处理

2.14.1、定义错误页面

SpringBoot 默认的异常处理机制:一旦程序中出现了异常 SpringBoot 就会请求 /error 的 url 。在 SpringBoot 中提供了一个叫 BasicExceptionController 来处理 /error 请求,它会跳转到默认显示异常的页面来展示异常信息。

image-20220925134115681

不过我们可以在 resources/templates/ 内添加 error 页面来自定义异常页面,名字和路径不能更改,因为BasicExceptionController 默认跳转到这此路径。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>恭喜你啊,你进入了异常页面</h1>
</body>
</html>
image-20220925134544868

2.14.2、局部异常

在SpringBoot中可以使用 @ExceptionHandler 注解处理局部异常,它是在Controller 内定义一个方法,内部写发生异常后的处理逻辑,然后在方法上添加 @ExceptionHandler(value={}) 注解,表明要捕捉的异常,然后此Controller内发生异常时就会使用此方法进行处理。

  • 定义一个错误页面

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
        </head>
        <body>
            <h1>恭喜你啊,你进入了异常页面</h1>
            <p th:text="${msg}"></p>
        </body>
    </html>
    
  • Controller:不写@ExceptionHandler

    @Controller
    @RequestMapping("/test")
    public class HelloController {
          
          
        @GetMapping("/hello")
        public String hello(String name){
          
          
            int i = 9/0;
            return "login";
        }
    }
    
    image-20220925170313492
  • 此时在Controller中 添加@ExceptionHandler注解,并完成相关的方法,发生异常时做处理

    @Controller
    @RequestMapping("/test")
    @Slf4j
    public class HelloController {
          
          
        @GetMapping("/hello")
        public String hello(String name){
          
          
            int i = 9/0;
            return "login";
        }
        @ExceptionHandler(value = {
          
          Exception.class})
        public String exceptionHandling(Model model,Exception e){
          
          
            model.addAttribute("msg","发生了异常:"+e.getMessage());
            log.info(e.getMessage());
            return "error";
        }
    }
    
    image-20220925170609521

2.14.3、全局异常

使用 @ExceptionHandler 注解处理的是局部的异常,它仅仅在一个Controller中有效,我们一般要求进行全局的异常处理,也就是对所有的Controller都生效。

创建一个专门处理异常的类,然后在类上使用 @ControllerAdvice 注解,然后内部创建异常处理的方法,并且在方法上添加 @ExceptionHandler 注解后,这个类就能够处理全局异常。

  • 定义全局异常处理类

    @ControllerAdvice
    @Slf4j
    public class HandleException {
          
          
        @ExceptionHandler
        public String exceptionHandling(Model model, Exception e){
          
          
            model.addAttribute("msg","全局异常处理:"+e.getMessage());
            log.info(e.getMessage());
            return "error";
        }
    }
    
  • 将Controller 中原本的局部异常方法去掉

    @Controller
    @RequestMapping("/test")
    public class HelloController {
          
          
        @GetMapping("/hello")
        public String hello(String name){
          
          
            int i = 9/0;
            return "login";
        }
    }
    
    image-20220925171551586

在使用全局异常处理的时候,一样可以使用局部的异常处理,它的优先级高于全局异常处理,也就是说一个Controller定义了局部异常处理方法后,就不会再执行全局的异常处理了

上面的例子给Controller添加局部异常处理方法

@Controller
@RequestMapping("/test")
public class HelloController {
    
    
    @GetMapping("/hello")
    public String hello(String name){
    
    
        int i = 9/0;
        return "login";
    }
    @ExceptionHandler(value = {
    
    Exception.class})
    public String exceptionHandling(Model model,Exception e){
    
    
        model.addAttribute("msg","局部异常处理:"+e.getMessage());
        return "error";
    }
}
image-20220925171857441

2.14.4、异常配置类

除了@ControllerAdvice + @ExceptionHandler 注解能进行全局的异常处理外,还可以通过配置类创建SimpleMappingExceptionResolver 对象处理异常,此对象也是全局的。

但是使用SimpleMappingExceptionResolver 获取不到异常对象,无法得知异常消息,但是它可以在一个方法内判断多个异常种类,根据不同的异常,跳转到不同的页面。

@Configuration
public class MyExceptionConfig {
    
    

    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
    
    
        System.out.println("处理异常");
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        //参数:异常类型全限定名,异常的视图名称
        properties.put("java.lang.Exception","error2");
        // properties.put()可以写多个,使不同的异常类型跳转到不同的异常页面
        resolver.setExceptionMappings(properties);
        return resolver;
    }
}

还是使用上面的Controller,但是注意需要将全局异常和局部异常都删除,SimpleMappingExceptionResolver 优先级三者里最小。

image-20220925173627469

2.14.5、异常处理接口

通过实现 HandlerExceptionResolver 接口,一样可以处理异常,这种处理的方式不仅可以获取到异常的对象,也可以根据不同的异常,跳转到不同的页面

@Configuration
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
    
    
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    
    
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", "HandlerExceptionResolver 接口处理异常:"+ex.getMessage());

         //可以根据不同的异常类型进行跳转
        if(ex instanceof ArithmeticException){
    
    
            modelAndView.setViewName("error");
        }else if(ex instanceof NumberFormatException){
    
    
            modelAndView.setViewName("error2");
        }

        return modelAndView;
    }
}

image-20220925174552362

2.14.6、优先级和区别

4种异常处理的优先级为:@ExceptionHandler的局部异常处理 > @ControllerAdvice + @ExceptionHandler 的全局异常处理 > HandlerExceptionResolver 接口的全局异常处理 > SimpleMappingExceptionResolver全局异常处理

@ExceptionHandler是局部异常处理,只能处理单个Controller的异常,其余三种能处理全局异常

HandlerExceptionResolverSimpleMappingExceptionResolver可以在一个方法内针对异常的不同种类做出不同的跳转,而@ControllerAdvice + @ExceptionHandler 的全局异常处理和 @ExceptionHandler局部异常处理 如果要实现不同异常类型跳转不同页面需要多个方法才能实现。

SimpleMappingExceptionResolver不能获取异常对象,其余三种都可以获取异常对象

猜你喜欢

转载自blog.csdn.net/yuandfeng/article/details/129726276