zoukankan      html  css  js  c++  java
  • Java调用Http/Https接口(7,end)--WebClient调用Http/Https接口

    WebClient是Spring提供的非阻塞、响应式的Http客户端,提供同步及异步的API,将会代替RestTemplate及AsyncRestTemplate。文中所使用到的软件版本:Java 1.8.0_191、SpringBoot 2.2.1.RELEASE。

    1、服务端

    参见Java调用Http接口(1)--编写服务端 

    2、调用

    使用WebClient需要用到Reactor Netty,依赖如下:

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webflux</artifactId>
            </dependency>
            <dependency>
                <groupId>io.projectreactor.netty</groupId>
                <artifactId>reactor-netty</artifactId>
            </dependency>

    2.1、GET请求

        public static void get() {
            String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白";
            WebClient webClient = WebClient.create();
            Mono<String> mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
            //同步方式
            System.out.println("get block返回结果:" + mono.block());
            
            //异步方式
            final CountDownLatch latch = new CountDownLatch(5);
            for (int i = 0; i < 5; i++) {
                requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白" + i;
                mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
                mono.subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) {
                        latch.countDown();
                        System.out.println("get subscribe返回结果:" + s);
                    }
                });
            }
            
            try {
                latch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.2、POST请求(发送键值对数据)

        public static void post() {
            String requestPath = "http://localhost:8080/demo/httptest/getUser";
            WebClient webClient = WebClient.create();
            MultiValueMap<String, String> map = new LinkedMultiValueMap <String, String>();
            map.add("userId", "1000");
            map.add("userName", "李白");
            Mono<String> mono = webClient.post().uri(requestPath).bodyValue(map).retrieve().bodyToMono(String.class);
            System.out.println("post返回结果:" + mono.block());
        }

    2.3、POST请求(发送JSON数据)

        public static void post2() {
            String requestPath = "http://localhost:8080/demo/httptest/addUser";
            WebClient webClient = WebClient.create();
            String param = "{"userId": "1001","userName":"杜甫"}";
            Mono<String> mono = webClient.post().uri(requestPath).contentType(MediaType.APPLICATION_JSON).bodyValue(param)
                    .retrieve().bodyToMono(String.class);
            System.out.println("post json返回结果:" + mono.block());
        }

    2.4、上传文件

        public static void upload() {
            String requestPath = "http://localhost:8080/demo/httptest/upload";
            WebClient webClient = WebClient.create();
            Mono<String> mono = webClient.post().uri(requestPath).contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .bodyValue(new FileSystemResource("d:/a.jpg")).retrieve().bodyToMono(String.class);
            System.out.println("upload返回结果:" + mono.block());
        }

    2.5、上传文件及发送键值对数据

        public static void mulit() {
            String requestPath = "http://localhost:8080/demo/httptest/multi";
            WebClient webClient = WebClient.create();
            
            MultipartBodyBuilder builder = new MultipartBodyBuilder();
            builder.part("param1", "参数1");
            builder.part("param2", "参数2");
            builder.part("file", new FileSystemResource("d:/a.jpg"));
            MultiValueMap<String, HttpEntity<?>> parts = builder.build();
            Mono<String> mono = webClient.post().uri(requestPath)
                    .bodyValue(parts).retrieve().bodyToMono(String.class);
            System.out.println("mulit返回结果:" + mono.block());
        }

    2.6、完整例子

    package com.inspur.demo.http.client;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.function.Consumer;
    
    import org.springframework.core.io.FileSystemResource;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.MultipartBodyBuilder;
    import org.springframework.util.LinkedMultiValueMap;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.reactive.function.client.WebClient;
    
    import reactor.core.publisher.Mono;
    
    /**
     * 
     * 通过WebClient调用Http接口
     *
     */
    public class WebClientCase {
        /**
         *  GET请求
         */
        public static void get() {
            String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白";
            WebClient webClient = WebClient.create();
            Mono<String> mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
            //同步方式
            System.out.println("get block返回结果:" + mono.block());
            
            //异步方式
            final CountDownLatch latch = new CountDownLatch(5);
            for (int i = 0; i < 5; i++) {
                requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=李白" + i;
                mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
                mono.subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) {
                        latch.countDown();
                        System.out.println("get subscribe返回结果:" + s);
                    }
                });
            }
            
            try {
                latch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         *  POST请求(发送键值对数据)
         */
        public static void post() {
            String requestPath = "http://localhost:8080/demo/httptest/getUser";
            WebClient webClient = WebClient.create();
            MultiValueMap<String, String> map = new LinkedMultiValueMap <String, String>();
            map.add("userId", "1000");
            map.add("userName", "李白");
            Mono<String> mono = webClient.post().uri(requestPath).bodyValue(map).retrieve().bodyToMono(String.class);
            System.out.println("post返回结果:" + mono.block());
        }
        
        /**
         *  POST请求(发送json数据)
         */
        public static void post2() {
            String requestPath = "http://localhost:8080/demo/httptest/addUser";
            WebClient webClient = WebClient.create();
            String param = "{"userId": "1001","userName":"杜甫"}";
            Mono<String> mono = webClient.post().uri(requestPath).contentType(MediaType.APPLICATION_JSON).bodyValue(param)
                    .retrieve().bodyToMono(String.class);
            System.out.println("post json返回结果:" + mono.block());
        }
        
        /**
         * 上传文件
         */
        public static void upload() {
            String requestPath = "http://localhost:8080/demo/httptest/upload";
            WebClient webClient = WebClient.create();
            Mono<String> mono = webClient.post().uri(requestPath).contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .bodyValue(new FileSystemResource("d:/a.jpg")).retrieve().bodyToMono(String.class);
            System.out.println("upload返回结果:" + mono.block());
        }
        
        /**
         * 上传文件及发送键值对数据
         */
        public static void mulit() {
            String requestPath = "http://localhost:8080/demo/httptest/multi";
            WebClient webClient = WebClient.create();
            
            MultipartBodyBuilder builder = new MultipartBodyBuilder();
            builder.part("param1", "参数1");
            builder.part("param2", "参数2");
            builder.part("file", new FileSystemResource("d:/a.jpg"));
            MultiValueMap<String, HttpEntity<?>> parts = builder.build();
            Mono<String> mono = webClient.post().uri(requestPath)
                    .bodyValue(parts).retrieve().bodyToMono(String.class);
            System.out.println("mulit返回结果:" + mono.block());
        }
        
        public static void main(String[] args) {
            get();
            post();
            post2();
            upload();
            mulit();
        }
    
    }
    View Code

    3、调用Https接口

    与调用Http接口不一样的部分主要在设置ssl部分,设置方法是生成合适的ClientHttpConnector;下面用GET请求来演示ssl的设置,其他调用方式类似。

    package com.inspur.demo.http.client;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.security.KeyStore;
    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 javax.net.ssl.TrustManagerFactory;
    
    import org.springframework.http.client.reactive.ClientHttpConnector;
    import org.springframework.http.client.reactive.ReactorClientHttpConnector;
    import org.springframework.web.reactive.function.client.WebClient;
    
    import com.inspur.demo.common.util.FileUtil;
    
    import io.netty.handler.ssl.SslContext;
    import io.netty.handler.ssl.SslContextBuilder;
    import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
    import reactor.core.publisher.Mono;
    import reactor.netty.http.client.HttpClient;
    import reactor.netty.tcp.SslProvider.SslContextSpec;
    
    /**
     * 通过WebClient调用Https接口
     */
    public class WebClientHttpsCase {
        public static void main(String[] args) {
            try {
                /*
                 * 请求有权威证书的地址
                 */
                String requestPath = "https://www.12306.cn/index/";
                WebClient webClient = WebClient.create();
                Mono<String> mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
                System.out.println("get1返回结果:" + mono.block());
                
                /*
                 * 请求自定义证书的地址
                 */
                //获取信任证书库
                KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456");
                
                //不需要客户端证书
                requestPath = "https://10.40.103.48:9010/zsywservice/";
                webClient = WebClient.builder().clientConnector(getClientHttpConnector(trustStore)).build();
                mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
                System.out.println("get2返回结果:" + mono.block());
                
                //需要客户端证书
                requestPath = "https://10.40.103.48:9016/zsywservice/";
                KeyStore keyStore = getkeyStore("pkcs12", "d:/client.p12", "123456");
                webClient = WebClient.builder().clientConnector(getClientHttpConnector(keyStore, "123456", trustStore)).build();
                mono = webClient.get().uri(requestPath).retrieve().bodyToMono(String.class);
                System.out.println("get3返回结果:" + mono.block());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 获取Connector
         * @param keyStore
         * @param password
         * @return
         * @throws Exception
         */
        private static ClientHttpConnector getClientHttpConnector(KeyStore keyStore, String keyStorePassword, KeyStore trustStore) throws Exception {
            SslContextBuilder builder = SslContextBuilder.forClient();
            if (keyStore != null) {
                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
                keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
                builder.keyManager(keyManagerFactory);
            }
            if (trustStore != null) {
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
                trustManagerFactory.init(trustStore);
                builder.trustManager(trustManagerFactory);
            } else {
                builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
            }
            SslContext sslContext = builder.build();
            HttpClient httpClient = HttpClient.create().secure(new Consumer<SslContextSpec>() {
                @Override
                public void accept(SslContextSpec t) {
                    t.sslContext(sslContext).handlerConfigurator(handler -> {
                        SSLEngine engine = handler.engine();
                        List<SNIMatcher> matchers = new LinkedList<SNIMatcher>();
                        SNIMatcher matcher = new SNIMatcher(0) {
                            @Override
                            public boolean matches(SNIServerName serverName) {
                                //if ("xxx".equals(serverName)) {
                                //    return true;
                                //} else {
                                //    return false;
                                //}
                                return true;
                            }
                        };
                        matchers.add(matcher);
                        SSLParameters params = new SSLParameters();
                        params.setSNIMatchers(matchers);
                        engine.setSSLParameters(params);
                    });
                }
            });
            
            ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
            return connector;
        }
        
        private static ClientHttpConnector getClientHttpConnector(KeyStore trustStore) throws Exception {
            return getClientHttpConnector(null, null, trustStore);
        }
        
        /**
         * 获取证书
         * @param type
         * @param filePath
         * @param password
         * @return
         */
        private static KeyStore getkeyStore(String type, String filePath, String password) {
            KeyStore keySotre = null;
            FileInputStream in = null;
            try {
                keySotre = KeyStore.getInstance(type);
                in = new FileInputStream(new File(filePath));
                keySotre.load(in, password.toCharArray());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(in);
            }
            return keySotre;
        }
    }
  • 相关阅读:
    hdu 4474 转化为bfs + 一个巧妙的剪枝~
    数据结构几类排序的总结和完整代码 待续。。
    poj 2135 Farm Tour
    hdu 4374 (单调队列+dp)
    poj2391 Ombrophobic Bovines 拆点连边要注意
    hdu3507
    hdu1506
    poj2175
    poj3308
    poj3155 Hard Life
  • 原文地址:https://www.cnblogs.com/wuyongyin/p/11959240.html
Copyright © 2011-2022 走看看