java - 请求不会在没有 block 的情况下发送()

标签 java spring spring-boot spring-webflux

我想使用这个 webflux 客户端代码来发送有回复和无回复的 POST 请求。我试过这个代码实现:

public class RestClientBuilder {
    private String token;
    private String username;
    private String password;
    private URL gatewayUrl;
    private SslContextBuilder sslContextBuilder;

    public static RestClientBuilder builder() {
        return new RestClientBuilder();
    }

    public RestClientBuilder token(String token) {
        this.token = validateAndTrim(token, "Token");
        return this;
    }

    public RestClientBuilder usernamePassword(String username, String password) {
        this.username = validateAndTrim(username, "Username");
        this.password = validateAndTrim(password, "Password");
        return this;
    }

    private String validateAndTrim(String value, final String parameter) {
        if (value == null || value.trim().isEmpty()) {
            throw new IllegalArgumentException(parameter + " is empty");
        }
        return value.trim();
    }

    public RestClientBuilder gatewayUrl(String gatewayUrl) {
        String urlSt = validateAndTrim(gatewayUrl, "Gateway URL");
        try {
            this.gatewayUrl = new URL(urlSt);
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException("Malformed URL: " + urlSt, e);
        }
        return this;
    }

    public RestClientBuilder truststore(File truststoreFile) {
        getSslContextBuilder().trustManager(truststoreFile);
        return this;
    }

    public RestClientBuilder sslCertificate(File keyCertChainFile, File keyFile, String keyPassword) {
        getSslContextBuilder().keyManager(keyCertChainFile, keyFile, keyPassword);
        return this;
    }

    public RestClient build() throws SSLException {
        SslContext sslContext = sslContextBuilder != null ? sslContextBuilder.build() : null;
        return new RestClient(gatewayUrl.toString(), token, username, password, sslContext);
    }

    private SslContextBuilder getSslContextBuilder() {
        if (sslContextBuilder == null) {
            sslContextBuilder = SslContextBuilder.forClient();
        }
        return sslContextBuilder;
    }

}

其余客户端的实现:

public class RestClient {

    private WebClient client;
    private String gatewayUrl;

    public RestClient(String gatewayUrl, String token, String username, String password, SslContext sslContext) {
        this.gatewayUrl = gatewayUrl;
        WebClient.Builder builder = WebClient.builder().baseUrl(gatewayUrl);
        if (sslContext != null) {
            HttpClient httpClient = HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
            ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient);
            builder.clientConnector(httpConnector);
        }
        if (username != null && password != null) {
            builder.filter(basicAuthentication(username, password));
        }
        client = builder.build();
    }

    public Mono<Void> executeOnly(ReportRequest transaction) {
        Mono<ReportRequest> transactionMono = Mono.just(transaction);
        return client.post().uri(gatewayUrl)
                .accept(MediaType.APPLICATION_XML)
                .contentType(MediaType.APPLICATION_XML)
                .body(transactionMono, ReportRequest.class)
                .retrieve()
                .bodyToMono(Void.class);
    }
}

进行远程调用:

public class ReportingProcessor {

    private String URL2 = "......";

    public void collectEnvironmentData() throws JAXBException {

        ReportRequest report = new ReportRequest();
        report.setVersion("1.0");

        RestClient client = null;
        try {
            client = RestClientBuilder.builder()
                    .gatewayUrl(URL2)
//                .token(contract.getTerminal_token())
//                  .usernamePassword("user", "password")
//                .truststore(new File("server.pem"))
//                .sslCertificate(new File("client.pem"), new File("clientKey.p8"), "secret")
                    .build();
        } catch (SSLException e) {
            e.printStackTrace();
        }

        Mono<Void> result = client.executeOnly(report);
        Void response = result.block();

    }

当我删除 Void response = result.block(); 时,请求不会发送。我找不到原因。你能给我一些建议,告诉我如何在不使用 block() 的情况下使客户端代码正常工作吗?

最佳答案

无论何时使用 Spring-webflux,您都必须牢记一件事。即你不必打破你的链条。因为有必要,有人应该在你的链上调用订阅。因为它适用于 RXJava 规范。

如果你打破了链,那么你必须调用block(),这不是推荐的

您必须按照以下方式修改您的代码。

假设您有一个处理程序正在调用您的 collectEnvironmentData() 方法,而您的方法正在调用远程服务。

public  Mono<ServerResponse> handelerMethod(ServerRequest request){
  return collectEnvironmentData().flatMap(aVoid -> ServerResponse.ok().build());
}

你的方法应该修改为

public Mono<Void> collectEnvironmentData() throws JAXBException {

ReportRequest report = new ReportRequest();
report.setVersion("1.0");

RestClient client = null;
try {
    client = RestClientBuilder.builder()
            .gatewayUrl(URL2)
//                .token(contract.getTerminal_token())
//                  .usernamePassword("user", "password")
//                .truststore(new File("server.pem"))
//                .sslCertificate(new File("client.pem"), new File("clientKey.p8"), 
//"secret").build();
} catch (SSLException e) {
    e.printStackTrace();
}

return client.executeOnly(report);
}

以上述方式更改您的实现,希望它能起作用。

关于java - 请求不会在没有 block 的情况下发送(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58364708/

相关文章:

java - 即使您在内部使用类级别变量,使用@Autowired anno并且从不在bean上调用set方法是否可以提供线程安全性?

java - 如何将 MySQL 转换为条件查询?

java - 如何在 Spring Boot 中设置经过身份验证的 JavaMailSender

java - Java-插入参数(参数)时输出已更改

java - Spring的@Transactional注解是否会混淆其他注解

java - 无法从命令提示符运行 Spring Boot 应用程序

java - 如何扩展使用@ConditionalOnMissingBean注释的默认bean?

java - 当我们在@Bean中创建新类,并在另一个@Bean中使用@Bean时会发生什么

java - 测试对象是否是特定类型的通用列表

java - 如何在java中正确编码这个URL?