Spring Boot 項(xiàng)目啟動(dòng)失敗的解決方案
Spring Boot 項(xiàng)目是不是經(jīng)常失敗,顯示一大堆的錯(cuò)誤信息,如端口重復(fù)綁定時(shí)會(huì)打印以下異常:
*************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container 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.
這個(gè)大家應(yīng)該很熟悉了吧!
錯(cuò)誤信息大家都能看懂,但很不友好,那么,Spring Boot 是怎么實(shí)現(xiàn)這樣一個(gè)異常錯(cuò)誤信息輸出的呢?今天棧長分享一個(gè) Spring Boot 啟動(dòng)失敗的簡單易懂的玩法,讓新來的實(shí)習(xí)生 1 秒都能看出問題。
如果你對(duì) Spring Boot 還不是很熟悉,或者只是會(huì)簡單的使用,那還是建議你深入學(xué)習(xí)下吧,推薦這個(gè) Spring Boot 學(xué)習(xí)倉庫,歡迎 Star 關(guān)注:
Failure Analyzers 介紹
Spring Boot 中注冊(cè)了許多 "Failure Analyzers",即 "失敗分析器",Spring Boot 中的啟動(dòng)失敗的場景都是由這些失敗分析器攔截處理的。
Spring Boot 提供了 FailureAnalyzers
接口:
package org.springframework.boot.diagnostics; /** * A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic * information that can be displayed to the user. * * @author Andy Wilkinson * @since 1.4.0 */ @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); }
這個(gè)接口的目的就是: 分析啟動(dòng)失敗異常并顯示給用戶有用的診斷信息。
Spring Boot 內(nèi)置注冊(cè)的所有失敗分析器在這個(gè)文件里面:
/org/springframework/boot/spring-boot/2.3.5.RELEASE/spring-boot-2.3.5.RELEASE-sources.jar!/META-INF/spring.factories
注冊(cè)的所有失敗分析器列表:
# Failure Analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\ org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer
再回到上面的端口重復(fù)綁定啟動(dòng)失敗異常,就是注冊(cè)了 PortInUseFailureAnalyzer
這個(gè)失敗分析器,可以看到 PortInUseFailureAnalyzer
失敗分析器就在注冊(cè)列表里面。
再來看下 PortInUseFailureAnalyzer
的源碼:
/** * A {@code FailureAnalyzer} that performs analysis of failures caused by a * {@code PortInUseException}. * * @author Andy Wilkinson */ class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { @Override protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) { return new FailureAnalysis("Web server failed to start. Port " + cause.getPort() + " was already in use.", "Identify and stop the process that's listening on port " + cause.getPort() + " or configure this " + "application to listen on another port.", cause); } }
只要應(yīng)用啟動(dòng)過程上拋出了 PortInUseException
異常就會(huì)被這個(gè)失敗分析器攔截并輸出可讀性的錯(cuò)誤信息,現(xiàn)在知道綁定重復(fù)綁定錯(cuò)誤是怎么輸出的了。
自定義 Failure Analyzers
從內(nèi)置的失敗分析器中可以發(fā)現(xiàn),所有的分析器都繼承了這個(gè)抽象基類是:AbstractFailureAnalyzer,它實(shí)現(xiàn)了 FailureAnalyzer 接口,一般基于這個(gè)抽象基類就可以實(shí)現(xiàn)自定義失敗分析器的擴(kuò)展。
下面棧長通過兩個(gè)示例帶大家了解下,如何擴(kuò)展或者自定義一個(gè) FailureAnalyzer。
1、重寫端口失敗分析器
比如說上面的PortInUseFailureAnalyzer
輸出內(nèi)容是英文的,不是很直觀的看出,我們可以自己實(shí)現(xiàn)一個(gè)中文的端口失敗分析器。
很簡單,創(chuàng)建一個(gè)失敗分析器繼承 AbstractFailureAnalyzer 抽象類即可:
package cn.javastack.springboot.features.analyzer; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.web.server.PortInUseException; public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> { @Override protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) { return new FailureAnalysis("你啟動(dòng)的端口 " + cause.getPort() + " 被占用了.", "快檢查下端口 " + cause.getPort() + " 被哪個(gè)程序占用了,或者強(qiáng)制殺掉進(jìn)程.", cause); } }
重寫 analyze
方法,并返回一個(gè) FailureAnalysis
對(duì)象,FailureAnalysis
類的三個(gè)主要信息分別是:
public FailureAnalysis(String description, String action, Throwable cause) { this.description = description; this.action = action; this.cause = cause; }
即要展示的:可讀性的錯(cuò)誤描述、建議的檢查修復(fù)動(dòng)作、原始異常。
然后在自己的資源目錄下創(chuàng)建 META-INF/spring.factories 文件,內(nèi)容添加:
org.springframework.boot.diagnostics.FailureAnalyzer=\ cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer
啟動(dòng)輸出:
*************************** APPLICATION FAILED TO START *************************** Description: 你啟動(dòng)的端口 8080 被占用了. Action: 快檢查下端口 8080 被哪個(gè)程序占用了,或者強(qiáng)制殺掉進(jìn)程.
這樣重新實(shí)現(xiàn)一下是不是要清楚多了?實(shí)習(xí)生都能看懂!
2、自定義失敗分析器
下面再來自定義一個(gè)全新的失敗分析器,讓大家能更清楚的認(rèn)識(shí)失敗分析器。
我們?cè)趧?chuàng)建 Bean 的過程中手動(dòng)拋出一個(gè)自定義的異常:
@Bean public CommandLineRunner commandLineRunner(){ throw new JavastackException("Java技術(shù)棧異常"); }
添加一個(gè)失敗分析器攔截該異常:
package cn.javastack.springboot.features.analyzer; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.FailureAnalysis; public class JavastackFailureAnalyzer extends AbstractFailureAnalyzer<JavastackException> { @Override protected FailureAnalysis analyze(Throwable rootFailure, JavastackException cause) { return new FailureAnalysis("Java技術(shù)棧發(fā)生異常了……", "趕快去檢查一下吧!", cause); } }
添加注冊(cè):
org.springframework.boot.diagnostics.FailureAnalyzer=\ cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer,\ cn.javastack.springboot.features.analyzer.JavastackFailureAnalyzer
啟動(dòng)輸出:
*************************** APPLICATION FAILED TO START *************************** Description: Java技術(shù)棧發(fā)生異常了…… Action: 趕快去檢查一下吧!
如果不注冊(cè)該失敗分析器,這個(gè)自定義的異常就不會(huì)被內(nèi)置的失敗分析器攔截,就會(huì)輸出大堆的異常信息,使用失敗分析器能很直觀的看出是什么錯(cuò)誤及怎么修復(fù)這個(gè)錯(cuò)誤。
總結(jié)
Spring Boot 提供的失敗分析器以友好的錯(cuò)誤信息和修復(fù)建議代替了大堆的錯(cuò)誤異常信息,可以幫助我們更直觀的定位應(yīng)用啟動(dòng)故障,你學(xué)會(huì)了嗎?
本文的所有示例源代碼都已上傳到了 Github:
https://github.com/javastacks/spring-boot-best-practice
歡迎大家 Star 關(guān)注,后續(xù)會(huì)不斷更新。
以上就是Spring Boot 項(xiàng)目啟動(dòng)失敗的解決方案的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot 項(xiàng)目啟動(dòng)失敗的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)中序表達(dá)式的實(shí)例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)中序表達(dá)式的實(shí)例代碼,需要的朋友可以參考下2018-08-08Java項(xiàng)目導(dǎo)入IDEA的流程配置以及常見問題解決方法
通常一個(gè)團(tuán)隊(duì)中可能有人用eclipse,有人用intelliJ,那么經(jīng)常會(huì)出現(xiàn)需要導(dǎo)入別人用eclipse建好的web項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于Java項(xiàng)目導(dǎo)入IDEA的流程配置以及常見問題解決方法的相關(guān)資料,需要的朋友可以參考下2023-05-05Java數(shù)據(jù)結(jié)構(gòu)之HashMap源碼深入分析
Java HashMap是一種基于哈希表實(shí)現(xiàn)的鍵值對(duì)存儲(chǔ)結(jié)構(gòu),可以實(shí)現(xiàn)快速的數(shù)據(jù)查找和存儲(chǔ)。它是線程不安全的,但在單線程環(huán)境中運(yùn)行效率高,被廣泛應(yīng)用于Java開發(fā)中2023-04-04JDBC PreparedStatement Like參數(shù)報(bào)錯(cuò)解決方案
這篇文章主要介紹了JDBC PreparedStatement Like參數(shù)報(bào)錯(cuò)解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10spring-boot.version2.6升級(jí)到2.7.18后security報(bào)錯(cuò)問題
這篇文章主要介紹了spring-boot.version2.6升級(jí)到2.7.18后security報(bào)錯(cuò)問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08java并發(fā)編程中的SynchronousQueue實(shí)現(xiàn)原理解析
這篇文章主要介紹了java并發(fā)編程中的SynchronousQueue實(shí)現(xiàn)原理解析,SynchronousQueue是一個(gè)比較特別的隊(duì)列,此隊(duì)列源碼中充斥著大量的CAS語句,理解起來是有些難度的,為了方便日后回顧,本篇文章會(huì)以簡潔的圖形化方式展示該隊(duì)列底層的實(shí)現(xiàn)原理,需要的朋友可以參考下2023-12-12