欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot之自定義啟動異常堆棧信息打印方式

 更新時間:2021年08月09日 08:38:52   作者:weixin_36276193  
這篇文章主要介紹了SpringBoot之自定義啟動異常堆棧信息打印方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

在SpringBoot項目啟動過程中,當一些配置或者其他錯誤信息會有一些的規(guī)范的提示信息

***************************
APPLICATION FAILED TO START
***************************

Description:

Web server failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

在SpringBoot 中其實現(xiàn)原理是什么,我們該如何自定義異常信息呢

1、SpringBoot異常處理的源碼分析

在springboot啟動的核心方法run中會加載所有的SpringBootExceptionReporter

 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
     new Class[] { ConfigurableApplicationContext.class }, context);

調用了getSpringFactoriesInstances方法

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
  ClassLoader classLoader = getClassLoader();
  // Use names and ensure unique to protect against duplicates
  Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
  AnnotationAwareOrderComparator.sort(instances);
  return instances;
 }

其主要通過Spring的Factories機制來加載

public ConfigurableApplicationContext run(String... args) {
  StopWatch stopWatch = new StopWatch();
  stopWatch.start();
  ConfigurableApplicationContext context = null;
  Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
  configureHeadlessProperty();
  SpringApplicationRunListeners listeners = getRunListeners(args);
  listeners.starting();
  try {
   ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
   ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
   configureIgnoreBeanInfo(environment);
   Banner printedBanner = printBanner(environment);
   context = createApplicationContext();
   exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
     new Class[] { ConfigurableApplicationContext.class }, context);
   prepareContext(context, environment, listeners, applicationArguments, printedBanner);
   refreshContext(context);
   afterRefresh(context, applicationArguments);
   stopWatch.stop();
   if (this.logStartupInfo) {
    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
   }
   listeners.started(context);
   callRunners(context, applicationArguments);
  }
  catch (Throwable ex) {
  //異常捕獲中,向用戶打印異常信息
   handleRunFailure(context, ex, exceptionReporters, listeners);
   throw new IllegalStateException(ex);
  }

  try {
   listeners.running(context);
  }
  catch (Throwable ex) {
   handleRunFailure(context, ex, exceptionReporters, null);
   throw new IllegalStateException(ex);
  }
  return context;
 }

在try catch中,catch會打印異常信息

private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
   Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) {
  try {
   try {
    handleExitCode(context, exception);
    if (listeners != null) {
     listeners.failed(context, exception);
    }
   }
   finally {
    reportFailure(exceptionReporters, exception);
    if (context != null) {
     context.close();
    }
   }
  }
  catch (Exception ex) {
   logger.warn("Unable to close ApplicationContext", ex);
  }
  ReflectionUtils.rethrowRuntimeException(exception);
 }
 private void reportFailure(Collection<SpringBootExceptionReporter> exceptionReporters, Throwable failure) {
  try {
   for (SpringBootExceptionReporter reporter : exceptionReporters) {
    if (reporter.reportException(failure)) {
     registerLoggedException(failure);
     return;
    }
   }
  }
  catch (Throwable ex) {
   // Continue with normal handling of the original failure
  }
  if (logger.isErrorEnabled()) {
   logger.error("Application run failed", failure);
   registerLoggedException(failure);
  }
 }

遍歷exceptionReporters,打印日常信息

SpringBootExceptionReporter-

SpringBootExceptionReporter是一個回調接口,用于支持對SpringApplication啟動錯誤的自定義報告。里面就一個報告啟動失敗的方法。

其實現(xiàn)類:org.springframework.boot.diagnostics.FailureAnalyzers

用于觸發(fā)從spring.factories加載的FailureAnalyzer和FailureAnalysisReporter實例。

2、如何自定義異常信息

/**
 * <p>
 *
 * <p>
 *
 * @author: xuwd
 * @time: 2020/11/16 10:52
 */
public class WannaStopException extends RuntimeException {
}

自定義異常信息打印

public class StopFailureAnalyzer
        extends AbstractFailureAnalyzer<WannaStopException> {
    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, WannaStopException cause) {
        for (StackTraceElement stackTraceElement : cause.getStackTrace()) {
            if (stackTraceElement.getClassName().equals("com.pigx.demo.Config21")) {
                return new FailureAnalysis("A想停止", "別要A了", cause);
            }
        }
        return null;
    }
}

