溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Application怎么配置

發(fā)布時間:2022-01-06 15:23:58 來源:億速云 閱讀:160 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要講解了“Spring Application怎么配置”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Application怎么配置”吧!

一、概述

目前Spring Boot已經(jīng)發(fā)展到2.3.4.RELEASE ,對于它的好處網(wǎng)上也是鋪天蓋地的,這里就不再重復(fù)了。直接說重點,從Spring Boot1.x一步步跟著迭代升級到現(xiàn)在的2.3.4也是遇到了很多的坑,了解其新版本的特性是非常重要的,可以幫助我們避免很多不必要的麻煩。

因為我也一直在搞基于Spring Boot技術(shù)棧的組件開發(fā)工作,最近準(zhǔn)備針對基礎(chǔ)組件進(jìn)行部分重構(gòu),所以順便把當(dāng)前版本的特性從頭在順一遍,就當(dāng)是回顧總結(jié)了,這個回顧只介紹目前版本的一些特性,不對特性展開來敘述,如果有興趣可以@我,后面我也會根據(jù)某一塊來進(jìn)行詳細(xì)的分析。喜歡的朋友可以跟著看一看,希望對你有所幫助。

二、從頭開始Application

1、應(yīng)用啟動失?。⊿tartup Failure)

如果應(yīng)用啟動失敗,Spring Boot會幫我們把大概為什么會啟動失敗的信息打印在日志中,如下面我用6080端口第二次啟動應(yīng)用就會提示我如下

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

Description:

Embedded servlet container failed to start. Port 6080 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.

有了這種友好的提示真是幸福感爆棚啊,而且Spring Boot 還給我們提供了更多的擴(kuò)展接口FailureAnalyzer,并提供了響應(yīng)得抽象類AbstractFailureAnalyzer。如果我們不滿足他默認(rèn)的啟動異常信息,就可以通過FailureAnalyzer 來進(jìn)行一些定制化開發(fā)(比如在異常發(fā)生的時候打印堆棧等).FailureAnalyzer的擴(kuò)展使用了SPI的方式,所以在我們使用的時候需要在應(yīng)用內(nèi)創(chuàng)建META-INF/spring.factories,來聲明下我們的實現(xiàn),下面上個小demo。

/** 首先創(chuàng)建我們自己的類,并且可以根據(jù)自己的需要來進(jìn)行異常攔截,這里我攔截的就是端口占用異常PortInUseException
 * @ClassName LearningFailureAnalyzer
 * @Author QIANGLU
 * @Date 2020/9/23 9:10 下午
 * @Version 1.0
 */
public class LearningFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> {

    private static final Logger LOGGER = LoggerFactory.getLogger(LearningFailureAnalyzer.class);

    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
        LOGGER.error("我出異常了,哇卡卡卡卡卡卡");
        return new FailureAnalysis("端口:" +cause.getPort()+"被占用",cause.getMessage(),rootFailure);
    }
}


//第二步就是創(chuàng)建個META-INF/spring.factories 了,如下
  
org.springframework.boot.diagnostics.FailureAnalyzer=\
  com.qianglu.chapter1.failure.LearningFailureAnalyzer
  
 
//第三布啟動兩次我們的應(yīng)用,就會發(fā)現(xiàn),打印的信息是我們需要的了
 ***************************
APPLICATION FAILED TO START
***************************

Description:

端口:6080被占用

Action:

Port 6080 is already in use

這東西可用場景其實很多很多,大家想一想有沒有點啟發(fā)

2、延遲初始化(Lazy Initialization)

在Spring Boot剛出的時候,因為啟動加載慢還被人吐槽過,這不,現(xiàn)在懶加載來了。允許你的應(yīng)用開啟懶加載,你的beans 不需要在項目啟動的時候被創(chuàng)建了,啥時候用啥時候在創(chuàng)建。這樣就能節(jié)省你很多啟動時間,但有利就有弊,懶加載這玩意在web應(yīng)用中會導(dǎo)致你很多web相關(guān)的bean也被延遲加載,知道有請求進(jìn)來才會被初始化,所以在使用的時候一定要注意,否則就會有叫你很懵逼的異常了。

并且官方也說了,你都延遲初始化了,那有些問題可能也會延遲被發(fā)現(xiàn)。比如我們以前某些配置配錯了,經(jīng)常會在啟動的時候就報XXXbean不能被找到之類的。嘿嘿,現(xiàn)在可就不了,一樣的啟動成功,只有在你用的時候給你掉鏈子,就問你怕不怕吧。

