HttpClient的使用

HttpClient的作用:
现在的互联网大型项目采用的都是分布式部署,各个模块都有各个模块的服务器,这些资源之间的相互访问就需要借助http协议,HttpClient就是用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包.
首先导包

<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>

HttpClient的使用步骤

	public void testGet() throws ClientProtocolException, IOException {
		String url = "https://www.baidu.com";        //1..确定要访问的url地址,这里访问百度
		HttpGet get = new HttpGet(url);						  //2..确定访问方式get/post
		HttpClient htClient = HttpClients.createDefault(); //3..实例化一个HttpClient对象
		HttpResponse response = htClient.execute(get);		      //4..发起请求,获取响应
		if(200 == response.getStatusLine().getStatusCode()) {      //5..判断返回状态信息
			String result = EntityUtils.toString(response.getEntity(),"utf-8");
			System.out.println(result);      		        	 //6..对返回信息做出处理
		}
	}

SpringBoot整合HttpClient

package com.jt.config;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@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){

		//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的连接信息
	 * @return
	 */
	@SuppressWarnings("deprecation")
	@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();
	}
}

配置文件

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

自动清理不被使用的连接

package com.jt.config;

import javax.annotation.PreDestroy;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@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) {
			notifyAll(); //全部从等待中唤醒.执行关闭操作;
		}
	}
}

这个时候,再写一个util工具类,简化拿取HttpClient 的过程.

package com.jt.util;

import java.io.IOException;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jt.Util.ObjectMapperUtil;

@Configuration
public class HttpClientService {
	@Autowired
	private CloseableHttpClient htClient;//从池中获取连接
	@Autowired
	private RequestConfig requestConfig; //控制请求超时时间
	public String Client(String url,Map<String,String> params,String Charset) {
		if(StringUtils.isEmpty(Charset)) {
			Charset="UTF-8";
		}		
		if(params!=null) {
			url +="?";
			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 get = new HttpGet(url);
		get.setConfig(requestConfig);
		//4..发起请求获取结果
		String result=null;
		try {
			HttpResponse response = htClient.execute(get);
			if(200 == response.getStatusLine().getStatusCode()) {
			result=	EntityUtils.toString
					(response.getEntity(),Charset);
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return result;		
	}
	
	
	public String Client(String url) {
		
		return  Client(url,null,null);
	}
	public String Client(String url,String Charset) {	
		return  Client(url,null,Charset);
	}
	public String Client(String url,Map<String, String>params) {	
		return  Client(url,params,null);
	}
	public <T> T Client(String url,Map<String,String> params,Class<T> targetClass,String charset) {
		String result = Client(url,params);
		return ObjectMapperUtil.getObject(result, targetClass);
	}
	public <T> T Client(String url,Class<T> targetClass) {
		String result = Client(url);
		return ObjectMapperUtil.getObject(result, targetClass);
	}

} 

最后,测试一下

	@Autowired
	private HttpClientService Client;
	@Test
	public void test03() {
		String url = "http://www.baidu.com";
		String result = Client.Client(url);
		System.out.println(result);
	}


完美.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值