第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

如何使用 WebClient 而不是 RestTemplate 來(lái)執(zhí)行非阻塞和異步調(diào)用

如何使用 WebClient 而不是 RestTemplate 來(lái)執(zhí)行非阻塞和異步調(diào)用

動(dòng)漫人物 2023-05-17 14:28:16
我有一個(gè)使用 Springboot Resttemplate 的 springboot 項(xiàng)目。我們已經(jīng)從 1.5.3 遷移到 springboot 2.0.1,我們正試圖通過(guò)使用 WebClient 使它的其余調(diào)用異步。我們?cè)?jīng)使用 Resttemplate 處理接收到的字符串,如下所示。但 WebClient 僅返回 Mono 或 Flux 中的數(shù)據(jù)。如何獲取字符串形式的數(shù)據(jù)。已經(jīng)嘗試過(guò) block() 方法,但它執(zhí)行異步調(diào)用。@Retryable(maxAttempts = 4, value = java.net.ConnectException.class,           backoff = @Backoff(delay = 3000, multiplier = 2))public Mono<String> getResponse(String url) {    return webClient.get().uri(urlForCurrent).accept(APPLICATION_JSON)                    .retrieve()                    .bodyToMono(String.class);}使用 RestTemplate 呈現(xiàn)數(shù)據(jù)流控制器接收客戶端調(diào)用provider 獲取 String 格式的數(shù)據(jù)提供程序處理字符串?dāng)?shù)據(jù)被提供給控制器Controller.java@RequestMapping(value = traffic/, method = RequestMethod.GET,                produces = MediaType.APPLICATION_JSON_VALUE)public String getTraffic(@RequestParam("place") String location) throws InterruptedException, ExecutionException {    String trafficJSON = Provider.getTrafficJSON(location)    return trafficJSON;}Provider.javapublic String getTrafficJSON(String location) {    String url = ----;    ResponseEntity<String> response = dataFetcher.getResponse(url);    /// RESPONSEBODY IS READ AS STRING AND IT NEEDS TO BE PROCESSED    if (null != response {        return parser.transformJSON(response.getBody(), params);    }    return null;}DataFetcher.java@Retryable(maxAttempts = 4,           value = java.net.ConnectException.class,           backoff = @Backoff(delay = 3000, multiplier = 2))public ResponseEntity<String> getResponse(String url) {    /* ----------------------- */    return getRestTemplate().getForEntity(urlForCurrent, String.class);}
查看完整描述

3 回答

?
胡說(shuō)叔叔

TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超8個(gè)贊

由于存在很多誤解,所以在這里我要澄清一些事情。

Spring 已經(jīng)正式聲明,如果可以的話,如果你想盡可能地證明未來(lái),請(qǐng)使用RestTemplate它。maintenence modeWebClient

如RestTemplate API中所述

注意:從 5.0 開始,這個(gè)類處于維護(hù)模式,只有少量的更改請(qǐng)求和錯(cuò)誤被接受。請(qǐng)考慮使用org.springframework.web.reactive.client.WebClient具有更現(xiàn)代 API 并支持同步、異步和流式傳輸方案的 。

非反應(yīng)性應(yīng)用

如果您的應(yīng)用程序是非反應(yīng)性應(yīng)用程序(不向調(diào)用客戶端返回通量或單聲道),您必須做的是block()在需要該值時(shí)使用。您當(dāng)然可以在您的應(yīng)用程序內(nèi)部使用Monoor?Flux,但最后您必須調(diào)用block()以獲取返回給調(diào)用客戶端所需的具體值。

非反應(yīng)性應(yīng)用程序使用例如作為底層服務(wù)器實(shí)現(xiàn),它遵循 servlet 規(guī)范,因此它將為每個(gè)請(qǐng)求分配 1 個(gè)線程,因此您將無(wú)法獲得反應(yīng)性應(yīng)用程序所獲得的性能提升tomcat。undertow

響應(yīng)式應(yīng)用

另一方面,如果您有一個(gè)反應(yīng)性應(yīng)用程序,則在任何情況下都不應(yīng)調(diào)用block()您的應(yīng)用程序。阻塞正是它所說(shuō)的,它會(huì)阻塞一個(gè)線程并阻止該線程執(zhí)行直到它可以繼續(xù),這在反應(yīng)世界中是不好的。

您也不應(yīng)該調(diào)用subscribe您的應(yīng)用程序,除非您的應(yīng)用程序是響應(yīng)的最終消費(fèi)者。例如,如果您正在調(diào)用一個(gè) api 來(lái)獲取數(shù)據(jù)并寫入您的應(yīng)用程序連接到的數(shù)據(jù)庫(kù)。您的后端應(yīng)用程序是最終消費(fèi)者。如果外部客戶端正在調(diào)用您的后端(例如反應(yīng)、角度應(yīng)用程序、移動(dòng)客戶端等),則外部客戶端是最終消費(fèi)者,并且是訂閱者。不是你。

這里的底層默認(rèn)服務(wù)器實(shí)現(xiàn)是一個(gè)netty服務(wù)器,它是一個(gè)非 servlet、基于事件的服務(wù)器,不會(huì)每個(gè)請(qǐng)求分配一個(gè)線程,服務(wù)器本身是線程不可知的,任何可用的線程都將在任何請(qǐng)求期間隨時(shí)處理任何事情。

webflux文檔清楚地指出,servlet 3.1+ 支持的服務(wù)器 tomcat 和 jetty 都可以與 webflux 以及非 serlet 服務(wù)器 netty 和 undertow 一起使用。

我怎么知道我有什么應(yīng)用程序?

Spring 指出,如果您同時(shí)擁有spring-webspring-webflux在類路徑中,則應(yīng)用程序?qū)⒅С?code>spring-web并默認(rèn)啟動(dòng)具有底層 tomcat 服務(wù)器的非反應(yīng)性應(yīng)用程序。

