HttpClient入门【简单使用】

前言:最近项目中用到了httpclient,于是乎去学习了一下,但是在实操过程中发现存在很多的问题,踩了很多坑,所以便想着记录下来,以便自己回顾,同时也希望能够帮助有需要的朋友们。
1.HttpClient介绍
要是不了解咱去就问下百度:HttpClient
2.为什么要用到HttpClient
httpclient的使用范围很广泛,不过在我的知识储备中主要是以下两点:

  • 一、使用httpclient写爬虫
  • 二、项目中远程调用服务(咱今天就好好来唠唠)

3.原因
在项目开发中,需要调用另外一个项目的接口,然鹅这个项目不是微服务的系统,用不了SpringCloud的Fegin,,然后再加上知识有限,于是就想到了使用HttpClient.
4.遇到的问题
开始使用的过程中,没啥问题一路通畅,感觉如鱼得水般,后来发现自己太年轻,然后就遇见了一系列的问题:

  • 传参:对象和map参数如何传递
  • 如何上传文件

5.解决问题
常规操作,导入依赖、yml配置、注入spring

<!-- 导入依赖-->
<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.8</version>
 </dependency>
 
<!-- yml的配置:根据自己项目需要来配置-->
#httpclient自定义属性
http:
  maxTotal: 100 #最大连接数
  defaultMaxPerRoute: 50 #并发数
  connectTimeout: 1000 #创建连接的最长时间
  connectionRequestTimeout: 1000  #从连接池中获取到连接的最长时间
  socketTimeout: 1000 #数据传输的最长时间
  staleConnectionCheckEnabled: true #提交请求前测试连接是否可用

配置配,然后注入spring

@Configuration
public class HttpClient {

    @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;

    /**
     * 首先实例化一个连接池管理器,设置最大连接数、并发连接数
     *
     * @return
     */
    @Bean(name = "httpClientConnectionManager")
    public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
        PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
        //最大连接数
        httpClientConnectionManager.setMaxTotal(maxTotal);
        //并发数
        httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        return httpClientConnectionManager;
    }

    /**
     * 实例化连接池,设置连接池管理器。
     * 这里需要以参数形式注入上面实例化的连接池管理器
     *
     * @param httpClientConnectionManager
     * @return
     */
    @Bean(name = "httpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {

        //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) {
        return httpClientBuilder.build();
    }

    /**
     * Builder是RequestConfig的一个内部类
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * 设置builder的连接信息
     * 这里还可以设置proxy,cookieSpec等属性。有需要的话可以在此设置
     *
     * @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();
    }

}

然后就是根据具体的业务操作抽取出一个工具类来,这里我就不贴出来了。接着该解决问题了~
如果你使用的是Post请求,那么有一点一定要注意,那就是数据格式

//JSON格式
post.setHeader("Content-Type", "application/json;charset=utf8");
//普通form表单
post.setHeader("Content-Type", "x-www-form-urlencoded");
//带文件对象的from表单
post.setHeader("Content-Type", "multipart/form-data");
 
//除了在头部设置,也可以在参数对象里面设置
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);

参数为对象的请求(JSON)

    public HttpResult doPostJSON(String url, Object object, String reqHeader) throws Exception {
        // 声明httpPost请求
        HttpPost post = new HttpPost(url);
        // 加入配置信息
        post.setConfig(config);
        post.setHeader("Content-Type", "application/json;charset=utf8");
        post.setHeader("User-Agent", reqHeader);
        String result = null;
        HttpResponse resp = null;
        try {
        	//将object转成StringEntity并且设置UTF-8格式
            StringEntity param = new StringEntity(JSONObject.toJSONString(object),"UTF-8");
            post.setEntity(param);
            //执行请求
            resp = this.httpClient.execute(post);
            if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 返回json格式:
                result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return new HttpResult(resp.getStatusLine().getStatusCode(),result);
    }

参数为Map的请求(JSON)

public HttpResult doPost(String url, Map<String,Object> map,String reqHeader) throws Exception {
        // 声明httpPost请求
        HttpPost post = new HttpPost(url);
        // 加入配置信息
        post.setConfig(config);
        post.setHeader("User-Agent", reqHeader);
        String result = null;
        HttpResponse resp = null;
        try {
            //设置参数
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            Iterator iterator = map.entrySet().iterator();
            while(iterator.hasNext()){
                Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
                list.add(new BasicNameValuePair(elem.getKey(),String.valueOf(elem.getValue())));
            }
            if(list.size() > 0){
            	//将集合封装成UrlEncodedFormEntity设置字符格式
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");
                post.setEntity(entity);
            }
            //执行请求
            resp = this.httpClient.execute(post);
            if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 返回json格式:
                result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return new HttpResult(resp.getStatusLine().getStatusCode(),result);
    }

上传文件

public HttpResult doPostForm(String url, MultipartFile file, Map<String,Object> map,String reqHeader) throws Exception {
        // 声明httpPost请求
        HttpPost post = new HttpPost(url);
        // 加入配置信息
        post.setConfig(config);
        post.setHeader("User-Agent",reqHeader );
        String result = null;
        HttpResponse resp = null;
        try {
            MultipartEntityBuilder builder =  MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(Consts.UTF_8);
            //要上传的文件,以文件流的形式进行传输
            builder.addBinaryBody("file",file.getInputStream(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
            //content-type
            ContentType strContent=ContentType.create("text/plain", Charset.forName("UTF-8"));
            Iterator iterator = map.entrySet().iterator();
            while(iterator.hasNext()){
                Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
                builder.addTextBody(elem.getKey(), elem.getValue(),strContent);
            }
            HttpEntity entity = builder.build();
            post.setEntity(entity);
            //执行请求
            resp = this.httpClient.execute(post);
            if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 返回json格式:
                result = JSONObject.toJSONString(EntityUtils.toString(resp.getEntity()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return new HttpResult(resp.getStatusLine().getStatusCode(),result);
    }

那么说到这里问题也差不多解决了,以上就是本人使用httpClient的简单经历,让我们一起沉浸在bug的海洋里,无法自拔吧~
PS:如有错误或者不正确的地方还请多多指教,一起共同学习共同进步

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值