SpringBoot整合HttpClient

一、编辑httpClient.properties配置文件

#最大连接数
http.maxTotal=1000
#并发数
http.defaultMaxPerRoute=20
#创建连接的最长时间
http.connectTimeout=5000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=5000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true

二、 编辑HttpClient的配置类

@Configuration
@PropertySource(value = "classpath:/properties/httpClient.properties")
public class HttpClientConfig {
    @Value("${http.maxTotal}")
    private Integer maxTotal;                        //最大连接数

    @Value("${http.defaultMaxPerRoute}")
    private Integer defaultMaxPerRoute;                //最大并发链接数

    @Value("${http.connectTimeout}")
    private Integer connectTimeout;                    //创建链接的最大时间

    @Value("${http.connectionRequestTimeout}")
    private Integer connectionRequestTimeout;        //链接获取超时时间

    @Value("${http.socketTimeout}")
    private Integer socketTimeout;                    //数据传输最长时间

    @Value("${http.staleConnectionCheckEnabled}")
    private boolean staleConnectionCheckEnabled;    //提交时检查链接是否可用

    //定义httpClient链接池
    @Bean(name = "httpClientConnectionManager")
    public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
        manager.setMaxTotal(maxTotal);  //设定最大链接数
        manager.setDefaultMaxPerRoute(defaultMaxPerRoute);  //设定并发链接数
        return manager;
    }

    //定义HttpClient

    /**
     * 实例化连接池,设置连接池管理器。
     * 这里需要以参数形式注入上面实例化的连接池管理器
     *
     * @Qualifier 指定bean标签进行注入
     */
    @Bean(name = "httpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
        //将池对象交给builder
        //HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(httpClientConnectionManager);
        return httpClientBuilder;
    }

    /**
     * 注入连接池,用于获取httpClient
     *
     * @param httpClientBuilder
     * @return
     */
    @Bean
    public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
        //利用builder对象动态获取链接对象
        return httpClientBuilder.build();
    }

    /**
     * Builder是RequestConfig的一个内部类
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * 设置builder的连接信息
     *
     * @return
     */
    @Bean(name = "builder")
    public RequestConfig.Builder getBuilder() {
        RequestConfig.Builder builder = RequestConfig.custom();
        return builder.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout)
                .setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
    }

    /**
     * 使用builder构建一个RequestConfig对象
     *
     * @param builder
     * @return
     */
    @Bean
    public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
        return builder.build();
    }
}

 三、定义关闭链接操作

@Component    //交给spring容器管理,定期将超时的链接关闭
public class HttpClientClose extends Thread {
    @Autowired
    private PoolingHttpClientConnectionManager manage;
    private volatile boolean shutdown;    //开关 volatitle表示多线程可变数据,一个线程修改,其他线程立即修改

    public HttpClientClose() {
        ///System.out.println("执行构造方法,实例化对象");
        //线程开启启动
        this.start();
    }

    @Override
    public void run() {
        try {
            //如果服务没有关闭,执行线程
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);            //等待5秒
                    //System.out.println("线程开始执行,关闭超时链接");
                    //关闭超时的链接
                    PoolStats stats = manage.getTotalStats();
                    int av = stats.getAvailable();    //获取可用的线程数量
                    int pend = stats.getPending();    //获取阻塞的线程数量
                    int lea = stats.getLeased();    //获取当前正在使用的链接数量
                    int max = stats.getMax();
                    //System.out.println("max/"+max+":	av/"+av+":  pend/"+pend+":   lea/"+lea);
                    manage.closeExpiredConnections();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        super.run();
    }

    //关闭清理无效连接的线程
    @PreDestroy    //容器关闭时执行该方法.
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            //System.out.println("关闭全部链接!!");
            notifyAll(); //全部从等待中唤醒.执行关闭操作;
        }
    }
}

四、编辑HttpClient工具API

/**
 * 需求:能否编辑一个HttpClientAPI,简化程序远程调用的过程
 * 简化策略:
 * 用户使用:传递参数
 * 结果:远程访问的返回值
 * 参数说明:
 * arg0:url地址,arg1:Map<key,value> 封装参数,arg2:指定字符集编码
 */
@Service
public class HttpClientService {
    @Autowired
    private CloseableHttpClient httpClient;
    @Autowired
    private RequestConfig requestConfig;

    public String doGet(String url, Map<String, String> params, String charset) {
        String result = null;
        //1.判断字符集编码是否为空 如果为空则给定默认值utf-8
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }
        //2.判断用户是否需要传递参数
        if (params != null) {
            url += "?";//需要进行参数的拼接.将Map集合遍历,动态获取key=value
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                url += key + "=" + value + "&";//拼接参数
            }
            url = url.substring(0, url.length() - 1);//去除多有的&符
        }

        //3.定义参数提交对象
        HttpGet httpGet = new HttpGet(url);

        //4.为请求设定超时时间
        httpGet.setConfig(requestConfig);

        //5.通过httpClient发送请求
        try {
            HttpResponse httpResponse = httpClient.execute(httpGet);
            //判断状态码是否正确
            if(httpResponse.getStatusLine().getStatusCode()==200){
                HttpEntity entity = httpResponse.getEntity();
                //注意字符集编码格式
                result = EntityUtils.toString(entity,charset);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return result;
    }

    public String doGet(String url) {
        return doGet(url, null, null);
    }

    public String doGet(String url, Map<String, String> params) {
        return doGet(url, params, null);
    }

    public String doGet(String url, String charset) {
        return doGet(url, null, charset);
    }

    //实现httpClient POST提交
    public String doPost(String url, Map<String, String> params, String charset) {
        String result = null;

        //1.定义请求类型
        HttpPost post = new HttpPost(url);
        post.setConfig(requestConfig);    //定义超时时间

        //2.判断字符集是否为null
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }

        //3.判断用户是否传递参数
        if (params != null) {
            //3.2准备List集合信息
            List<NameValuePair> parameters = new ArrayList<>();

            //3.3将数据封装到List集合中
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }

            //3.1模拟表单提交
            try {
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, charset); //采用u8编码

                //3.4将实体对象封装到请求对象中
                post.setEntity(formEntity);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        //4.发送请求
        try {
            CloseableHttpResponse response = httpClient.execute(post);

            //4.1判断返回值状态
            if (response.getStatusLine().getStatusCode() == 200) {

                //4.2表示请求成功
                result = EntityUtils.toString(response.getEntity(), charset);
            } else {
                System.out.println("获取状态码信息:" + response.getStatusLine().getStatusCode());
                throw new RuntimeException();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return result;
    }


    public String doPost(String url) {
        return doPost(url, null, null);
    }

    public String doPost(String url, Map<String, String> params) {
        return doPost(url, params, null);
    }

    public String doPost(String url, String charset) {
        return doPost(url, null, charset);
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值