基于SpringBoot的httpclient实现
创始人
2024-11-24 12:37:09
0

添加依赖

      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> formEntity = new HttpEntity(body, headers);         ResponseEntity response = restTemplate.postForEntity(url, formEntity, clazz);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public  T post(String url, Object body, Class clazz) {         HttpEntity> formEntity = new HttpEntity(body, defaultHeaders());         ResponseEntity response = restTemplate.postForEntity(url, formEntity, clazz);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public  T get(String url, Map headers, Object params, Class clazz) {          ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, generateHeader(headers)), clazz, params);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public  T get(String url, Object params, Class clazz) {         ResponseEntity response = restTemplate.getForEntity(url, clazz, params);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public  T transfer(String url, Map headerMap, ResponseExtractor extractor) {         RequestCallback requestCallback = null;         if (headerMap == null || headerMap.isEmpty()) {             requestCallback = restTemplate.httpEntityCallback(HttpEntity.EMPTY);         } else {             HttpEntity> formEntity = new HttpEntity<>(null, generateHeader(headerMap));             requestCallback = restTemplate.httpEntityCallback(formEntity);         }         return restTemplate.execute(url, HttpMethod.GET, requestCallback, extractor);     }       /**      * 如果请求的header,Content-Type=application/x-www-form-urlencoded      * 则需参数接收的载体需要使用 MultiValueMap      * @return      */     private static MultiValueMap defaultHeaders() {         Map header = new HashMap<>();         header.put("Content-Type", "application/json;charset=utf-8");         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);         }         return headers;     }      private static MultiValueMap generateHeader(Map headerMap) {         if (headerMap == null || headerMap.isEmpty()) {             return defaultHeaders();         }         MultiValueMap headers = new HttpHeaders();         for (Map.Entry entry : headerMap.entrySet()) {             List objList = new ArrayList<>();             objList.add(entry.getValue());             headers.put(entry.getKey(), objList);         }         return headers;     } }  

相关内容

热门资讯

一分钟教你!广东雀神外 挂(一... 一分钟教你!广东雀神外 挂(一贯真的是有挂)详细透视辅助教程1.广东雀神外 挂 ai辅助创建新账号,...
微扑克辅助器ios!微扑克网页... 微扑克辅助器ios!微扑克网页版辅助,微扑克真的有挂存在(都是真的是有挂);无聊就玩这款微扑克真的有...
重大来袭!都莱罗松(本来真的是... 重大来袭!都莱罗松(本来真的是有挂)详细透视辅助教程1、打开软件启动之后找到中间准星的标志长按。2、...
微扑克辅助软件!微扑克有挂(透... 微扑克辅助软件!微扑克有挂(透明挂)好像是有挂1、微扑克系统规律教程、微扑克辅助透视等服务,为用户提...
玩家必知教程!金州水鱼辅助工具... 玩家必知教程!金州水鱼辅助工具(一贯是真的有挂)详细辅助教程所有人都在同一条线上,像星星一样排成一排...
最新技巧!!福建众娱软件有没有... 最新技巧!!福建众娱软件有没有辅助(透明挂)透明挂透视辅助脚本(2023已更新)(哔哩哔哩);福建众...
科普分享!心悦填大坑总输怎么回... 科普分享!心悦填大坑总输怎么回事(确实有挂)详细透视辅助教程1、心悦填大坑总输怎么回事系统规律教程、...
分享认知!柳州天天爱麻将有挂吗... 分享认知!柳州天天爱麻将有挂吗(透视)透明挂透视辅助脚本(2023已更新)(哔哩哔哩);1、金币登录...
记者揭秘!衢州都莱十三道辅助器... 记者揭秘!衢州都莱十三道辅助器(切实是有挂)详细辅助教程1、衢州都莱十三道辅助器ai机器人多个强度级...
玩家必知教程!!卡农斗牛辅助最... 玩家必知教程!!卡农斗牛辅助最新版本(透视)透视脚本辅助插件(2021已更新)(哔哩哔哩)运卡农斗牛...