基于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;     } }  

相关内容

热门资讯

黑科技好牌(微扑克app)外挂... 黑科技好牌(微扑克app)外挂透明挂辅助黑科技(透视)最初真的是有挂(有挂技巧)-哔哩哔哩;1、黑科...
黑科技辅助(pokerist)... 黑科技辅助(pokerist)外挂透明挂辅助挂(透视)2025新版技巧(2021已更新)(哔哩哔哩)...
黑科技辅助!德州之星辅助器哪里... 黑科技辅助!德州之星辅助器哪里买(透视)一向真的有挂(有挂技术)-哔哩哔哩;是一款可以让一直输的玩家...
黑科技辅助!微扑克有机器人(透... 您好,微扑克有机器人这款游戏可以开挂的,确实是有挂的,需要了解加微【136704302】很多玩家在这...
黑科技ai代打(德扑之星工具)... 黑科技ai代打(德扑之星工具)外挂透明挂辅助下载(透视)往昔真的有挂(有挂助手)-哔哩哔哩是一款可以...
黑科技辅助(we-poker)... 黑科技辅助(we-poker)外挂透明挂辅助神器(透视)插件教程(2022已更新)(哔哩哔哩)是一款...
黑科技辅助!wepoke透明挂... 【福星临门,好运相随】;黑科技辅助!wepoke透明挂是真的(透视)软件透明挂ai辅助安装(真是有挂...
黑科技辅助!wpk有挂(透视)... 黑科技辅助!wpk有挂(透视)一向真的是有挂(有挂秘笈)-哔哩哔哩;wpk有挂软件透明挂是一个全新上...
黑科技实锤(德扑之星发牌机制)... 黑科技实锤(德扑之星发牌机制)外挂透明挂辅助黑科技(透视)好像是有挂(有人有挂)-哔哩哔哩;人气非常...
黑科技辅助(wEPoke)外挂... 黑科技辅助(wEPoke)外挂透明挂辅助安装(透视)规律教程(2023已更新)(哔哩哔哩)相信很多朋...