前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot异常处理和退出

SpringBoot异常处理和退出

作者头像
星哥玩云
发布2022-09-15 14:17:31
1.2K0
发布2022-09-15 14:17:31
举报
文章被收录于专栏:开源部署

1、自定义错误页面

1.1、概述

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

1.2、自定义错误页面

在src/main/resources/templates 目录下创建 error.html 页面

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    出错了,请与管理员联系。。。
</body>
</html>

**注意:**名称必须叫 error,工程中要添加thymeleaf依赖

2、@ExceptionHandler 注解处理局部异常

2.1、Controller

代码语言:javascript
复制
@Controller
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        int result=10/0;
        return "index";
    }
    /**
     * java.lang.ArithmeticException
     * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
     图的指定
     * 参数 Exception e:会将产生异常对象注入到方法中
     */
    @ExceptionHandler(value={java.lang.ArithmeticException.class})
    public ModelAndView arithmeticExceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("error", e.toString());
        mv.setViewName("error");
        return mv;
    }
}

2.2、修改error.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>错误页面</title>
</head>
<body>
  <span th:text="${error}"></span>,请与管理员联系......
</body>
</html>

3、处理全局异常

3.1、@ControllerAdvice+@ExceptionHandler:

代码语言:javascript
复制
@ControllerAdvice
public class GlobalException {

    /**
     * java.lang.ArithmeticException
     * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
     图的指定
     * 参数 Exception e:会将产生异常对象注入到方法中
     */
    @ExceptionHandler(value={java.lang.ArithmeticException.class})
    public ModelAndView arithmeticExceptionHandler(Exception e){
        ModelAndView mv = new ModelAndView();
        mv.addObject("error", e.toString());
        mv.setViewName("error");
        return mv;
    }
}

3.2、配置 SimpleMappingExceptionResolver 处理异常

在全局异常类中添加一个方法完成异常的统一处理,代码如下:

代码语言:javascript
复制
@Configuration
public class GlobalException {

    /**
     * 该方法必须要有返回值。返回值类型必须是:
     * SimpleMappingExceptionResolver
     */
    @Bean
    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver resolver = new
                SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
    /**
     * 参数一:异常的类型,注意必须是异常类型的全名
    * 参数二:视图名称
    */
        mappings.put("java.lang.ArithmeticException", "error");
        //设置异常与视图映射信息的
        resolver.setExceptionMappings(mappings);
        return resolver;
    }
}

3.3、自定义 HandlerExceptionResolver 类处理异常

在全 局 异 常 处 理 类 中 实 现HandlerExceptionResolver 接口,代码如下:

代码语言:javascript
复制
@Configuration
public class GlobalException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response, Object handler,
                                         Exception ex) {
        ModelAndView mv = new ModelAndView();
        //判断不同异常类型,做不同视图跳转
        if(ex instanceof ArithmeticException){
            mv.setViewName("error");
        }
        mv.addObject("error", ex.toString());
        return mv;
    }
}

4、Spring Boot 应用正常退出

查看SpringApplication源码

代码语言:javascript
复制
public class SpringApplication {
    	......
        //退出方法
        public static int exit(ApplicationContext context, ExitCodeGenerator... exitCodeGenerators) {
        //断言conext不能为null
        Assert.notNull(context, "Context must not be null");
        byte exitCode = 0;
        int exitCode;
        try {
            try {
                //创建退出码生成器
                ExitCodeGenerators generators = new ExitCodeGenerators();
                //从Spring容器中获取所有的退出码生成器实例
                Collection<ExitCodeGenerator> beans = context.getBeansOfType(ExitCodeGenerator.class).values();
                generators.addAll(exitCodeGenerators);
                generators.addAll(beans);
                //获得退出码
                exitCode = generators.getExitCode();
                //如果退出码不为0
                if (exitCode != 0) {
                    //发布退出码事件监听
                    context.publishEvent(new ExitCodeEvent(context, exitCode));
                }
            } finally {
                close(context);
            }
        } catch (Exception var9) {
            var9.printStackTrace();
            exitCode = exitCode != 0 ? exitCode : 1;
        }
				//返回退出码
        return exitCode;
    }
}

案例:

验证程序退出时ExitCodeGenerators的getExitCode()方法执行了

代码语言:javascript
复制
@EnableAutoConfiguration
public class ExiteCodeGeneratorBootstrap {
		
    @Bean
    public ExitCodeGenerator exitCodeGenerator(){
        System.out.println("ExitCodeGenerator Bean 创建...");
        return ()->{
            System.out.println("执行退出码88");
            return 88;
        };
    }
		
    public static void main(String[] args) {
        //在非Web应用中退出
        SpringApplication.exit(new SpringApplicationBuilder(ExiteCodeGeneratorBootstrap.class)
                            .web(WebApplicationType.NONE)
                            .run(args));
    }
}

5、Spring Boot应用异常退出

源码:

代码语言:javascript
复制
    private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception, Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) {
        try {
            try {
                //处理退出码
                this.handleExitCode(context, exception);
                //如果Spring应用运行监听器不为null
                if (listeners != null) {
                    //监听异常退出
                    listeners.failed(context, exception);
                }
            } finally {
                //报告错误
                this.reportFailure(exceptionReporters, exception);
                //关闭Spring 上下文
                if (context != null) {
                    context.close();
                }

            }
        } catch (Exception var9) {
            logger.warn("Unable to close ApplicationContext", var9);
        }

        ReflectionUtils.rethrowRuntimeException(exception);
    }
    //退出码处理方法
    private void handleExitCode(ConfigurableApplicationContext context, Throwable exception) {
        //从异常中获取退出码
        int exitCode = this.getExitCodeFromException(context, exception);
        if (exitCode != 0) {
            if (context != null) {
               //如果退出码不为0,context不为null,发布退出码事件监听
                context.publishEvent(new ExitCodeEvent(context, exitCode));
            }
            //获取SpringBoot异常处理器
            SpringBootExceptionHandler handler = this.getSpringBootExceptionHandler();
            if (handler != null) {
                //如果处理器不为null,注册退出码
                handler.registerExitCode(exitCode);
            }
        }

    }
    //从异常中获得退出码
    private int getExitCodeFromException(ConfigurableApplicationContext context, Throwable exception) {
        //从MappedException获得退出码
        int exitCode = this.getExitCodeFromMappedException(context, exception);
        //如果exitCode==0
        if (exitCode == 0) {
            //从异常退出码生成器中获取退出码
            exitCode = this.getExitCodeFromExitCodeGeneratorException(exception);
        }
				//退出码
        return exitCode;
    }
    private int getExitCodeFromExitCodeGeneratorException(Throwable exception) {
        //如果exception==null,直接返回0
        if (exception == null) {
            return 0;
        } else {
            //从退出码生成器中获得退出码
            return exception instanceof ExitCodeGenerator ? ((ExitCodeGenerator)exception).getExitCode() : this.getExitCodeFromExitCodeGeneratorException(exception.getCause());
        }
    }

由源码可知当异常实现ExitCodeGenerator接口时,退出码直接采用getExitCode()方法返回。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、自定义错误页面
    • 1.1、概述
      • 1.2、自定义错误页面
      • 2、@ExceptionHandler 注解处理局部异常
        • 2.1、Controller
          • 2.2、修改error.html
          • 3、处理全局异常
            • 3.1、@ControllerAdvice+@ExceptionHandler:
              • 3.2、配置 SimpleMappingExceptionResolver 处理异常
                • 3.3、自定义 HandlerExceptionResolver 类处理异常
                • 4、Spring Boot 应用正常退出
                • 5、Spring Boot应用异常退出
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档