基于SpringBoot的httpclient实现

avatar
作者
筋斗云
阅读量:0

添加依赖

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>     <parent>         <groupId>com.zzc</groupId>         <artifactId>Demo</artifactId>         <version>1.0-SNAPSHOT</version>     </parent>      <groupId>com.zzc.component</groupId>     <artifactId>component</artifactId>      <properties>         <maven.compiler.source>8</maven.compiler.source>         <maven.compiler.target>8</maven.compiler.target>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>     </properties>      <dependencies> 		 <!-- 公共类、日志依赖等 -->         <!-- <dependency>             <groupId>com.zzc.common</groupId>             <artifactId>common</artifactId>             <version>1.0-SNAPSHOT</version>         </dependency> -->          <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-aop</artifactId>         </dependency>          <!-- springboot中包含了httpclient -->         <dependency>             <groupId>org.apache.httpcomponents</groupId>             <artifactId>httpclient</artifactId>         </dependency>          <dependency>             <groupId>org.projectlombok</groupId>             <artifactId>lombok</artifactId>             <scope>provided</scope>         </dependency>      </dependencies>  </project> 

定义配置类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<String, Integer> keepAliveTargetHost;      /**      * http请求header      */     private Map<String, String> 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<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>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<Header> 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<Map.Entry<String, Integer>> 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<Header> genHeaders() {         List<Header> headers = new ArrayList<>();         if (httpClientProperties.getHeaders() == null) {             log.warn("init header is null");             return headers;         }         for (Map.Entry<String, String> entry : httpClientProperties.getHeaders().entrySet()) {             headers.add(new BasicHeader(entry.getKey(), entry.getValue()));         }         return headers;     }      private void modifyDefaultCharset(RestTemplate restTemplate) {         List<HttpMessageConverter<?>> 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> T post(String url, Map<String, String> header, Object body, Class<T> clazz);      <T> T post(String url, Object body, Class<T> clazz);       <T> T get(String url, Map<String, String> header, Object params, Class<T> clazz);      <T> T get(String url, Object params, Class<T> clazz);      /**      * get请求的文件代理传输等      * @param url      * @param headerMap      * @param extractor      * @return      * @param <T>      */     <T> T transfer(String url, Map<String, String> headerMap, ResponseExtractor<T> 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> T post(String url, Map<String, String> header, Object body, Class<T> clazz) {         log.info("rest post url:{}", url);         Set<Map.Entry<String, String>> entries = header.entrySet();         MultiValueMap<String, String> headers = new HttpHeaders();         for (Map.Entry<String, String> entry : entries) {             List<String> objList = new ArrayList<>();             objList.add(entry.getValue());             headers.put(entry.getKey(), objList);         }          HttpEntity<Map<String, Object>> formEntity = new HttpEntity(body, headers);         ResponseEntity<T> response = restTemplate.postForEntity(url, formEntity, clazz);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public <T> T post(String url, Object body, Class<T> clazz) {         HttpEntity<Map<String, Object>> formEntity = new HttpEntity(body, defaultHeaders());         ResponseEntity<T> response = restTemplate.postForEntity(url, formEntity, clazz);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public <T> T get(String url, Map<String, String> headers, Object params, Class<T> clazz) {          ResponseEntity<T> 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> T get(String url, Object params, Class<T> clazz) {         ResponseEntity<T> response = restTemplate.getForEntity(url, clazz, params);         if (response == null) {             log.error("request error, url:{}", url);             return null;         }         return response.getBody();     }      @Override     public <T> T transfer(String url, Map<String, String> headerMap, ResponseExtractor<T> extractor) {         RequestCallback requestCallback = null;         if (headerMap == null || headerMap.isEmpty()) {             requestCallback = restTemplate.httpEntityCallback(HttpEntity.EMPTY);         } else {             HttpEntity<Map<String, Object>> 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<String, String> defaultHeaders() {         Map<String, String> header = new HashMap<>();         header.put("Content-Type", "application/json;charset=utf-8");         Set<Map.Entry<String, String>> entries = header.entrySet();         MultiValueMap<String, String> headers = new HttpHeaders();         for (Map.Entry<String, String> entry : entries) {             List<String> objList = new ArrayList<>();             objList.add(entry.getValue());             headers.put(entry.getKey(), objList);         }         return headers;     }      private static MultiValueMap<String, String> generateHeader(Map<String, String> headerMap) {         if (headerMap == null || headerMap.isEmpty()) {             return defaultHeaders();         }         MultiValueMap<String, String> headers = new HttpHeaders();         for (Map.Entry<String, String> entry : headerMap.entrySet()) {             List<String> objList = new ArrayList<>();             objList.add(entry.getValue());             headers.put(entry.getKey(), objList);         }         return headers;     } }  

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!