還有就是官方提示延遲初始化的,會導(dǎo)致初期jvm 內(nèi)存表現(xiàn)比較小,但要注意配置足夠的內(nèi)存給未來對象創(chuàng)建使用(我覺得一般應(yīng)用這都不是問題,不需要過多關(guān)注)。

下面我們就來看看兩種配置方式:

  • 使用SpringApplication調(diào)用setLazyInitialization 方法設(shè)置

  • 使用配置spring.main.lazy-initialization=true

如果你設(shè)置了延遲初始化,又有某些特殊的類想初始化,那可以配置@Lazy(false) 關(guān)閉其懶加載。

3、配置Banner

這玩意說實話我一直不知道有啥用,以前我們都是配置個大佛保平安,娛樂性大于實際吧,當(dāng)然也許有沒GET到的點。

配置方式也很簡單,就是在你的classpath下放個banner.txt,通過spring.banner.location 配置來指定下文件位置。當(dāng)然還有很多屬性,什么編碼、gif、version之類的我其實懶得說了,沒啥興趣。

####4、配置你的SpringApplication

咱們一般啟動類都是直接調(diào)用SpringApplication.run就行了。但如果你覺得太簡單沒啥意思,那其實SpringApplication.run 里面有很多有意思的屬性你可以去看看,比如我關(guān)閉banner

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
}

當(dāng)然還有很多配置屬性,你也可以使用application.yml來配置SpringApplication 的屬性。

5、流式構(gòu)建API(Fluent Builder API)

官方提供了SpringApplicationBuilder 類來幫大家使用流式構(gòu)建的方式來創(chuàng)建多級的ApplicationContext。SpringApplicationBuilder可以幫助我們構(gòu)建一種層級關(guān)系,如下這種方式等于SpringApplication.run

new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .bannerMode(Banner.Mode.OFF)
        .run(args);
6、應(yīng)用可用性(Application Availability)

這里說的其實就是k8s的Liveness 和 Readiness ,他們已經(jīng)成為了Spring Boot的核心。

簡單說下,Liveness 和 Readiness 在k8s中代表了應(yīng)用程序狀態(tài)的各個方面。

Liveness 狀態(tài)來查看內(nèi)部情況可以理解為health check,如果Liveness失敗就就意味著應(yīng)用處于故障狀態(tài)并且目前無法恢復(fù),這種情況就重啟吧。

Readiness 狀態(tài)用來告訴應(yīng)用是否已經(jīng)準(zhǔn)備好接受客戶端請求,如果Readiness未就緒那么k8s就不能路由流量過來。

我們可以用代碼來監(jiān)聽Readiness狀態(tài),并進(jìn)行我們需要的處理

@Component
public class ReadinessStateExporter {

    @EventListener
    public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
        switch (event.getState()) {
        case ACCEPTING_TRAFFIC:
            // xxxxx
        break;
        case REFUSING_TRAFFIC:
            // xxxxxx
        break;
        }
    }

}

我們也能在應(yīng)用出現(xiàn)故障不能被恢復(fù)的時候改變此狀態(tài)來進(jìn)行動態(tài)的降級和隔離,這個真是太爽了,有機(jī)會建議大家試一試

@Component
public class LocalCacheVerifier {

    private final ApplicationEventPublisher eventPublisher;

    public LocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void checkLocalCache() {
        try {
            //...
        }
        catch (CacheCompletelyBrokenException ex) {
            AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
        }
    }

}
7、事件和監(jiān)聽(Application Events and Listeners)

Spring Boot的事件通知機(jī)制,簡直是解耦神器,包括Spring Cloud的用的分布式遠(yuǎn)程通知機(jī)制其實核心也是這個,這是增加了一層中間件來進(jìn)行消息的傳遞。

有些事件因為實在ApplicationContext創(chuàng)建前就觸發(fā)了,所以很多時候不能使用@Bean來聲明這些事件。最好使用SpringApplication.addListeners(…)SpringApplicationBuilder.listeners(…) 來注冊監(jiān)聽器。

但如果你真是把握不了這些加載時機(jī)的話,那有個萬能的辦法就是配置SPI擴(kuò)展,直接在META-INF/spring.factories 配置,加上你得listener就行了,如:org.springframework.context.ApplicationListener=com.example.project.MyListener

官方介紹了寫在啟動時候會發(fā)送的事件順序:

1、ApplicationStartingEvent 在運行開始的時候發(fā)送事件

2、ApplicationEnvironmentPreparedEvent 當(dāng)Environment在上下文中被使用的時候發(fā)送事件

3、ApplicationContextInitializedEvent 在所有的bean定義前,ApplicationContext準(zhǔn)備好并且ApplicationContextInitializers已經(jīng)被調(diào)用的時候發(fā)送事件

