对于反应编程和尝试通过WebFlux和WebClient创建反应服务是新的。
方法的流程类似于
private Mono<ResponseEntity<Recommendations>> myMethod(final Request request, final String variantName) {
Mono<String> response = webClient.build()
.post()
.uri(uri)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(requestBody)
.retrieve().bodyToMono(String.class);
var recommendations = ((XYZResponseMapper) responseMapper).mapReactive(request, response, useCaseId, variantName); //return type Recommendations
var entity = new ResponseEntity<>(recommendations, nullHeaders, HttpStatus.OK);
return Mono.just(entity);
}
简短的答案很可能是否定的。
更长的版本是,当某人开始订阅您的服务(它是一个生产者)时,客户端希望使用数据。订阅一开始,webflux就要在应用程序内部构建反应链。这个链可以与一种回调链相比较,被称为“组装阶段”。
在这个组装阶段,重要的是每个通量/单声道的返回是相互连接的。否则你就会破坏链条。
var firstAction = Mono.just("Hello").flatMap(value -> {
// do something
});
// Next action needs to chain on the last
var secondAction = firstAction.flatMap(value -> {
// Do the next thing
});
// Can be combined
var bothActions = Mono.just("Hello").flatMap(value -> {
// do something
}).flatMap(value -> {
// do next thing
});
private Mono<ResponseEntity<Recommendations>> myMethod(final Request request, final String variantName) {
// Here you have a response
Mono<String> response = webClient.build()
.post()
.uri(uri)
// Not needed content type will default to json
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
// will also default to json
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(requestBody)
.retrieve().bodyToMono(String.class);
// here you pass the response into a function, hence probably breaking the chain
var recommendations = ((XYZResponseMapper) responseMapper).mapReactive(request, response, useCaseId, variantName); //return type Recommendations
var entity = new ResponseEntity<>(recommendations, nullHeaders, HttpStatus.OK);
// Here you are suddenly creating a new mono, which tells me you deffo broke the chain and need to recreate it by doing a mono#just
return Mono.just(entity);
}
那么我们该怎么解决呢?
private Mono<Recommendations> myMethod(final Request request, final String variantName) {
// You should not build a webclient on each request, you should build it in a @Bean
final Mono<XYZResponse> response = webClient.build()
.post()
.uri(uri)
.bodyValue(requestBody)
.retrieve()
// Map into a class representation to uphold type safety
.bodyToMono(XYZResponse.class);
// if we need to do additional transformations we can flatMap and chain on
final Mono<Recommendations> recommendations = response.flatMap(value -> {
var recommendations = mapper.toRecommendations(value);
});
// No need to wrap it in a response webflux will do that for you automatically when you return it to the client
return recommendations;
}
然后我们甚至可以把它改写得更短。
private Mono<Recommendations> myMethod(final Request request, final String variantName) {
return webClient.build()
.post()
.uri(uri)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(XYZResponse.class)
.flatMap(value -> {
var recommendations = mapper.toRecommendations(value);
});
}
我通常把return语句写在第一行,然后再写我的chain。
@Configuration
public class ClientConfig {
@Bean
public WebClient webclient(WebClient.Builder webClient) {
return webClient.baseUrl( ... )
.build();
}
}
@Component
public class RecommendationHandler {
final private WebClient
@Autowire
public RecommendationHandler(WebClient webClient) {
this.webClient = webClient;
}
private Mono<Recommendations> getRecommendations(RequestBody requestBody) {
return webClient
.post()
.bodyValue(requestBody)
.retrieve()
.bodyToMono(XYZResponse.class)
.flatMap(value -> {
var recommendations = mapper.toRecommendations(value);
});
}
}
我在UserResource中有一个具有这种签名的方法。我正在测试的java(rest控制器): 这里的关键时刻是@AuthenticationMain(我们有一个自定义类)作为方法参数传递。 我在测试中所做的是将UserResources自动连接到测试类中,并尝试调用getUsers方法 故障原因如下: 我知道它可能不像只是传递一个构造的User对象那样简单,因为Spring无法正确解析它,但是
我尝试使处理程序和路由器类的Spring引导webflow。模型类是用户类。代码是 下面是webflux项目的处理程序类。在register方法中,我编写了id复制测试代码。但这是完全错误的。 我想提取的用户名或id字符串从Mono的Spring webflow.将需要任何评论。我被这部分卡住了。
问题内容: 注意:这旨在作为常见问题的规范答案。 我有一个带有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示同时创建了bean和bean,但是每当尝试在服务bean上调用方法时,我都会得到一个。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 带注释的字段是因为Spring不知道您
我对反应性非常陌生,所以在范式转变中有点挣扎,但是也许有人能帮我克服这个问题? 我的控制器将Mono(称为“limit”)作为服务参数传递给我的服务。Mono在subscribe上发出一个整数,服务使用该整数执行其工作,该整数返回一个流量。 在我的服务方法中,我需要订阅mono,但我需要在我的服务方法(对其他endpoint进行web客户端REST调用)之前订阅mono,因为REST调用中需要限制
我的代码是这样构造的- 我正在努力实现这一点: 方法1()返回地址时,我需要使用它并调用方法2()来更新MongoDB文档中的地址。也没有抛出异常。但是我没有看到任何日志在方法2() 代码: 虽然调用了method2(),但MongoDB中的文档更新没有发生。
问题内容: 假设我有汽车清单: 如何缩短上面的代码?简而言之,如何在List的每个元素上调用方法? 例如,在Python中: 问题答案: 更新: 有关使用lambda表达式的Java8解决方案,请参见aaiezza的答案。 Java 8之前的原始答案: 使用Guava可以实现效果,实现比您现有的更加冗长: (请记住,返回的视图将延迟应用该函数- 如果要立即复制,则需要将返回的列表复制到新列表中。)