Spring Boot 老啓動失敗,此次不再怕了!

Spring Boot 項目是否是常常失敗,顯示一大堆的錯誤信息,如端口重複綁定時會打印如下異常:java

***************************
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.

這個你們應該很熟悉了吧!git

錯誤信息你們都能看懂,但很不友好,那麼,Spring Boot 是怎麼實現這樣一個異常錯誤信息輸出的呢?今天棧長分享一個 Spring Boot 啓動失敗的簡單易懂的玩法,讓新來的實習生 1 秒都能看出問題。github

若是你對 Spring Boot 還不是很熟悉,或者只是會簡單的使用,那仍是建議你深刻學習下吧,推薦這個 Spring Boot 學習倉庫,歡迎 Star 關注:web

https://github.com/javastacks/spring-boot-best-practice面試

Failure Analyzers 介紹

Spring Boot 中註冊了許多 "Failure Analyzers",即 "失敗分析器",Spring Boot 中的啓動失敗的場景都是由這些失敗分析器攔截處理的。spring

Spring Boot 提供了 FailureAnalyzers 接口:springboot

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);

}

這個接口的目的就是: 分析啓動失敗異常並顯示給用戶有用的診斷信息。微信

Spring Boot 內置註冊的全部失敗分析器在這個文件裏面:intellij-idea

/org/springframework/boot/spring-boot/2.3.5.RELEASE/spring-boot-2.3.5.RELEASE-sources.jar!/META-INF/spring.factoriesapp

註冊的全部失敗分析器列表:

# 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

再回到上面的端口重複綁定啓動失敗異常,就是註冊了 PortInUseFailureAnalyzer 這個失敗分析器,能夠看到 PortInUseFailureAnalyzer 失敗分析器就在註冊列表裏面。

再來看下 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);
   }

}

只要應用啓動過程上拋出了 PortInUseException 異常就會被這個失敗分析器攔截並輸出可讀性的錯誤信息,如今知道綁定重複綁定錯誤是怎麼輸出的了。

自定義 Failure Analyzers

從內置的失敗分析器中能夠發現,全部的分析器都繼承了這個抽象基類是:AbstractFailureAnalyzer,它實現了 FailureAnalyzer 接口,通常基於這個抽象基類就能夠實現自定義失敗分析器的擴展。

下面棧長經過兩個示例帶你們瞭解下,如何擴展或者自定義一個 FailureAnalyzer

一、重寫端口失敗分析器

好比說上面的PortInUseFailureAnalyzer 輸出內容是英文的,不是很直觀的看出,咱們能夠本身實現一箇中文的端口失敗分析器。

很簡單,建立一個失敗分析器繼承 AbstractFailureAnalyzer 抽象類便可:

/**
 * 來源微信公衆號:Java技術棧
 */
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("你啓動的端口 " + cause.getPort() + " 被佔用了.",
            "快檢查下端口 " + cause.getPort() + " 被哪一個程序佔用了,或者強制殺掉進程.",
            cause);
   }

}

重寫 analyze 方法,並返回一個 FailureAnalysis 對象,FailureAnalysis 類的三個主要信息分別是:

public FailureAnalysis(String description, String action, Throwable cause) {
   this.description = description;
   this.action = action;
   this.cause = cause;
}

即要展現的:可讀性的錯誤描述、建議的檢查修復動做、原始異常。

而後在本身的資源目錄下建立 META-INF/spring.factories 文件,內容添加:

org.springframework.boot.diagnostics.FailureAnalyzer=\
cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer

啓動輸出:

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

Description:

你啓動的端口 8080 被佔用了.

Action:

快檢查下端口 8080 被哪一個程序佔用了,或者強制殺掉進程.

這樣從新實現一下是否是要清楚多了?實習生都能看懂!

二、自定義失敗分析器

下面再來自定義一個全新的失敗分析器,讓你們能更清楚的認識失敗分析器。

咱們在建立 Bean 的過程當中手動拋出一個自定義的異常:

/**
 * 來源微信公衆號:Java技術棧
 */
@Bean
public CommandLineRunner commandLineRunner(){
    throw new JavastackException("Java技術棧異常");
}

添加一個失敗分析器攔截該異常:

/**
 * 來源微信公衆號:Java技術棧
 */
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技術棧發生異常了……",
            "趕快去檢查一下吧!",
            cause);
   }

}

添加註冊:

org.springframework.boot.diagnostics.FailureAnalyzer=\
cn.javastack.springboot.features.analyzer.PortInUseFailureAnalyzer,\
cn.javastack.springboot.features.analyzer.JavastackFailureAnalyzer

啓動輸出:

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

Description:

Java技術棧發生異常了……

Action:

趕快去檢查一下吧!

若是不註冊該失敗分析器,這個自定義的異常就不會被內置的失敗分析器攔截,就會輸出大堆的異常信息,使用失敗分析器能很直觀的看出是什麼錯誤及怎麼修復這個錯誤。

總結

Spring Boot 提供的失敗分析器以友好的錯誤信息和修復建議代替了大堆的錯誤異常信息,能夠幫助咱們更直觀的定位應用啓動故障,你學會了嗎?

本文的全部示例源代碼都已上傳到了 Github:

https://github.com/javastacks/spring-boot-best-practice

歡迎你們 Star 關注,後續會不斷更新。

學習更多 Spring Boot 教程,請關注公衆號Java技術棧,在後臺回覆:boot,歷史 Spring Boot 教程我都整理好了。

最後,別忘了點在看、轉發哦,須要你的鼓勵~

版權申明:本文系公衆號 "Java技術棧" 原創,原創實屬不易,轉載、引用本文內容請註明出處,禁止抄襲、洗稿,請自重,尊重他人勞動成果和知識產權。

近期熱文推薦:

1.600+ 道 Java面試題及答案整理(2021最新版)

2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!

3.阿里 Mock 工具正式開源,幹掉市面上全部 Mock 工具!

4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索