Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 成人爱爱网站在线观看,亚洲精品国产综合一线久久,欧美freesex黑人又粗又大长

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Spring Boot :Spring Boot中的

          Spring Boot :Spring Boot中的響應(yīng)式編程和WebFlux原理解析

          pring 5.0 中發(fā)布了重量級組件 Webflux,拉起了響應(yīng)式編程的規(guī)模使用序幕。

          WebFlux 使用的場景是異步非阻塞的,使用 Webflux 作為系統(tǒng)解決方案,在大多數(shù)場景下可以提高系統(tǒng)吞吐量。Spring Boot 2.0 是基于 Spring5 構(gòu)建而成,因此 Spring Boot 2.X 將自動繼承了 Webflux 組件,本篇給大家介紹如何在 Spring Boot 中使用 Webflux 。

          為了方便大家理解,我們先來了解幾個概念。

          響應(yīng)式編程

          在計(jì)算機(jī)中,響應(yīng)式編程或反應(yīng)式編程(英語:Reactive programming)是一種面向數(shù)據(jù)流和變化傳播的編程范式。這意味著可以在編程語言中很方便地表達(dá)靜態(tài)或動態(tài)的數(shù)據(jù)流,而相關(guān)的計(jì)算模型會自動將變化的值通過數(shù)據(jù)流進(jìn)行傳播。

          例如,在命令式編程環(huán)境中,a=b+c 表示將表達(dá)式的結(jié)果賦給 a,而之后改變 b 或 c 的值不會影響 a 。但在響應(yīng)式編程中,a 的值會隨著 b 或 c 的更新而更新。

          響應(yīng)式編程是基于異步和事件驅(qū)動的非阻塞程序,只需要在程序內(nèi)啟動少量線程擴(kuò)展,而不是水平通過集群擴(kuò)展。

          用大白話講,我們以前編寫的大部分都是阻塞類的程序,當(dāng)一個請求過來時(shí)任務(wù)會被阻塞,直到這個任務(wù)完成后再返回給前端;響應(yīng)式編程接到請求后只是提交了一個請求給后端,后端會再安排另外的線程去執(zhí)行任務(wù),當(dāng)任務(wù)執(zhí)行完成后再異步通知到前端。

          Reactor

          Java 領(lǐng)域的響應(yīng)式編程庫中,最有名的算是 Reactor 了。Reactor 也是 Spring 5 中反應(yīng)式編程的基礎(chǔ),Webflux 依賴 Reactor 而構(gòu)建。

          Reactor 是一個基于 JVM 之上的異步應(yīng)用基礎(chǔ)庫。為 Java 、Groovy 和其他 JVM 語言提供了構(gòu)建基于事件和數(shù)據(jù)驅(qū)動應(yīng)用的抽象庫。Reactor 性能相當(dāng)高,在最新的硬件平臺上,使用無堵塞分發(fā)器每秒鐘可處理 1500 萬事件。

          簡單說,Reactor 是一個輕量級 JVM 基礎(chǔ)庫,幫助你的服務(wù)或應(yīng)用高效,異步地傳遞消息。Reactor 中有兩個非常重要的概念 Flux 和 Mono 。

          Flux 和 Mono

          Flux 和 Mono 是 Reactor 中的兩個基本概念。Flux 表示的是包含 0 到 N 個元素的異步序列。在該序列中可以包含三種不同類型的消息通知:正常的包含元素的消息、序列結(jié)束的消息和序列出錯的消息。當(dāng)消息通知產(chǎn)生時(shí),訂閱者中對應(yīng)的方法 onNext(), onComplete()和 onError()會被調(diào)用。

          Mono 表示的是包含 0 或者 1 個元素的異步序列。該序列中同樣可以包含與 Flux 相同的三種類型的消息通知。Flux 和 Mono 之間可以進(jìn)行轉(zhuǎn)換。對一個 Flux 序列進(jìn)行計(jì)數(shù)操作,得到的結(jié)果是一個 Mono對象。把兩個 Mono 序列合并在一起,得到的是一個 Flux 對象。

          WebFlux 是什么?

          WebFlux 模塊的名稱是 spring-webflux,名稱中的 Flux 來源于 Reactor 中的類 Flux。Spring webflux 有一個全新的非堵塞的函數(shù)式 Reactive Web 框架,可以用來構(gòu)建異步的、非堵塞的、事件驅(qū)動的服務(wù),在伸縮性方面表現(xiàn)非常好。

          非阻塞的關(guān)鍵預(yù)期好處是能夠以小的固定數(shù)量的線程和較少的內(nèi)存進(jìn)行擴(kuò)展。在服務(wù)器端 WebFlux 支持2種不同的編程模型:

          • 基于注解的 @Controller 和其他注解也支持 Spring MVC
          • Functional 、Java 8 lambda 風(fēng)格的路由和處理

          WebFlux 模塊從上到下依次是 Router Functions、WebFlux、Reactive Streams 三個新組件。

          • Router Functions 對標(biāo)準(zhǔn)的 @Controller,@RequestMapping 等的 Spring MVC 注解,提供一套 函數(shù)式風(fēng)格的 API,用于創(chuàng)建 Router、Handler 和Filter。
          • WebFlux 核心組件,協(xié)調(diào)上下游各個組件提供 響應(yīng)式編程 支持。
          • Reactive Streams 一種支持 背壓 (Backpressure) 的 異步數(shù)據(jù)流處理標(biāo)準(zhǔn),主流實(shí)現(xiàn)有 RxJava 和 Reactor,Spring WebFlux 集成的是 Reactor。

          默認(rèn)情況下,Spring Boot 2 使用 Netty WebFlux,因?yàn)?Netty 在異步非阻塞空間中被廣泛使用,異步非阻塞連接可以節(jié)省更多的資源,提供更高的響應(yīng)度。通過比較 Servlet 3.1 非阻塞 I / O 沒有太多的使用,因?yàn)槭褂盟某杀颈容^高,Spring WebFlux 打開了一條實(shí)用的通路。

          值得注意的是:支持 reactive 編程的數(shù)據(jù)庫只有 MongoDB, redis, Cassandra, Couchbase

          Spring Webflux

          Spring Boot 2.0 包括一個新的 spring-webflux 模塊。該模塊包含對響應(yīng)式 HTTP 和 WebSocket 客戶端的支持,以及對 REST,HTML 和 WebSocket 交互等程序的支持。一般來說,Spring MVC 用于同步處理,Spring Webflux 用于異步處理。

          Spring Boot Webflux 有兩種編程模型實(shí)現(xiàn),一種類似 Spring MVC 注解方式,另一種是基于 Reactor 的響應(yīng)式方式。

          快速上手

          添加 webflux 依賴

          <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-webflux</artifactId>
          </dependency>
          

          通過 IEDA 的依賴關(guān)系圖我們可以返現(xiàn)spring-boot-starter-webflux依賴于spring-webflux、Reactor 和 Netty 相關(guān)依賴包。

          創(chuàng)建 Controller

          @RestController
          public class HelloController {
           @GetMapping("/hello")
           public Mono<String> hello() {
           return Mono.just("Welcome to reactive world ~");
           }
          }
          

          通過上面的示例可以發(fā)現(xiàn),開發(fā)模式和之前 Spring Mvc 的模式差別不是很大,只是在方法的返回值上有所區(qū)別。

          • just() 方法可以指定序列中包含的全部元素。
          • 響應(yīng)式編程的返回值必須是 Flux 或者 Mono ,兩者之間可以相互轉(zhuǎn)換。

          測試類

          @RunWith(SpringRunner.class)
          @WebFluxTest(controllers=HelloController.class)
          public class HelloTests {
           @Autowired
           WebTestClient client;
           @Test
           public void getHello() {
           client.get().uri("/hello").exchange().expectStatus().isOk();
           }
          }
          

          運(yùn)行測試類,測試用例通過表示服務(wù)正常。啟動項(xiàng)目后,訪問地址:http://localhost:8080/hello,頁面返回信息:

          Welcome to reactive world ~
          

          證明 Webflux 集成成功。

          以上便是 Spring Boot 集成 Webflux 最簡單的 Demo ,后續(xù)我們繼續(xù)研究 Webflux 的使用。

          關(guān)注我:私信回復(fù)“555”獲取往期Java高級架構(gòu)資料、源碼、筆記、視頻Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高并發(fā)等架構(gòu)技術(shù)往期架構(gòu)視頻截圖

          鏈路追蹤是可觀測性軟件系統(tǒng)的一個非常好的工具。它使開發(fā)人員能夠了解應(yīng)用程序中和應(yīng)用程序之間不同交互發(fā)生的時(shí)間、地點(diǎn)和方式。同時(shí)讓觀測復(fù)雜的軟件系統(tǒng)變得更加容易。

          Spring Boot 3開始,Spring Boot 中用于鏈路追蹤的舊 Spring Cloud Sleuth 解決方案將替換為新的 Micrometer Tracing 庫。

          您可能已經(jīng)了解 Micrometer,因?yàn)樗郧氨挥米鞴_獨(dú)立于平臺的指標(biāo)和監(jiān)控基于 JVM 的微服務(wù)(例如 Prometheus )的默認(rèn)解決方案。最新產(chǎn)品通過獨(dú)立于平臺的鏈路追蹤解決方案擴(kuò)展了 Micrometer 生態(tài)系統(tǒng)。這使得開發(fā)人員能夠使用一個通用 API 來檢測其應(yīng)用程序,并以不同的格式將其導(dǎo)出到 Jaeger、Zipkin 或 OpenTelemetry 等鏈路追蹤收集器。

          本文將介紹在響應(yīng)式編程 Kotlin 中,如何在 Spring Boot 3 WebFlux 利用 Micrometer 進(jìn)行鏈路追蹤。

          1. 微服務(wù)設(shè)置

          接下來,我們將創(chuàng)建一個簡單的 Spring Boot 微服務(wù),它提供一個響應(yīng)式 REST 端點(diǎn),該端點(diǎn)在內(nèi)部查詢另一個第三方服務(wù)以獲取一些信息。目標(biāo)是導(dǎo)出兩個操作的 trace。

          我們將從以下 Spring Boot Initializr 項(xiàng)目開始,您可以在此處找到該項(xiàng)目。它包括帶有Kotlin Gradle DSLSpring Boot 3.0.1Spring Web Reactive (WebFlux)和帶有PrometheusSpring Actuator。以下代碼主要使用Kotlin,但如果使用 Java 也是可以的,大多數(shù)方法都是相同的。

          Spring 初始化模板(https://start.spring.io/) 帶有 Webflux、Spring Actuator 和 Prometheus 的 Spring Boot 3 Kotlin 模板

          定義 endpoint

          我們將首先添加一個帶有測試 endpoint 的簡單 REST 控制器類,該測試 endpoint 使用 Spring WebClient 調(diào)用外部 API 。我們正在使用 suspend 關(guān)鍵字來使用Kotlin的協(xié)程。這使我們能夠在利用 Spring WebFlux 的響應(yīng)式流的同時(shí)編寫命令式代碼。

          在以下示例中,我們使用 Spring WebClient 調(diào)用外部 TODO-API,該 API 以 JSON 字符串形式返回 TODO 項(xiàng)。我們還將創(chuàng)建一條日志消息,其中稍后應(yīng)包含一些鏈路追蹤信息。

          @RestController
          class Controller {
            val log=LoggerFactory.getLogger(javaClass)
            
            val webClient=WebClient.builder()
              .baseUrl("https://jsonplaceholder.typicode.com")
              .build()
            
            @GetMapping("/test")
            suspend fun test(): String {
              // simulate some complex calculation  
              delay(1.seconds)
              
              log.info("test log with tracing info")
              
              // make web client call to external API
              val externalTodos=webClient.get()
                .uri("/todos/1")
                .retrieve()
                .bodyToMono(String::class.java)
                .awaitSingle()
              
              return externalTodos
            }
          }
          

          新增 Micrometer tracing

          在下一步中,我們將把 Micrometer tracing 依賴項(xiàng)添加到我們的build.gradle.kts文件中。由于 Micrometer 支持不同的鏈路追蹤格式和供應(yīng)商,因此依賴項(xiàng)被分開,我們只導(dǎo)入我們需要的內(nèi)容。為了保持所有依賴項(xiàng)同步,我們使用 Micrometer Tracing BOM(bom 清單)。此外,我們添加了核心依賴項(xiàng)和橋接器,以將 Micrometer Tracing 轉(zhuǎn)換為 OpenTelemetry 格式(其他格式也可用)。

          implementation(platform("io.micrometer:micrometer-tracing-bom:1.0.0"))
          implementation("io.micrometer:micrometer-tracing")
          implementation("io.micrometer:micrometer-tracing-bridge-otel")
          

          我們還需要添加導(dǎo)出器依賴項(xiàng)來導(dǎo)出創(chuàng)建的 trace。在此示例中,我們將使用由 OpenTelemetry 維護(hù)并由 Micrometer Tracing 支持的 Zipkin 導(dǎo)出器。

          implementation("io.opentelemetry:opentelemetry-exporter-zipkin")
          

          配置

          配置是設(shè)置鏈路追蹤必不可少的一步,配置文件application.yaml位于src/main/resources目錄下。

          • 首先,我們必須在管理設(shè)置中啟用鏈路追蹤。我們還將鏈路追蹤采樣率設(shè)置為 1(默認(rèn)值為 0.1),以便為服務(wù)收到的每個調(diào)用創(chuàng)建鏈路追蹤。在具有大量請求的生產(chǎn)系統(tǒng)中,您可能只想追蹤一些調(diào)用鏈路。
          • 此外,我們可以定義希望 Zipkin 導(dǎo)出器發(fā)送鏈路追蹤的端點(diǎn) URL。
          • 最后,我們必須更新默認(rèn)日志記錄模式以包含鏈路追蹤和 spanId。
          management:
            tracing:
              enabled: true
              sampling.probability: 1.0
          
            zipkin.tracing.endpoint: http://localhost:9411/api/v2/spans
          
          logging.pattern.level: "trace_id=%mdc{traceId} span_id=%mdc{spanId} trace_flags=%mdc{traceFlags} %p"
          

          2. 測試

          現(xiàn)在我們已經(jīng)完成了服務(wù)設(shè)置,我們可以運(yùn)行它了。如果啟動應(yīng)用程序,默認(rèn)情況下,服務(wù)器應(yīng)在端口下啟動 8080。然后,可以通過打開瀏覽器來調(diào)用我們創(chuàng)建的端點(diǎn)http://localhost:8080/test。以下是請求響應(yīng)內(nèi)容:

          {  "userId" :  1 ,  "id" :  1 ,  "title" :  "delectus aut autem" ,  "已完成" :  false  }
          

          要查看調(diào)用端點(diǎn)時(shí)創(chuàng)建的實(shí)際鏈路追蹤,我們需要收集并查看它們。在本教程中,我們將使用zipkin導(dǎo)出器將數(shù)據(jù)導(dǎo)出到 觀測云。當(dāng)然也可以使用其他系統(tǒng),例如 Zipkin、Grafana Loki 或 Datadog。

          現(xiàn)在您可以再次調(diào)用我們的 Spring Boot 服務(wù)的端點(diǎn)。之后,當(dāng)您在 觀測云 中搜索任何 tracing 時(shí),您應(yīng)該能夠找到端點(diǎn)請求的鏈路追蹤信息。

          3. 問題

          乍一看,一切似乎都運(yùn)行良好。然而,我們有兩個問題。

          解決了部分 issue 問題,這些問題可以在 Micrometer Tracing 文檔中找到,參考鏈接:https://micrometer.io/docs/observation#instrumentation_of_reactive_libraries_after_reactor_3_5_3。

          日志缺少數(shù)據(jù)

          如果我們查看應(yīng)用程序日志,可以發(fā)現(xiàn)調(diào)用端點(diǎn)時(shí)發(fā)出的日志消息。

          trace_id=span_id=trace_flags=INFO 43636 --- [DefaultExecutor] com.example.tracing.Controller           : test log with tracing info
          

          正如你所看到的,trace_idspan_id沒有設(shè)置。這是因?yàn)?span style="color: #F0506E; --tt-darkmode-color: #F0506E;">Micrometer Tracing還無法輕松處理響應(yīng)式流中的鏈路追蹤上下文。此外,響應(yīng)式流的Kotlin協(xié)程包裝器隱藏了鏈路追蹤上下文。因此,我們必須推遲當(dāng)前響應(yīng)式流的上下文來獲取鏈路追蹤信息。實(shí)際上,這看起來如下所示:

           Mono.deferContextual { contextView ->
             ContextSnapshot.setThreadLocalsFrom(
               contextView,
               ObservationThreadLocalAccessor.KEY
             ).use {
               log.info("test log with tracing info")
               Mono.empty<String>()
             }
          }.awaitSingleOrNull()
          

          為了更符合應(yīng)用性,我們可以將示例代碼提取到一個單獨(dú)的函數(shù)中。

          @GetMapping("/test")
          suspend fun test(): String {
            // ...
            observeCtx { log.info("test log with tracing info") }
            // ...
          }
          
          suspend inline fun observeCtx(crossinline f: () -> Unit) {
            Mono.deferContextual { contextView ->
              ContextSnapshot.setThreadLocalsFrom(
                contextView,
                ObservationThreadLocalAccessor.KEY
              ).use {
                f()
                Mono.empty<Unit>()
              }
            }.awaitSingleOrNull()
          }
          

          如果我們現(xiàn)在啟動應(yīng)用程序并調(diào)用我們的端點(diǎn),我們應(yīng)該能夠trace_id在日志中看到。

          trace_id=6c0053eba01199f194f5f76ff8d61917 span_id=967d591266756905 trace_flags=INFO 45139 --- [DefaultExecutor] com.example.tracing.Controller           : test log with tracing info
          

          WebClient 調(diào)用沒有產(chǎn)生追蹤信息

          第二個問題可以通過查看觀測云中的 trace 來發(fā)現(xiàn)。它僅顯示端點(diǎn)的父鏈路追蹤,但不顯示調(diào)用的子范圍 WebClient。理論上,Spring WebClient 以及 RestTemplate 都是由 Micrometer 自動檢測的。但是如果我們查看代碼,就會發(fā)現(xiàn)我們正在使用靜態(tài)構(gòu)建器方法 WebClient。為了從 WebClient 獲取自動鏈路追蹤,我們需要使用 Spring 框架提供的構(gòu)建器 bean。它可以通過我們類的構(gòu)造函數(shù)注入Controller。

          @RestController
          class Controller(
            webClientBuilder: WebClient.Builder
          ) {
          
           val webClient=webClientBuilder // use injected builder
            .baseUrl("https://jsonplaceholder.typicode.com")
            .build()
          
           // ...
          
          }
          

          通過上面的代碼調(diào)整后重新調(diào)用 endpoint,我們在觀測云中可以看到WebClient的跨度。Micrometer Tracing 還將自動為包含trace_id. 例如,如果我們調(diào)用另一個帶有鏈路追蹤功能的微服務(wù),它可以獲取 ID 并向觀測云發(fā)送附加信息。

          4. 觀測指南

          Micrometer Tracing 在 Spring 中自動為我們做了很多事情。但是,有時(shí)我們可能希望向鏈路追蹤范圍添加特定信息或觀察應(yīng)用程序中非傳入或傳出調(diào)用的特定部分。

          添加跨度標(biāo)簽

          我們可以定義自定義標(biāo)簽并將其添加到當(dāng)前觀察中以增強(qiáng)鏈路追蹤數(shù)據(jù)。要檢索當(dāng)前鏈路追蹤,我們可以使用ObservationRegistry類的 bean 。與日志記錄問題類似,我們必須使用包裝函數(shù)來獲取正確的上下文。

          @GetMapping("/test")
          suspend fun test(): String {
          
            observeCtx {
              val currentObservation=observationRegistry.currentObservation
              currentObservation?.highCardinalityKeyValue("test_key", "test sample value")
            }
          
            // ...
          }
          

          添加此代碼后,我們可以在觀測云中看到我們的自定義標(biāo)簽及其值。

          自定義可觀測

          使用 Micrometer API 創(chuàng)建自定義可觀測(跨度)通常很容易。但是,在使用響應(yīng)式流和協(xié)程時(shí),我們需要幫助上下文鏈路追蹤。如果我們在端點(diǎn)處理程序中創(chuàng)建一個新的觀測,它將被視為一個單獨(dú)的鏈路追蹤。為了使代碼可重用,我們可以編寫一個簡單的包裝函數(shù)來創(chuàng)建新的觀測點(diǎn)。它的工作原理與我們之前創(chuàng)建的用于使用 trace_id 。

          suspend fun runObserved(
            name: String, 
            observationRegistry: ObservationRegistry,
            f: suspend () -> Unit
          ) {
            Mono.deferContextual { contextView ->
              ContextSnapshot.setThreadLocalsFrom(
                contextView,
                ObservationThreadLocalAccessor.KEY
              ).use {
                val observation=Observation.start(name, observationRegistry)
                Mono.just(observation).flatMap {
                  mono { f() }
                }.doOnError {
                  observation.error(it)
                  observation.stop()
                }.doOnSuccess {
                  observation.stop()
                }
              }
            }.awaitSingleOrNull()
          }
          

          該函數(shù)可以將任何掛起函數(shù)包裝在新的觀察周圍。一旦執(zhí)行了給定的函數(shù),它將自動停止觀測。此外,我們將追蹤可能發(fā)生的任何錯誤并將其附加到鏈路追蹤中。

          我們現(xiàn)在可以應(yīng)用這個函數(shù)來觀察任何代碼,例如函數(shù)的執(zhí)行delay

          @GetMapping("/test")
          suspend fun test(): String {
          
            runObserved("delay", observationRegistry) {
              delay(1.seconds)
            }
          
            // ....
          }
          

          將此代碼添加到端點(diǎn)處理程序后,觀測云將向我們顯示該操作的自定義范圍。

          5. 數(shù)據(jù)庫鏈路追蹤

          典型的 Spring Boot 應(yīng)用程序通常會連接到實(shí)際應(yīng)用程序中的數(shù)據(jù)庫。要利用響應(yīng)式技術(shù)棧,建議使用 R2DBC(https://r2dbc.io/) API 而不是 JDBC 。

          由于Micrometer Tracing是一項(xiàng)相當(dāng)新的技術(shù),目前還沒有可用的自動追蹤。然而,Spring 團(tuán)隊(duì)正在研究創(chuàng)建自動配置。實(shí)驗(yàn)存儲庫參考鏈接:https://github.com/spring-projects-experimental/r2dbc-micrometer-spring-boot。

          當(dāng)前項(xiàng)目,需將添加以下依賴項(xiàng)到build.gradle.kts. 為了方便測試,我們不會使用真實(shí)的數(shù)據(jù)庫,而是使用 H2 內(nèi)存數(shù)據(jù)庫(https://www.h2database.com/html/main.html)。

           implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
           runtimeOnly("com.h2database:h2")
           runtimeOnly("io.r2dbc:r2dbc-h2")
          
           // R2DBC micrometer auto tracing
           implementation("org.springframework.experimental:r2dbc-micrometer-spring-boot:1.0.2")
          

          Kotlin代碼中,添加了一個帶有協(xié)程支持的簡單 CRUD 存儲庫。如下所示:

          @Table("todo")
          data class ToDo(
            @Id
            val id: Long=0,
            val title: String,
          )
          
          interface ToDoRepository : CoroutineCrudRepository<ToDo, Long>
          
          
          @RestController
          class Controller(
            val todoRepo: ToDoRepository,
            // ...
          ) {
          
            @GetMapping("/test")
            suspend fun test(): String {
              // ...
              // save
              val entry=ToDo(0,"Springboot3 + WebFlux + Kotlin ")
              todoRepo.save(entry)
              // Sample traced DB call
              val dbtodos=todoRepo.findAll().toList()
              
              // ...
          
              return "${dbtodos.size} $externalTodos"
            }
          }
          

          調(diào)用我們的 endpoint 將會再添加一個跨度。新的跨度名為query,包含多個標(biāo)簽,包括Spring Data R2DBC(https://spring.io/projects/spring-data-r2dbc/) 執(zhí)行的 SQL 查詢。

          結(jié)論

          Micrometer 和新的鏈路追蹤擴(kuò)展統(tǒng)一了Spring Boot 3及以上版本的可觀測性技術(shù)棧。為不同公司及其技術(shù)棧使用的不同鏈路追蹤解決方案提供了很好的抽象。因此,它簡化了我們開發(fā)人員的工作。

          在 Spring WebFlux 的響應(yīng)式編程方面,仍然有一些改進(jìn)的潛力,尤其是 Kotlin。Micrometer 團(tuán)隊(duì)正在與Project Reactor (https://projectreactor.io/),Spring WebFlux 使用的響應(yīng)式庫背后的團(tuán)隊(duì)進(jìn)行積極會談,以簡化響應(yīng)式技術(shù)棧的 Micrometer Tracing 的使用。

          開發(fā)Web應(yīng)用程序時(shí),經(jīng)常需要進(jìn)行一些全局性的配置,例如添加攔截器、設(shè)置消息轉(zhuǎn)換器、配置跨域資源共享(CORS)等。在Spring WebFlux中,我們可以通過實(shí)現(xiàn)WebFluxConfigurer接口來進(jìn)行這些全局配置。本文將詳細(xì)介紹如何使用WebFluxConfigurer進(jìn)行全局配置,以及常見的配置項(xiàng)和實(shí)現(xiàn)方式。

          全局配置接口

          WebFluxConfigurer是Spring WebFlux框架中用于配置WebFlux全局特性的接口,它提供了多個方法用于配置不同的功能。

          public interface WebFluxConfigurer {
          
              default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {}
          
              default void addFormatters(FormatterRegistry registry) {}
          
              default void configureViewResolvers(ViewResolverRegistry registry) {}
          
              default void addArgumentResolvers(ArgumentResolverConfigurer configurer) {}
          
              default void addReturnValueHandlers(ReturnValueHandlerConfigurer configurer) {}
          
              default void configureHandlerExceptionResolvers(HandlerExceptionResolverConfigurer configurer) {}
          
              default void addInterceptors(InterceptorRegistry registry) {}
          
              default void addCorsMappings(CorsRegistry registry) {}
          
              default void configurePathMatching(PathMatchConfigurer configurer) {}
          
              default void configureWebSocketTransport(WebSocketTransportConfigurer configurer) {}
          
              default void configureWebSocketHandlerMapping(WebSocketHandlerMappingConfigurer configurer) {}
          
              default void configureHttpMessageReader(ServerHttpMessageReaderConfigurer configurer) {}
          
              default void configureHttpMessageWriter(ServerHttpMessageWriterConfigurer configurer) {}
          
              default void configureClientHttpRequestFactory(ClientHttpConnectorConfigurer configurer) {}
          
              default void addResourceHandlers(ResourceHandlerRegistry registry) {}
          
              default void configureServerSentEvent(ServerSentEventHttpMessageWriterConfigurer configurer) {}
          }

          在上述接口中,每個方法對應(yīng)一個特定的全局配置功能。接下來,我們將詳細(xì)介紹每個方法的作用和實(shí)現(xiàn)方式。

          配置消息編解碼器

          在WebFlux中,消息編解碼器(Message Codec)負(fù)責(zé)將請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換為對象,并進(jìn)行序列化和反序列化。可以通過configureHttpMessageCodecs方法來配置消息編解碼器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
                  configurer.customCodecs().encoder(new MyEncoder());
                  configurer.customCodecs().decoder(new MyDecoder());
              }
          }

          在上述示例中,我們通過configureHttpMessageCodecs方法添加了自定義的編碼器和解碼器,實(shí)現(xiàn)了對特定數(shù)據(jù)格式的處理。

          配置格式化器

          格式化器(Formatter)用于將字符串類型的數(shù)據(jù)轉(zhuǎn)換為特定類型的對象,例如將字符串轉(zhuǎn)換為日期對象。可以通過addFormatters方法來配置格式化器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addFormatters(FormatterRegistry registry) {
                  registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
              }
          }

          在上述示例中,我們通過addFormatters方法添加了日期格式化器,將日期字符串轉(zhuǎn)換為yyyy-MM-dd格式的日期對象。

          配置視圖解析器

          視圖解析器(View Resolver)用于將邏輯視圖名稱解析為實(shí)際的視圖對象,例如將Thymeleaf模板文件解析為HTML視圖。可以通過configureViewResolvers方法來配置視圖解析器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureViewResolvers(ViewResolverRegistry registry) {
                  registry.viewResolver(new ThymeleafViewResolver());
              }
          }

          在上述示例中,我們通過configureViewResolvers方法添加了Thymeleaf視圖解析器,用于解析Thymeleaf模板文件。

          配置參數(shù)解析器和返回值處理器

          在WebFlux中,參數(shù)解析器(Argument Resolver)用于將請求中的參數(shù)解析為控制器方法的參數(shù),而返回值處理器(Return Value Handler)用于將控制器方法的返回值處理為響應(yīng)數(shù)據(jù)。可以通過addArgumentResolversaddReturnValueHandlers方法來配置參數(shù)解析器和返回值處理器。

          配置參數(shù)解析器

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addArgumentResolvers(ArgumentResolverConfigurer configurer) {
                  configurer.addCustomResolver(new MyArgumentResolver());
              }
          }

          在上述示例中,我們通過addArgumentResolvers方法添加了自定義的參數(shù)解析器MyArgumentResolver

          配置返回值處理器

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addReturnValueHandlers(ReturnValueHandlerConfigurer configurer) {
                  configurer.addCustomHandler(new MyReturnValueHandler());
              }
          }

          在上述示例中,我們通過addReturnValueHandlers方法添加了自定義的返回值處理器MyReturnValueHandler

          配置異常處理器

          在Web應(yīng)用程序開發(fā)中,異常處理器(Exception Resolver)用于處理控制器方法中拋出的異常,并返回適當(dāng)?shù)捻憫?yīng)。可以通過configureHandlerExceptionResolvers方法來配置異常處理器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configureHandlerExceptionResolvers(HandlerExceptionResolverConfigurer configurer) {
                  configurer.addExceptionHandler(new MyExceptionHandler());
              }
          }

          在上述示例中,我們通過configureHandlerExceptionResolvers方法添加了自定義的異常處理器MyExceptionHandler

          配置攔截器

          攔截器(Interceptor)用于在處理請求之前或之后執(zhí)行一些額外的邏輯,例如記錄請求日志、權(quán)限驗(yàn)證等。可以通過addInterceptors方法來配置攔截器。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addInterceptors(InterceptorRegistry registry) {
                  registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**");
              }
          }

          在上述示例中,我們通過addInterceptors方法添加了自定義的攔截器MyInterceptor,并指定了攔截路徑為/api/**

          配置跨域資源共享(CORS)

          跨域資源共享(Cross-Origin Resource Sharing,CORS)是一種用于解決跨域訪問問題的機(jī)制,可以通過addCorsMappings方法來配置CORS。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void addCorsMappings(CorsRegistry registry) {
                  registry.addMapping("/api/**")
                          .allowedOrigins("*")
                          .allowedMethods("GET", "POST", "PUT", "DELETE")
                          .allowCredentials(true)
                          .maxAge(3600);
              }
          }

          在上述示例中,我們通過addCorsMappings方法配置了跨域訪問的規(guī)則,允許所有來源的請求訪問/api/**路徑,并指定了允許的方法、是否允許攜帶憑證以及最大緩存時(shí)間。

          配置路徑匹配規(guī)則

          路徑匹配規(guī)則(Path Matching)用于指定URL路徑與請求處理器的映射關(guān)系。可以通過configurePathMatching方法來配置路徑匹配規(guī)則。

          @Configuration
          public class WebConfig implements WebFluxConfigurer {
          
              @Override
              public void configurePathMatching(PathMatchConfigurer configurer) {
                  configurer.setUseSuffixPatternMatch(false)
                            .setUseTrailingSlashMatch(false);
              }
          }

          在上述示例中,我們通過configurePathMatching方法配置了路徑匹配規(guī)則,禁用了后綴模式匹配和尾部斜杠匹配。

          總 結(jié)

          通過本文的詳細(xì)介紹,讀者應(yīng)該對如何使用WebFluxConfigurer進(jìn)行全局配置有了更深入的了解。合理地進(jìn)行全局配置可以提高開發(fā)效率,并確保應(yīng)用程序的穩(wěn)定性和可維護(hù)性。希望本文能夠幫助讀者更好地理解和應(yīng)用Spring WebFlux中的全局配置功能,為開發(fā)高效、靈活的Web應(yīng)用程序提供參考和指導(dǎo)。


          公眾號:九極客


          主站蜘蛛池模板: 日本福利一区二区| 亚洲中文字幕一区精品自拍| 伊人无码精品久久一区二区| 日本一区二区三区在线观看视频| 韩日午夜在线资源一区二区| 亚洲AV无码一区二区大桥未久| 国产区精品一区二区不卡中文 | 国产香蕉一区二区在线网站| 精品理论片一区二区三区| 久久婷婷久久一区二区三区| 精品视频一区二区观看| 精品成人乱色一区二区| 日韩精品国产一区| 任你躁国语自产一区在| 无码人妻一区二区三区在线水卜樱| 日韩AV无码一区二区三区不卡毛片| 久久精品道一区二区三区| 波多野结衣中文一区| 国产91精品一区二区麻豆网站| 久久久久人妻精品一区三寸蜜桃| 亚洲字幕AV一区二区三区四区| 久久高清一区二区三区| 国产成人精品无码一区二区三区| 国产一区二区三区小说| 亚洲美女视频一区二区三区| 伊人精品视频一区二区三区| 国产伦精品一区三区视频| 亚洲午夜一区二区电影院| 无码国产精品一区二区免费vr | 久久精品一区二区三区日韩 | 国产精品丝袜一区二区三区| 在线视频国产一区| 日本一区二区三区在线观看视频| 精品深夜AV无码一区二区老年| 国产精品福利区一区二区三区四区| 日本无码一区二区三区白峰美| 精品无码人妻一区二区三区 | 日本精品夜色视频一区二区| 97精品国产一区二区三区| 日韩人妻不卡一区二区三区 | 亚洲国产精品一区二区成人片国内|