Spring Webclient中的onStatus为何不适用于HttpStatus::is4xxClientError?

huangapple go评论52阅读模式
英文:

How come Spring Webclient onStatus is not applicable for HttpStatus::is4xxClientError?

问题

I've translated the provided text into Chinese for you:

我已经基于 `spring-boot-starter-webflux` 构件实现了一个Web客户端。

代码:

~~~java
// 创建客户端bean以在整个服务中使用
@Bean
public WebClient geoserverWebClient() {
	// 为了避免出现DataBufferLimitException
	final int size = 16 * 1024 * 1024;
	final ExchangeStrategies strategies = ExchangeStrategies.builder()
		.codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size))
		.build();
	
	return WebClient.builder()
		.exchangeStrategies(strategies)
		.baseUrl(geoserverURL) 
        .defaultHeader(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString(geoserverBasicAuth.getBytes()))
		.build();
}
~~~

到目前为止,我在使用它时没有遇到任何问题:

~~~java
// 发送getMap WMS请求到geoserver
public Mono<byte[]> getMap(String requestURL){

    return geoserverWebClient
    .get()
    .uri(requestURL)
    .retrieve()
    .bodyToMono(byte[].class);
}
~~~

但是,如果我添加`onStatus`方法来检查HTTP错误,我会遇到以下错误:_“WebClient.ResponseSpec中的onStatus(Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>)方法不适用于参数(HttpStatus::is4xxClientError”_ 以及对于`HttpStatus`的错误_“HttpStatus类型未定义is4xxClientError(HttpStatusCode)”_。

~~~java
// 其他各种导入...

import org.springframework.http.HttpStatus;

// 发送getMap WMS请求到geoserver
public Mono<byte[]> getMap(String requestURL){

    return geoserverWebClient
    .get()
    .uri(requestURL)
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError,
            error -> Mono.error(new RuntimeException("API not found")))
    .bodyToMono(byte[].class);
}
~~~

我已经阅读了该方法,并且由于我使用的是Spring Boot版本3.0.5,我不明白为什么它不按照文档工作。

我尝试从`Builder`开始,但它不会改变一点。我还尝试了其他HTTP错误,甚至编写了`org.springframework.http.HttpStatus::is4xxClientError`。所有这些都没有奏效。我唯一没有做的事情是实例化一个`HttpStatus`对象 - 但我认为`.onStatus()`方法会从`.retrieve()`方法中获取正确的对象。

我考虑到也许我的IDE当前没有正确加载导入。我关闭了项目,重新启动了IDE并重新打开了项目,但没有效果。即使删除本地的.m2文件夹也无法解决问题。

这是Java/Spring的问题还是我的IDE(VS Code)的问题?
英文:

I've implemented a web client based on the spring-boot-starter-webflux artifact.

The code:

// create  client bean to use throughout services
@Bean
public WebClient geoserverWebClient() {
	// to not fall prone to DataBufferLimitException
	final int size = 16 * 1024 * 1024;
	final ExchangeStrategies sΩtrategies = ExchangeStrategies.builder()
		.codecs(codecs -&gt; codecs.defaultCodecs().maxInMemorySize(size))
		.build();
	
	return WebClient.builder()
		.exchangeStrategies(strategies)
		.baseUrl(geoserverURL) 
        .defaultHeader(HttpHeaders.AUTHORIZATION, &quot;Basic &quot; + Base64Utils.encodeToString(geoserverBasicAuth.getBytes()))
		.build();
}

So far I didn't have any issues with using it like:

// send getMap WMS to geoserver
public Mono&lt;byte[]&gt; getMap(String requestURL){

    return geoserverWebClient
    .get()
    .uri(requestURL)
    .retrieve()
    .bodyToMono(byte[].class);
}

But if I add the onStatus method to it in order to check for HTTP errors, I get the errors: "The method onStatus(Predicate<HttpStatusCode>, Function<ClientResponse,Mono<? extends Throwable>>) in the type WebClient.ResponseSpec is not applicable for the arguments (HttpStatus::is4xxClientError" for onStatus and "The type HttpStatus does not define is4xxClientError(HttpStatusCode)" for HttpStatus.

// various other imports ...

import org.springframework.http.HttpStatus;

// send getMap WMS to geoserver
public Mono&lt;byte[]&gt; getMap(String requestURL){

    return geoserverWebClient
    .get()
    .uri(requestURL)
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError,
            error -&gt; Mono.error(new RuntimeException(&quot;API not found&quot;)))
    .bodyToMono(byte[].class);
}

I've read up on the method and as I'm using Spring Boot version 3.0.5 I don't see why it wouldn't work as documented.

I tried starting with the Builder instead but it wouldn't change a bit. I also tried other HTTP errors and even writing out org.springframework.http.HttpStatus::is4xxClientError. None of that worked. The only thing I didn't do is instantiate a HttpStatus object - but I assume the .onStatus() method would get the right object from the .retrieve() method.

I considered that perhaps my IDE isn't loading the imports correctly at the moment. I've closed the project, restarted the IDE and reopened the project but to no avail. Even deleting the local .m2 folder wouldn't solve the issue.

Is this a Java/Spring problem or a problem with my IDE (VS Code)?

答案1

得分: 1

Predicate中的类型参数(onStatus(...)的第一个参数)不是org.springframework.http.HttpStatus类型,而是org.springframework.http.HttpStatusCode类型(这恰好是HttpStatus枚举实现的接口)。

因此,请将方法引用从HttpStatus::is4xxClientError更改为HttpStatusCode::is4xxClientError,错误应该消失。

英文:

The type parameter in the Predicate (first argument to onStatus(...)) is not of type org.springframework.http.HttpStatus, but of type org.springframework.http.HttpStatusCode (which happens to be an interface that the HttpStatus enum implements).

As such, switch the method reference from HttpStatus::is4xxClientError to HttpStatusCode::is4xxClientError, and the error should go away.

huangapple
  • 本文由 发表于 2023年5月17日 22:51:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273423.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定