您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“SpringBoot打印詳細(xì)啟動(dòng)異常信息的方法”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
SpringBoot在項(xiàng)目啟動(dòng)時(shí)如果遇到異常并不能友好的打印出具體的堆棧錯(cuò)誤信息,我們只能查看到簡(jiǎn)單的錯(cuò)誤消息,以致于并不能及時(shí)解決發(fā)生的問題,針對(duì)這個(gè)問題SpringBoot提供了故障分析儀的概念(failure-analyzer),內(nèi)部根據(jù)不同類型的異常提供了一些實(shí)現(xiàn),我們?nèi)绻胱远x該怎么去做?
SpringBoot提供了啟動(dòng)異常分析接口FailureAnalyzer,該接口位于org.springframework.boot.diagnosticspackage內(nèi)。內(nèi)部?jī)H提供一個(gè)分析的方法,源碼如下所示:
@FunctionalInterface public interface FailureAnalyzer { /** * Returns an analysis of the given {@code failure}, or {@code null} if no analysis * was possible. * @param failure the failure * @return the analysis or {@code null} */ FailureAnalysis analyze(Throwable failure); }
該接口會(huì)把遇到的異常對(duì)象實(shí)例Throwable failure交付給實(shí)現(xiàn)類,實(shí)現(xiàn)類進(jìn)行自定義處理。
AbstractFailureAnalyzer是FailureAnalyzer的基礎(chǔ)實(shí)現(xiàn)抽象類,實(shí)現(xiàn)了FailureAnalyzer定義的analyze(Throwable failure)方法,并提供了一個(gè)指定異常類型的抽象方法analyze(Throwable rootFailure, T cause),源碼如下所示:
public abstract class AbstractFailureAnalyzer<T extends Throwable> implements FailureAnalyzer { @Override public FailureAnalysis analyze(Throwable failure) { T cause = findCause(failure, getCauseType()); if (cause != null) { return analyze(failure, cause); } return null; } /** * Returns an analysis of the given {@code rootFailure}, or {@code null} if no * analysis was possible. * @param rootFailure the root failure passed to the analyzer * @param cause the actual found cause * @return the analysis or {@code null} */ protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause); /** * Return the cause type being handled by the analyzer. By default the class generic * is used. * @return the cause type */ @SuppressWarnings("unchecked") protected Class<? extends T> getCauseType() { return (Class<? extends T>) ResolvableType.forClass(AbstractFailureAnalyzer.class, getClass()).resolveGeneric(); } @SuppressWarnings("unchecked") protected final <E extends Throwable> E findCause(Throwable failure, Class<E> type) { while (failure != null) { if (type.isInstance(failure)) { return (E) failure; } failure = failure.getCause(); } return null; } }
通過AbstractFailureAnalyzer源碼我們可以看到,它在實(shí)現(xiàn)于FailureAnalyzer的接口方法內(nèi)進(jìn)行了特殊處理,根據(jù)getCauseType()方法獲取當(dāng)前類定義的第一個(gè)泛型類型,也就是我們需要分析的指定異常類型。
獲取泛型異常類型后根據(jù)方法findCause判斷Throwable是否與泛型異常類型匹配,如果匹配直接返回給SpringBoot進(jìn)行注冊(cè)處理。
SpringBoot內(nèi)部通過實(shí)現(xiàn)AbstractFailureAnalyzer抽象類定義了一系列的針對(duì)性異常類型的啟動(dòng)分析,如下圖所示:
SpringBoot內(nèi)部提供的啟動(dòng)異常分析都是指定具體的異常類型實(shí)現(xiàn)的,最常見的一個(gè)錯(cuò)誤就是端口號(hào)被占用(PortInUseException),雖然SpringBoot內(nèi)部提供一個(gè)這個(gè)異常的啟動(dòng)分析,我們也是可以進(jìn)行替換這一異常分析的,我們只需要?jiǎng)?chuàng)建PortInUseException異常的AbstractFailureAnalyzer,并且實(shí)現(xiàn)類注冊(cè)給SpringBoot即可,實(shí)現(xiàn)自定義如下所示:
/** * 端口號(hào)被占用{@link PortInUseException}異常啟動(dòng)分析 * * @author 恒宇少年 */ public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { /** * logger instance */ static Logger logger = LoggerFactory.getLogger(PortInUseFailureAnalyzer.class); @Override protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) { logger.error("端口被占用。", cause); return new FailureAnalysis("端口號(hào):" cause.getPort() "被占用", "PortInUseException", rootFailure); } }
在上面我們只是編寫了指定異常啟動(dòng)分析,我們接下來需要讓它生效,這個(gè)生效方式比較特殊,類似于自定義SpringBoot Starter AutoConfiguration的形式,我們需要在META-INF/spring.factories文件內(nèi)進(jìn)行定義,如下所示:
org.springframework.boot.diagnostics.FailureAnalyzer=\ org.minbox.chapter.springboot.failure.analyzer.PortInUseFailureAnalyzer
那我們?yōu)槭裁葱枰褂眠@種方式定義呢?
項(xiàng)目啟動(dòng)遇到的異常順序不能確定,很可能在Spring IOC并未執(zhí)行初始化之前就出現(xiàn)了異常,我們不能通過@Component注解的形式使其生效,所以SpringBoot提供了通過spring.factories配置文件的方式定義。
啟動(dòng)異常分析繼承關(guān)系
自定義的運(yùn)行異常一般都是繼承自RuntimeException,如果我們定義一個(gè)RuntimeException的異常啟動(dòng)分析實(shí)例會(huì)是什么效果呢?
/** * 項(xiàng)目啟動(dòng)運(yùn)行時(shí)異常{@link RuntimeException}統(tǒng)一啟動(dòng)分析 * * @author 恒宇少年 */ public class ProjectBootUnifiedFailureAnalyzer extends AbstractFailureAnalyzer<RuntimeException> { /** * logger instance */ static Logger logger = LoggerFactory.getLogger(ProjectBootUnifiedFailureAnalyzer.class); @Override protected FailureAnalysis analyze(Throwable rootFailure, RuntimeException cause) { logger.error("遇到運(yùn)行時(shí)異常", cause); return new FailureAnalysis(cause.getMessage(), "error", rootFailure); } }
將該類也一并注冊(cè)到spring.factories文件內(nèi),如下所示:
org.springframework.boot.diagnostics.FailureAnalyzer=\ org.minbox.chapter.springboot.failure.analyzer.PortInUseFailureAnalyzer,\ org.minbox.chapter.springboot.failure.analyzer.ProjectBootUnifiedFailureAnalyzer
運(yùn)行項(xiàng)目并測(cè)試端口號(hào)被占用異常我們會(huì)發(fā)現(xiàn),并沒有執(zhí)行ProjectBootUnifiedFailureAnalyzer內(nèi)的analyze方法,而是繼續(xù)執(zhí)行了PortInUseFailureAnalyzer類內(nèi)的方法。
那我們將PortInUseFailureAnalyzer這個(gè)啟動(dòng)分析從spring.factories文件內(nèi)暫時(shí)刪除掉,再來運(yùn)行項(xiàng)目我們會(huì)發(fā)現(xiàn)這時(shí)卻是會(huì)執(zhí)行ProjectBootUnifiedFailureAnalyzer類內(nèi)分析方法。
總結(jié)
根據(jù)本章我們了解了SpringBoot提供的啟動(dòng)異常分析接口以及基本抽象實(shí)現(xiàn)類的運(yùn)作原理,而且啟動(dòng)異常分析存在分析泛型異常類的上下級(jí)繼承關(guān)系,異常子類的啟動(dòng)分析會(huì)覆蓋掉異常父類的啟動(dòng)分析,如果你想包含全部異常的啟動(dòng)分析可以嘗試使用Exception作為AbstractFailureAnalyzer的泛型參數(shù)。
“SpringBoot打印詳細(xì)啟動(dòng)異常信息的方法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。