如果需要作為彈簧狀態(tài),可以手動(dòng)覆蓋此行為。

在您的應(yīng)用程序中同時(shí)添加spring-boot-starter-webspring-boot-starter-webflux模塊會(huì)導(dǎo)致 Spring Boot 自動(dòng)配置 Spring MVC,而不是 WebFlux。選擇此行為是因?yàn)樵S多 Spring 開發(fā)人員將其添加spring-boot-starter-webflux到他們的 Spring MVC 應(yīng)用程序中以使用反應(yīng)式 WebClient。您仍然可以通過(guò)將所選應(yīng)用程序類型設(shè)置為 來(lái)強(qiáng)制執(zhí)行您的選擇SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)。

“Spring WebFlux 框架”

那么如何按照題目提供的代碼實(shí)現(xiàn)WebClient呢?

@Retryable(maxAttempts = 4,

? ? ? ?value = java.net.ConnectException.class,

? ? ? ?backoff = @Backoff(delay = 3000, multiplier = 2))

public Mono<String> getResponse(String url) {

? ? return webClient.get()

? ? ? ? ? ? .uri(url)

? ? ? ? ? ? .exchange()

? ? ? ? ? ? .flatMap(response -> response.toEntity(String.class));

}

我會(huì)說(shuō)這是最簡(jiǎn)單和最少侵入性的實(shí)現(xiàn)。您當(dāng)然需要構(gòu)建一個(gè)合適的網(wǎng)絡(luò)客戶端,@Bean并將其自動(dòng)連接到它的類中。


查看完整回答
反對(duì) 回復(fù) 2023-05-17
?
MYYA

TA貢獻(xiàn)1868條經(jīng)驗(yàn) 獲得超4個(gè)贊

第一步是WebClient使用 baseUrl 構(gòu)建對(duì)象;

WebClient webClient = WebClient.builder()
    .baseUrl("http://localhost:8080/api") //baseUrl
    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .build();

然后選擇方法并將路徑與請(qǐng)求變量或正文有效負(fù)載一起附加。

ResponseSpec responseSpec = webClient
    .get()
    .uri(uriBuilder -> uriBuilder.path("/findById") //additional path
        .queryParam("id", id).build())
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new CustomRuntimeException("Error")));

等待響應(yīng)的block()功能bodyToMono。如果你想要響應(yīng)作為字符串,你可以使用谷歌的 gson 庫(kù)來(lái)轉(zhuǎn)換它。

Object response = responseSpec.bodyToMono(Object.class).block();Gson gson = new Gson();String str = gson.toJson(response);

如果你不想知道 api 調(diào)用的狀態(tài),你可以像下面那樣做。

webClient
    .post()
    .uri(uri -> uri.path("/save").build())
    .body( BodyInserters.fromObject(payload) )
    .exchange().subscribe();


查看完整回答
反對(duì) 回復(fù) 2023-05-17
?
繁星點(diǎn)點(diǎn)滴滴

TA貢獻(xiàn)1803條經(jīng)驗(yàn) 獲得超3個(gè)贊

首先要了解的是,如果您需要調(diào)用,.block()不妨堅(jiān)持使用RestTemplate,使用 WebClient 將一無(wú)所獲。


如果你想從使用 WebClient 中獲益,你需要開始以反應(yīng)的方式思考。反應(yīng)過(guò)程實(shí)際上只是一系列步驟,每個(gè)步驟的輸入都是前一步的輸出。當(dāng)收到請(qǐng)求時(shí),您的代碼會(huì)創(chuàng)建步驟序列并立即返回并釋放 http 線程。當(dāng)上一步的輸入可用時(shí),框架然后使用工作線程池來(lái)執(zhí)行每個(gè)步驟。


這樣做的好處是在接受競(jìng)爭(zhēng)請(qǐng)求的能力上獲得了巨大的收益,而代價(jià)很小,而不得不重新考慮您編寫代碼的方式。您的應(yīng)用程序只需要一個(gè)非常小的 http 線程池和另一個(gè)非常小的工作線程池。


當(dāng)您的控制器方法返回Monoor時(shí)Flux,您就做對(duì)了,不需要調(diào)用block().


像這樣的最簡(jiǎn)單的形式:


@GetMapping(value = "endpoint", produces = MediaType.TEXT_PLAIN_VALUE)

@ResponseBody

@ResponseStatus(OK)

public Mono<String> controllerMethod() {


    final UriComponentsBuilder builder =

            UriComponentsBuilder.fromHttpUrl("http://base.url/" + "endpoint")

                    .queryParam("param1", "value");


    return webClient

            .get()

            .uri(builder.build().encode().toUri())

            .accept(APPLICATION_JSON_UTF8)

            .retrieve()

            .bodyToMono(String.class)

            .retry(4)

            .doOnError(e -> LOG.error("Boom!", e))

            .map(s -> {


                // This is your transformation step. 

                // Map is synchronous so will run in the thread that processed the response. 

                // Alternatively use flatMap (asynchronous) if the step will be long running. 

                // For example, if it needs to make a call out to the database to do the transformation.


                return s.toLowerCase();

            });

}

轉(zhuǎn)向反應(yīng)式思考是一個(gè)相當(dāng)大的范式轉(zhuǎn)變,但值得付出努力。堅(jiān)持住,一旦您能夠在整個(gè)應(yīng)用程序中完全沒(méi)有阻塞代碼,這真的不是那么困難。構(gòu)建步驟并返回它們。然后讓框架管理步驟的執(zhí)行。


如果有任何不清楚的地方,我們很樂(lè)意提供更多指導(dǎo)。


記得玩得開心:)


查看完整回答
反對(duì) 回復(fù) 2023-05-17
  • 3 回答
  • 0 關(guān)注
  • 244 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)