4、ApplicationPreparedEvent 刷新配置前、bean的定義加載之后發(fā)送事件

5、ApplicationStartedEvent 刷新上下文后,在執(zhí)行CommandLineRunner的實現(xiàn)之前

6、AvailabilityChangeEvent 發(fā)送LivenessState.CORRECT 表面應(yīng)用是活躍狀態(tài)

7、ApplicationReadyEvent 在執(zhí)行CommandLineRunner接口之后發(fā)送

8、AvailabilityChangeEvent 發(fā)送ReadinessState.ACCEPTING_TRAFFIC 后代表應(yīng)用可以接入流量

9、ApplicationFailedEvent 發(fā)送應(yīng)用啟動失敗事件

上面的只是SpringApplicationEvent 的事件,一般咱們也不需要對這些進(jìn)行操作,帶你得知道它的存在,以免出了問題都不知道怎么找,其實人家Spring Boot已經(jīng)都發(fā)給你了。

8、Web屬性

一般使用SpringApplication就會為我們正確的創(chuàng)建ApplicationContext類型,用于確定WebApplicationType 也就是應(yīng)用類型的方式其實很簡單:

  • 如果存在Spring MVC 就使用AnnotationConfigServletWebServerApplicationContext

  • 如果Spring MVC不存 在,但是Spring WebFlux存在,就使用AnnotationConfigReactiveWebServerApplicationContext

  • 都沒有的話就用AnnotationConfigApplicationContext

  • 如果你既用了Spring MVC 又用了Spring WebFlux WebClient,Spring MVC 這一套是默認(rèn)使用的,除非你設(shè)置SpringApplication.setWebApplicationType(WebApplicationType)來強(qiáng)制改變。

9、訪問應(yīng)用參數(shù)(Accessing Application Arguments)

如果你想訪問SpringApplication.run(…) 的參數(shù),你其實可以注入一個org.springframework.boot.ApplicationArguments 對象,ApplicationArguments這個接口提供對原始String[] 參數(shù)以及已解析的選項和非選項參數(shù)的訪問,上demo:

import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

@Component
public class MyBean {

    @Autowired
    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> files = args.getNonOptionArgs();
        // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
    }

}

Spring Boot 中的環(huán)境變量也注冊了一個CommandLinePropertySource,我們可以使用@Value來獲取某個環(huán)境變量。

10、使用ApplicationRunner or CommandLineRunner

這倆貨也是我們經(jīng)常會用到的東西,如果你需要在項目啟動時加載一些東西,那它倆簡直就是神器了,這倆接口都提供了一個run方法,這個方法會在SpringApplication.run(…) 執(zhí)行完成前被調(diào)用。這倆接口適合哪種在應(yīng)用接收請求前來處理一些東西。

舉個使用例子

import org.springframework.boot.*;
import org.springframework.stereotype.*;

@Component
public class MyBean implements CommandLineRunner {

    public void run(String... args) {
        // Do something...
    }

}

如果咱們定義了多個CommandLineRunner或ApplicationRunner實現(xiàn),有的時候又需要有個先后順序來執(zhí)行,那就可以用org.springframework.core.annotation.Order 這個注解來定義下。

11、應(yīng)用退出( Application Exit)

每個SpringApplication 都會像JVM注冊一個關(guān)閉鉤子(shutdown hook ),來確保能夠正常的退出。保證@PreDestroy 注解和DisposableBean 接口這些回調(diào)都被執(zhí)行。

另外,如果你想在使用SpringApplication.exit() 時返回一些特殊的退出代碼,可以實現(xiàn)org.springframework.boot.ExitCodeGenerator接口,傳遞給System.exit() 進(jìn)行返回。如:

@SpringBootApplication
public class ExitCodeApplication {

    @Bean
    public ExitCodeGenerator exitCodeGenerator() {
        return () -> 42;
    }

    public static void main(String[] args) {
        System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
    }

}

ExitCodeGenerator接口可以通過異常實現(xiàn)。遇到此類異常時,Spring Boot返回實現(xiàn)的getExitCode() 方法提供的退出代碼

12、管理員功能(Admin Features)

我們可以使用spring.application.admin.enabled 屬性來開啟管理員功能。開了的話就會把你自己的SpringApplicationAdminMXBean 全部暴露給MBeanServer咯,當(dāng)然你也可以用這種特性來遠(yuǎn)程操作你應(yīng)用。但你要想明白其中的安全性問題,沒啥必要的話還是不要亂搞。

感謝各位的閱讀,以上就是“Spring Application怎么配置”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring Application怎么配置這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI