java非同步呼叫外部介面
阿新 • • 發佈:2020-12-25
通過SpringBoot-RestTemplate方式呼叫
1.RestTemplate工具類
package com.singhand.companyadressredis.main.config; import org.apache.http.impl.client.CloseableHttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.Iterator; import java.util.List; @Configuration public class RestTemplateConfig { @Autowired CloseableHttpClient httpClient; @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory()); return restTemplate; } @Bean public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setHttpClient(httpClient); return clientHttpRequestFactory; } }
上面是通過設定httpClient,我們也可以直接
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory){ return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory(){ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(15000); factory.setReadTimeout(5000); return factory; } }
如果通過httpClient,需要加入httpClient配置,如下
2.httpClient
package com.singhand.companyadressredis.main.config; import com.singhand.sysdev.utils.log4wk.KLog; import com.singhand.sysdev.utils.tools.ExceptionUtils; import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; /** * - Supports both HTTP and HTTPS * - Uses a connection pool to re-use connections and save overhead of creating connections. * - Has a custom connection keep-alive strategy (to apply a default keep-alive if one isn't specified) * - Starts an idle connection monitor to continuously clean up stale connections. */ @Configuration @EnableScheduling public class HttpClientConfig { /* * Determines the timeout in milliseconds until a connection is established * */ private static final int CONNECT_TIMEOUT = 30000; /* * The timeout when requesting a connection from the connection manager */ private static final int REQUEST_TIMEOUT = 30000; /* * The timeout for waiting for data */ private static final int SOCKET_TIMEOUT = 60000; private static final int MAX_TOTAL_CONNECTIONS = 50; private static final int DEFAULT_KEEP_ALIVE_TIME_MILLIS = 20 * 1000; private static final int CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS = 30; @Bean public PoolingHttpClientConnectionManager poolingConnectionManager() { SSLContextBuilder builder = new SSLContextBuilder(); try { builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); } catch (NoSuchAlgorithmException | KeyStoreException e) { KLog.error("poolingConnectionManager Exception","Pooling Connection Manager Initialisation failure because of " + ExceptionUtils.errInfo(e)); } SSLConnectionSocketFactory sslsf = null; try { sslsf = new SSLConnectionSocketFactory(builder.build()); } catch (KeyManagementException | NoSuchAlgorithmException e) { KLog.error("poolingConnectionManager Exception","Pooling Connection Manager Initialisation failure because of " + ExceptionUtils.errInfo(e)); } Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder .<ConnectionSocketFactory>create().register("https", sslsf) .register("http", new PlainConnectionSocketFactory()) .build(); PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); poolingConnectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS); return poolingConnectionManager; } @Bean public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() { return new ConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse response, HttpContext context) { HeaderElementIterator it = new BasicHeaderElementIterator (response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { return Long.parseLong(value) * 1000; } } return DEFAULT_KEEP_ALIVE_TIME_MILLIS; } }; } @Bean public CloseableHttpClient httpClient() { RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(REQUEST_TIMEOUT) .setConnectTimeout(CONNECT_TIMEOUT) .setSocketTimeout(SOCKET_TIMEOUT).build(); return HttpClients.custom() .setDefaultRequestConfig(requestConfig) .setConnectionManager(poolingConnectionManager()) .setKeepAliveStrategy(connectionKeepAliveStrategy()) .build(); } }
3.接下來t通過CompletableFuture非同步呼叫介面
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@Component
public class ReptileUtils {
@Autowired
RestTemplate restTemplate;
public void sendReptile(String keyword){
//CompletableFuture實現非同步呼叫
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
//你自己的邏輯程式碼,通過restTemplate.exchange呼叫外部介面
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
List<ReptileInput> params= new ArrayList<>();
HttpEntity<Object> requestEntity = new HttpEntity<>(params, header);
ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.POST,requestEntity,Object.class);
return response;
}).thenAccept(e->System.out.println(e));//thenAccept介面完成處理結果
}
}