首页 > 编程语言 > 详细

Spring WebClient使用

时间:2020-08-30 23:11:46      阅读:141      评论:0      收藏:0      [点我收藏+]

如下为一个使用了线程池,SSL,出现指定异常后充实,超时配置的demo

SSL配置

package com.demo.client;

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SNIMatcher;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import reactor.netty.tcp.SslProvider.SslContextSpec;

public class SslConsumer implements Consumer<SslContextSpec> {

    private Logger logger = LoggerFactory.getLogger(SslConsumer.class);

    private String keyStorePath;
    private String password = "123456";
    private boolean trustServer = true;// 测试,默认为true
    private String serverCaPath = "";

    public SslConsumer(String keyStorePath) {
        this.keyStorePath = keyStorePath;
    }

    @Override
    public void accept(SslContextSpec t) {
        try {
            t.sslContext(createSslContext(loadKeyStore(keyStorePath))).handlerConfigurator(handler -> {

                SSLEngine engine = handler.engine();
                List<SNIMatcher> matchers = new LinkedList<SNIMatcher>();
                SNIMatcher matcher = new SNIMatcher(0) {
                    @Override
                    public boolean matches(SNIServerName serverName) {
                        // 返回true,不验证主机名
                        return true;
                    }
                };
                matchers.add(matcher);
                SSLParameters params = new SSLParameters();
                params.setSNIMatchers(matchers);
                engine.setSSLParameters(params);

            });
        } catch (Exception e) {

        }
    }

    private SslContext createSslContext(KeyStore keyStore) throws Exception {
        SslContextBuilder builder = SslContextBuilder.forClient();
        KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
        keyMgrFactory.init(keyStore, password.toCharArray());
        builder.keyManager(keyMgrFactory);

        SSLX509TrustMgr trustMgr = null;
        if (trustServer) {
            trustMgr = new SSLX509TrustMgr();
        } else {
            trustMgr = new SSLX509TrustMgr(getSeverPublicKey(serverCaPath));
        }
        builder.trustManager(trustMgr);

        List<String> ciper = new ArrayList<String>();
        ciper.add("TLS_RSA_WITH_AES_128_GCM_SHA256");
        ciper.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
        ciper.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");

        builder.ciphers(ciper);
        return builder.build();
    }

    private KeyStore loadKeyStore(String keyStorePath) {
        KeyStore keyStore = null;
        InputStream in = null;
        try {
            in = new FileInputStream(keyStorePath);
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(in, password.toCharArray());

        } catch (Exception e) {
            logger.error("", e);
        }

        return keyStore;
    }

    private PublicKey getSeverPublicKey(String serverCaPath) {
        PublicKey key = null;
        InputStream in = null;
        try {
            in = new FileInputStream(serverCaPath);
            X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(in);
            key = cert.getPublicKey();
        } catch (Exception e) {
            logger.error("", e);
        }
        return key;
    }

}

验证服务器整数实现类

目前没有做任何处理,有需要验证服务器证书时,可以在对应的重写方法中进行处理

package com.demo.client;

import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class SSLX509TrustMgr implements X509TrustManager {

    private PublicKey serverPublicKey;

    public SSLX509TrustMgr() {
        
    }
    public SSLX509TrustMgr(PublicKey serverPublicKey) {
        this.serverPublicKey = serverPublicKey;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // TODO Auto-generated method stub

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }

}

WebClient工具类

package com.demo.client;

import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;

import io.netty.channel.ChannelOption;
import io.netty.channel.ConnectTimeoutException;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;
import reactor.retry.Backoff;
import reactor.retry.Retry;

public class WebClientUtil {

    private static Logger logger = LoggerFactory.getLogger(WebClientUtil.class);
    private static Map<String, WebClient> webClientMap = new ConcurrentHashMap<String, WebClient>();

    public static WebClient createWebClient(String keyStorePath) {
        ConnectionProvider provider = ConnectionProvider.builder("wc-").maxConnections(30)
                .maxIdleTime(Duration.ofSeconds(30)).maxLifeTime(Duration.ofSeconds(30))
                .pendingAcquireTimeout(Duration.ofSeconds(30)).build();

        HttpClient httpClient = HttpClient.create(provider).secure(new SslConsumer(keyStorePath))
                .tcpConfiguration(client -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                        .doOnConnected(con -> con.addHandlerLast(new ReadTimeoutHandler(20))
                                .addHandlerLast(new WriteTimeoutHandler(10)))
                        .runOn(LoopResources.create("loop-", 20, 20, true)));

        return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();
    }

    public static Mono<String> doPost(String url, String data, String keyStorePath) {
        WebClient webClient = webClientMap.get(url);
        if (webClient == null) {
            webClient = createWebClient(keyStorePath);
            WebClient putIfAbsent = webClientMap.putIfAbsent(url, webClient);
            if (putIfAbsent != null) {
                webClient = putIfAbsent;
            }
        }

        Retry<?> retry = Retry.anyOf(ConnectTimeoutException.class, NoRouteToHostException.class).retryMax(3)
                .backoff(Backoff.fixed(Duration.ofMillis(100)));

        Mono<String> mono = webClient.post().uri(url).accept(MediaType.APPLICATION_JSON).bodyValue(data).retrieve()
                .bodyToMono(String.class).timeout(Duration.ofSeconds(30)).doOnError(ConnectException.class, e -> {
                    logger.error("", e);
                }).doOnError(NoRouteToHostException.class, e -> {
                    logger.error("", e);
                }).retryWhen(retry);
        return mono;
    }

}

 

Spring WebClient使用

原文:https://www.cnblogs.com/qq931399960/p/13586927.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!