接下來令他生效,通過上面分析可以可看出需要通過AutoConfigurationImportSelector,類似于自定義SpringBoot Starter AutoConfiguration的形式,我們需要在META-INF/spring.factories文件內進行定義,如下所示:

https://juejin.im/post/6844903956208943111

接著在合適的地方拋出WannaStopException 異常

總結

在springboot 啟動過程中會先對異常信息進行補捕獲,對進行日志格式處理的日志進行處理;其核心是通過SpringBootExceptionReporter回調及sping-spi bean的管理。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • spring中@Autowire和@Resource的區(qū)別在哪里(推薦)

    spring中@Autowire和@Resource的區(qū)別在哪里(推薦)

    這篇文章主要介紹了spring中@Autowire和@Resource的區(qū)別在哪里?本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-02-02
  • springboot中如何配置LocalDateTime JSON返回時間戳

    springboot中如何配置LocalDateTime JSON返回時間戳

    這篇文章主要介紹了springboot中如何配置LocalDateTime JSON返回時間戳問題。具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • java統(tǒng)計漢字字數(shù)的方法示例

    java統(tǒng)計漢字字數(shù)的方法示例

    這篇文章主要介紹了java統(tǒng)計漢字字數(shù)的方法,結合實例形式分析了java正則判定、字符串遍歷及統(tǒng)計相關操作技巧,需要的朋友可以參考下
    2017-05-05
  • SpringBoot入門實現(xiàn)第一個SpringBoot項目

    SpringBoot入門實現(xiàn)第一個SpringBoot項目

    今天我們一起來完成一個簡單的SpringBoot(Hello World)。就把他作為你的第一個SpringBoot項目。具有一定的參考價值,感興趣的可以了解一下
    2021-09-09
  • springboot docker原理及項目構建

    springboot docker原理及項目構建

    這篇文章主要介紹了springboot docker原理及項目構建,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot2.6.x默認禁用循環(huán)依賴后的問題解決

    SpringBoot2.6.x默認禁用循環(huán)依賴后的問題解決

    由于SpringBoot從底層逐漸引導開發(fā)者書寫規(guī)范的代碼,同時也是個憂傷的消息,循環(huán)依賴的應用場景實在是太廣泛了,所以SpringBoot 2.6.x不推薦使用循環(huán)依賴,本文給大家說下SpringBoot2.6.x默認禁用循環(huán)依賴后的應對策略,感興趣的朋友一起看看吧
    2022-02-02
  • 解決java.util.NoSuchElementException異常正確方法

    解決java.util.NoSuchElementException異常正確方法

    java.util.NoSuchElementException是Java中的一種異常,表示在迭代器或枚舉中找不到元素,這篇文章主要給大家介紹了關于解決java.util.NoSuchElementException異常的相關資料,需要的朋友可以參考下
    2023-11-11
  • 教你通過B+Tree平衡多叉樹理解InnoDB引擎的聚集和非聚集索引

    教你通過B+Tree平衡多叉樹理解InnoDB引擎的聚集和非聚集索引

    大家都知道B+Tree是從二叉樹演化而來,在這之前我們來先了解二叉樹、平衡二叉樹、平衡多叉樹,這篇文章主要介紹了通過B+Tree平衡多叉樹理解InnoDB引擎的聚集和非聚集索引,需要的朋友可以參考下
    2022-01-01
  • Java TreeMap升序|降序排列和按照value進行排序的案例

    Java TreeMap升序|降序排列和按照value進行排序的案例

    這篇文章主要介紹了Java TreeMap升序|降序排列和按照value進行排序的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • SpringBoot利用jackson格式化時間的三種方法

    SpringBoot利用jackson格式化時間的三種方法

    日常開發(fā)過程中經常會使用json進行數(shù)據的傳輸,這就涉及到了對象和json的相互轉化,常用的解決方案有:Jackson(推薦)、谷歌的Gson、阿里的Fastjson,這篇文章主要給大家介紹了關于SpringBoot如何利用jackson格式化時間的相關資料,需要的朋友可以參考下
    2021-06-06

最新評論