添加依赖
4.0.0 com.zzc Demo 1.0-SNAPSHOT com.zzc.component component 8 8 UTF-8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-aop org.apache.httpcomponents httpclient org.projectlombok lombok provided
定义配置类Properties
package com.zzc.component.http; import lombok.Data; import lombok.ToString; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.Map; @Data @ToString @ConfigurationProperties(prefix = "httpclient") public class HttpClientProperties { private String charset = "UTF-8"; /** * 总链接数 */ private Integer connMaxTotal = 3000; /** * 并发数量 */ private Integer maxPerRoute = 1200; /** * 重试次数 */ private Integer retryNum = 1; /** * 链接超时 */ private Integer connectTimeout = 30000; /** * 读写超时 */ private Integer readTimeout = 15000; /** * 链接不够用的等待时间,不宜过长,必须设置 */ private Integer requestTimeout = 200; /** * 默认链接保持时间,单位 秒 */ private Integer keepAliveTime = 60; /** * 如果请求目标地址单独配置可长链接保持时间,使用该配置 */ private Map keepAliveTargetHost; /** * http请求header */ private Map headers; }
初始化httpclient
package com.zzc.component.http; import lombok.extern.slf4j.Slf4j; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpHost; import org.apache.http.client.HttpClient; import org.apache.http.client.protocol.HttpClientContext; 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.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; @Slf4j @Configuration @ConditionalOnClass(value = {RestTemplate.class, CloseableHttpClient.class}) @Import(HttpClientProperties.class) public class HttpClientFactory { private HttpClientProperties httpClientProperties; public HttpClientFactory(HttpClientProperties httpClientProperties) { this.httpClientProperties = httpClientProperties; } @Bean(name = "clientHttpRequestFactory") public ClientHttpRequestFactory clientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory factory = httpComponentsClientHttpRequestFactory(); return factory; } protected HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); factory.setConnectTimeout(httpClientProperties.getConnectTimeout()); factory.setReadTimeout(httpClientProperties.getReadTimeout()); factory.setConnectionRequestTimeout(httpClientProperties.getRequestTimeout()); factory.setHttpClient(httpClient()); return factory; } public HttpClient httpClient() { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); try { Registry registry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()) .build(); PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(registry); httpClientConnectionManager.setMaxTotal(httpClientProperties.getConnMaxTotal()); httpClientConnectionManager.setDefaultMaxPerRoute(httpClientProperties.getMaxPerRoute()); httpClientBuilder.setConnectionManager(httpClientConnectionManager); httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(httpClientProperties.getRetryNum(), httpClientProperties.getRetryNum() != 0)); List headers = genHeaders(); if (headers != null && !headers.isEmpty()) { httpClientBuilder.setDefaultHeaders(headers); } httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy()); //设置定时关闭无效链接 httpClientBuilder.evictIdleConnections(30L, TimeUnit.SECONDS); return httpClientBuilder.build(); } catch (Exception e) { log.error("init http factory error", e); } return null; } private ConnectionKeepAliveStrategy connectionKeepAliveStrategy() { return ((httpResponse, httpContext) -> { HeaderElementIterator it = new BasicHeaderElementIterator(httpResponse.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String name = he.getName(); String value = he.getValue(); if (value != null && "timeout".equalsIgnoreCase(name)) { try { return Long.parseLong(value) * 1000L; } catch (NumberFormatException ignore) { log.error("resolve Keep-Alive timeout", ignore); } } } HttpHost target = (HttpHost) httpContext.getAttribute(HttpClientContext.HTTP_TARGET_HOST); //如果请求的目标地址单独做了配置,使用以下的设置 Optional> any = Optional.ofNullable(httpClientProperties.getKeepAliveTargetHost()) .orElseGet(HashMap::new) .entrySet() .stream() .filter(e -> e.getKey().equalsIgnoreCase(target.getHostName())) .findAny(); int keepAliveTime = httpClientProperties.getKeepAliveTime() == null ? 60 : httpClientProperties.getKeepAliveTime(); return any.map(e -> e.getValue() * 1000L).orElse(keepAliveTime * 1000L); }); } private List genHeaders() { List headers = new ArrayList<>(); if (httpClientProperties.getHeaders() == null) { log.warn("init header is null"); return headers; } for (Map.Entry entry : httpClientProperties.getHeaders().entrySet()) { headers.add(new BasicHeader(entry.getKey(), entry.getValue())); } return headers; } private void modifyDefaultCharset(RestTemplate restTemplate) { List> converterList = restTemplate.getMessageConverters(); HttpMessageConverter> converterTarget = null; for (HttpMessageConverter> item : converterList) { if (StringHttpMessageConverter.class == item.getClass()) { log.info("HttpMessageConvert exist null"); converterTarget = item; break; } } if (null != converterTarget) { converterList.remove(converterTarget); } Charset defaultCharset = Charset.forName(httpClientProperties.getCharset()); converterList.add(1, new StringHttpMessageConverter(defaultCharset)); } private RestTemplate createRestTemplate(ClientHttpRequestFactory clientHttpRequestFactory) { RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory); modifyDefaultCharset(restTemplate); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); return restTemplate; } @Bean(name = "httpClientRestTemplate") public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) { return createRestTemplate(clientHttpRequestFactory); } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
定义接口
package com.zzc.component.http; import org.springframework.web.client.ResponseExtractor; import java.util.Map; public interface RestTemplateComponent { T post(String url, Map header, Object body, Class clazz); T post(String url, Object body, Class clazz); T get(String url, Map header, Object params, Class clazz); T get(String url, Object params, Class clazz); /** * get请求的文件代理传输等 * @param url * @param headerMap * @param extractor * @return * @param */ T transfer(String url, Map headerMap, ResponseExtractor extractor); }
实现接口
package com.zzc.component.http; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RequestCallback; import org.springframework.web.client.ResponseExtractor; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @Slf4j @Component public class RestTemplateComponentImpl implements RestTemplateComponent { @Qualifier("httpClientRestTemplate") @Autowired private RestTemplate restTemplate; @Override public T post(String url, Map header, Object body, Class clazz) { log.info("rest post url:{}", url); Set> entries = header.entrySet(); MultiValueMap headers = new HttpHeaders(); for (Map.Entry entry : entries) { List objList = new ArrayList<>(); objList.add(entry.getValue()); headers.put(entry.getKey(), objList); } HttpEntity
上一篇:网络赛输入flag什么
下一篇:【JavaEE】单例模式