整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Spring Boot :Spring Boot中的

          Spring Boot :Spring Boot中的響應式編程和WebFlux原理解析

          pring 5.0 中發布了重量級組件 Webflux,拉起了響應式編程的規模使用序幕。

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

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

          響應式編程

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

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

          響應式編程是基于異步和事件驅動的非阻塞程序,只需要在程序內啟動少量線程擴展,而不是水平通過集群擴展。

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

          Reactor

          Java 領域的響應式編程庫中,最有名的算是 Reactor 了。Reactor 也是 Spring 5 中反應式編程的基礎,Webflux 依賴 Reactor 而構建。

          Reactor 是一個基于 JVM 之上的異步應用基礎庫。為 Java 、Groovy 和其他 JVM 語言提供了構建基于事件和數據驅動應用的抽象庫。Reactor 性能相當高,在最新的硬件平臺上,使用無堵塞分發器每秒鐘可處理 1500 萬事件。

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

          Flux 和 Mono

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

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

          WebFlux 是什么?

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

          非阻塞的關鍵預期好處是能夠以小的固定數量的線程和較少的內存進行擴展。在服務器端 WebFlux 支持2種不同的編程模型:

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

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

          • Router Functions 對標準的 @Controller,@RequestMapping 等的 Spring MVC 注解,提供一套 函數式風格的 API,用于創建 Router、Handler 和Filter。
          • WebFlux 核心組件,協調上下游各個組件提供 響應式編程 支持。
          • Reactive Streams 一種支持 背壓 (Backpressure) 的 異步數據流處理標準,主流實現有 RxJava 和 Reactor,Spring WebFlux 集成的是 Reactor。

          默認情況下,Spring Boot 2 使用 Netty WebFlux,因為 Netty 在異步非阻塞空間中被廣泛使用,異步非阻塞連接可以節省更多的資源,提供更高的響應度。通過比較 Servlet 3.1 非阻塞 I / O 沒有太多的使用,因為使用它的成本比較高,Spring WebFlux 打開了一條實用的通路。

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

          Spring Webflux

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

          Spring Boot Webflux 有兩種編程模型實現,一種類似 Spring MVC 注解方式,另一種是基于 Reactor 的響應式方式。

          快速上手

          添加 webflux 依賴

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

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

          創建 Controller

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

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

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

          測試類

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

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

          Welcome to reactive world ~
          

          證明 Webflux 集成成功。

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

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

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

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

          您可能已經了解 Micrometer,因為它以前被用作公開獨立于平臺的指標和監控基于 JVM 的微服務(例如 Prometheus )的默認解決方案。最新產品通過獨立于平臺的鏈路追蹤解決方案擴展了 Micrometer 生態系統。這使得開發人員能夠使用一個通用 API 來檢測其應用程序,并以不同的格式將其導出到 Jaeger、Zipkin 或 OpenTelemetry 等鏈路追蹤收集器。

          本文將介紹在響應式編程 Kotlin 中,如何在 Spring Boot 3 WebFlux 利用 Micrometer 進行鏈路追蹤。

          1. 微服務設置

          接下來,我們將創建一個簡單的 Spring Boot 微服務,它提供一個響應式 REST 端點,該端點在內部查詢另一個第三方服務以獲取一些信息。目標是導出兩個操作的 trace。

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

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

          定義 endpoint

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

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

          @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 依賴項添加到我們的build.gradle.kts文件中。由于 Micrometer 支持不同的鏈路追蹤格式和供應商,因此依賴項被分開,我們只導入我們需要的內容。為了保持所有依賴項同步,我們使用 Micrometer Tracing BOM(bom 清單)。此外,我們添加了核心依賴項和橋接器,以將 Micrometer Tracing 轉換為 OpenTelemetry 格式(其他格式也可用)。

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

          我們還需要添加導出器依賴項來導出創建的 trace。在此示例中,我們將使用由 OpenTelemetry 維護并由 Micrometer Tracing 支持的 Zipkin 導出器。

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

          配置

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

          • 首先,我們必須在管理設置中啟用鏈路追蹤。我們還將鏈路追蹤采樣率設置為 1(默認值為 0.1),以便為服務收到的每個調用創建鏈路追蹤。在具有大量請求的生產系統中,您可能只想追蹤一些調用鏈路。
          • 此外,我們可以定義希望 Zipkin 導出器發送鏈路追蹤的端點 URL。
          • 最后,我們必須更新默認日志記錄模式以包含鏈路追蹤和 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. 測試

          現在我們已經完成了服務設置,我們可以運行它了。如果啟動應用程序,默認情況下,服務器應在端口下啟動 8080。然后,可以通過打開瀏覽器來調用我們創建的端點http://localhost:8080/test。以下是請求響應內容:

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

          要查看調用端點時創建的實際鏈路追蹤,我們需要收集并查看它們。在本教程中,我們將使用zipkin導出器將數據導出到 觀測云。當然也可以使用其他系統,例如 Zipkin、Grafana Loki 或 Datadog。

          現在您可以再次調用我們的 Spring Boot 服務的端點。之后,當您在 觀測云 中搜索任何 tracing 時,您應該能夠找到端點請求的鏈路追蹤信息。

          3. 問題

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

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

          日志缺少數據

          如果我們查看應用程序日志,可以發現調用端點時發出的日志消息。

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

          正如你所看到的,trace_idspan_id沒有設置。這是因為Micrometer Tracing還無法輕松處理響應式流中的鏈路追蹤上下文。此外,響應式流的Kotlin協程包裝器隱藏了鏈路追蹤上下文。因此,我們必須推遲當前響應式流的上下文來獲取鏈路追蹤信息。實際上,這看起來如下所示:

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

          為了更符合應用性,我們可以將示例代碼提取到一個單獨的函數中。

          @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()
          }
          

          如果我們現在啟動應用程序并調用我們的端點,我們應該能夠trace_id在日志中看到。

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

          WebClient 調用沒有產生追蹤信息

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

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

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

          4. 觀測指南

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

          添加跨度標簽

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

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

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

          自定義可觀測

          使用 Micrometer API 創建自定義可觀測(跨度)通常很容易。但是,在使用響應式流和協程時,我們需要幫助上下文鏈路追蹤。如果我們在端點處理程序中創建一個新的觀測,它將被視為一個單獨的鏈路追蹤。為了使代碼可重用,我們可以編寫一個簡單的包裝函數來創建新的觀測點。它的工作原理與我們之前創建的用于使用 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()
          }
          

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

          我們現在可以應用這個函數來觀察任何代碼,例如函數的執行delay

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

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

          5. 數據庫鏈路追蹤

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

          由于Micrometer Tracing是一項相當新的技術,目前還沒有可用的自動追蹤。然而,Spring 團隊正在研究創建自動配置。實驗存儲庫參考鏈接:https://github.com/spring-projects-experimental/r2dbc-micrometer-spring-boot。

          當前項目,需將添加以下依賴項到build.gradle.kts. 為了方便測試,我們不會使用真實的數據庫,而是使用 H2 內存數據庫(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代碼中,添加了一個帶有協程支持的簡單 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"
            }
          }
          

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

          結論

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

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

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

          全局配置接口

          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) {}
          }

          在上述接口中,每個方法對應一個特定的全局配置功能。接下來,我們將詳細介紹每個方法的作用和實現方式。

          配置消息編解碼器

          在WebFlux中,消息編解碼器(Message Codec)負責將請求和響應的數據轉換為對象,并進行序列化和反序列化。可以通過configureHttpMessageCodecs方法來配置消息編解碼器。

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

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

          配置格式化器

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

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

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

          配置視圖解析器

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

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

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

          配置參數解析器和返回值處理器

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

          配置參數解析器

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

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

          配置返回值處理器

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

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

          配置異常處理器

          在Web應用程序開發中,異常處理器(Exception Resolver)用于處理控制器方法中拋出的異常,并返回適當的響應。可以通過configureHandlerExceptionResolvers方法來配置異常處理器。

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

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

          配置攔截器

          攔截器(Interceptor)用于在處理請求之前或之后執行一些額外的邏輯,例如記錄請求日志、權限驗證等。可以通過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)是一種用于解決跨域訪問問題的機制,可以通過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方法配置了跨域訪問的規則,允許所有來源的請求訪問/api/**路徑,并指定了允許的方法、是否允許攜帶憑證以及最大緩存時間。

          配置路徑匹配規則

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

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

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

          總 結

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


          公眾號:九極客


          主站蜘蛛池模板: 538国产精品一区二区在线| 国产精品久久无码一区二区三区网| 国产乱码精品一区二区三区四川| 久久久人妻精品无码一区| 无码人妻精品一区二区三区99性 | 国模视频一区二区| 精品视频一区二区三区四区| 一区二区乱子伦在线播放| 蜜桃视频一区二区三区| 久久久久久人妻一区二区三区| 久久久综合亚洲色一区二区三区| 国产美女露脸口爆吞精一区二区 | 亚洲综合一区二区| 中文字幕亚洲一区二区三区| 一区五十路在线中出| 深夜福利一区二区| 亚洲日韩国产一区二区三区在线| 少妇精品久久久一区二区三区| 久久国产香蕉一区精品| 国产一区二区精品久久岳| 色噜噜AV亚洲色一区二区| 白丝爆浆18禁一区二区三区| 国产福利一区二区| 日本美女一区二区三区| 国产精品免费视频一区| 午夜福利国产一区二区| 国产成人综合精品一区| 亚洲欧洲∨国产一区二区三区| 综合久久一区二区三区 | 国产美女av在线一区| 视频一区精品自拍| 久久国产精品一区免费下载| 无码人妻精品一区二区三18禁| 亚洲国产精品一区第二页| 中文字幕亚洲一区二区三区| 亚洲中文字幕无码一区二区三区 | 精品人妻少妇一区二区三区不卡| 精品动漫一区二区无遮挡| 国产精品视频一区| 国产伦一区二区三区高清 | 精品一区二区三区视频在线观看|