基于SpringBoot的httpclient实现

添加依赖

<?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;
    }
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot ChatGPT是一个基于SpringBoot的聊天应用程序,它使用GPT(生成对抗网络)技术来生成聊天内容。这个应用程序可以让用户与聊天机器人进行交互,聊天机器人可以回答用户的问题、提供建议和进行有趣的对话。 要实现SpringBoot ChatGPT聊天应用程序,需要以下步骤: 1. 准备数据集:GPT需要大量的数据集来进行训练。可以从互联网上收集不同主题的聊天记录,然后将它们转换成合适的格式,以便GPT可以识别和训练。 2. 训练模型:使用所收集的数据集训练GPT模型。这可能需要一些时间和计算资源,因为GPT需要处理大量的数据。训练完成后,可以将模型保存起来以备后续使用。 3. 构建应用程序:使用SpringBoot构建一个Web应用程序,其中包含与用户进行交互的前端界面和与GPT进行通信的后端服务。可以使用开源框架和库来实现这些功能,例如SpringMVC、Thymeleaf和HttpClient。 4. 集成GPT:将训练好的GPT模型集成到应用程序中。可以使用Python和TensorFlow等技术来加载模型并处理用户输入,并将生成的聊天内容返回给用户。 5. 部署应用程序:将应用程序部署到云服务器或本地服务器上,以便用户可以通过互联网或局域网访问该应用程序。 6. 测试和优化:测试应用程序,检查其是否能够正确地与用户进行交互,并查看其性能和可靠性。根据测试结果进行优化,以提高应用程序的质量和用户体验。 总结:SpringBoot ChatGPT聊天应用程序是一种有趣且实用的应用程序,它利用GPT技术为用户提供有趣的对话和有用的信息。要实现该应用程序,需要准备数据集、训练模型、构建应用程序、集成GPT、部署应用程序和测试和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值